device.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "usb.h"
  5. static int
  6. readnum(int fd)
  7. {
  8. char buf[20];
  9. int n;
  10. for(;;){
  11. n = read(fd, buf, sizeof buf);
  12. if (n < 0){
  13. rerrstr(buf, sizeof buf);
  14. if (strcmp(buf, "interrupted") != 0)
  15. break;
  16. } else
  17. break;
  18. }
  19. buf[sizeof(buf)-1] = 0;
  20. return n <= 0? -1: strtol(buf, nil, 0);
  21. }
  22. Device*
  23. opendev(int ctlrno, int id)
  24. {
  25. int isnew;
  26. Device *d;
  27. char name[100], *p;
  28. d = emallocz(sizeof(Device), 1);
  29. incref(d);
  30. isnew = 0;
  31. if(id == -1) {
  32. sprint(name, "/dev/usb%d/new", ctlrno);
  33. if((d->ctl = open(name, ORDWR)) < 0){
  34. Error0:
  35. close(d->ctl);
  36. werrstr("open %s: %r", name);
  37. free(d);
  38. /* return nil; */
  39. sysfatal("%r");
  40. }
  41. id = readnum(d->ctl);
  42. isnew = 1;
  43. }
  44. sprint(name, "/dev/usb%d/%d/", ctlrno, id);
  45. p = name+strlen(name);
  46. if(!isnew) {
  47. strcpy(p, "ctl");
  48. if((d->ctl = open(name, ORDWR)) < 0)
  49. goto Error0;
  50. }
  51. strcpy(p, "setup");
  52. if((d->setup = open(name, ORDWR)) < 0){
  53. Error1:
  54. close(d->setup);
  55. goto Error0;
  56. }
  57. strcpy(p, "status");
  58. if((d->status = open(name, OREAD)) < 0)
  59. goto Error1;
  60. d->ctlrno = ctlrno;
  61. d->id = id;
  62. d->ep[0] = newendpt(d, 0, 0);
  63. return d;
  64. }
  65. void
  66. closedev(Device *d)
  67. {
  68. int i;
  69. if(d==nil)
  70. return;
  71. if(decref(d) != 0)
  72. return;
  73. close(d->ctl);
  74. close(d->setup);
  75. close(d->status);
  76. for(i=0; i<nelem(d->ep); i++)
  77. free(d->ep[i]);
  78. free(d);
  79. }
  80. void
  81. setdevclass(Device *d, int n)
  82. {
  83. Endpt *e;
  84. if (e = d->ep[n]) {
  85. if (verbose) fprint(2, "class %d %d %#6.6lux\n",
  86. d->nif, n, e->csp);
  87. fprint(d->ctl, "class %d %d %#6.6lux",
  88. d->nif, n, e->csp);
  89. }
  90. }
  91. int
  92. describedevice(Device *d)
  93. {
  94. DDevice *dd;
  95. byte buf[1023];
  96. int nr = -1;
  97. if (setupreq(d->ep[0], RD2H|Rstandard|Rdevice, GET_DESCRIPTOR, (DEVICE<<8)|0, 0, sizeof(buf)) < 0 ||
  98. (nr = setupreply(d->ep[0], buf, sizeof(buf))) < DDEVLEN) {
  99. fprint(2, "usb: error reading device descriptor, got %d of %d\n",
  100. nr, DDEVLEN);
  101. return -1;
  102. }
  103. /* extract gubbins */
  104. pdesc(d, -1, -1, buf, nr);
  105. dd = (DDevice*)buf;
  106. d->csp = CSP(dd->bDeviceClass, dd->bDeviceSubClass, dd->bDeviceProtocol);
  107. d->ep[0]->maxpkt = dd->bMaxPacketSize0;
  108. if (dd->bDeviceClass == 9)
  109. d->class = Hubclass;
  110. else
  111. d->class = Otherclass;
  112. d->nconf = dd->bNumConfigurations;
  113. d->vid = GET2(dd->idVendor);
  114. d->did = GET2(dd->idProduct);
  115. return 0;
  116. }
  117. int
  118. loadconfig(Device *d, int n)
  119. {
  120. byte buf[1023];
  121. int nr, len;
  122. if (setupreq(d->ep[0], RD2H|Rstandard|Rdevice, GET_DESCRIPTOR, (CONFIGURATION<<8)|n, 0, sizeof(buf)) < 0 ||
  123. (nr = setupreply(d->ep[0], buf, sizeof(buf))) < 1) {
  124. fprint(2, "usb: error reading configuration descriptor\n");
  125. return -1;
  126. }
  127. if (buf[1] == CONFIGURATION) {
  128. len = GET2(((DConfig*)buf)->wTotalLength);
  129. if (len < nr)
  130. nr = len;
  131. }
  132. /* extract gubbins */
  133. pdesc(d, n, -1, buf, nr);
  134. return 0;
  135. }
  136. Endpt *
  137. newendpt(Device *d, int id, ulong csp)
  138. {
  139. Endpt *e;
  140. e = mallocz(sizeof(*e), 1);
  141. e->id = id;
  142. e->dev = d;
  143. e->csp = csp;
  144. e->maxpkt = 32;
  145. return e;
  146. }