device.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. werrstr("open %s: %r", name);
  36. if(d->ctl >= 0)
  37. close(d->ctl);
  38. free(d);
  39. /* return nil; */
  40. sysfatal("%r");
  41. }
  42. id = readnum(d->ctl);
  43. isnew = 1;
  44. }
  45. sprint(name, "/dev/usb%d/%d/", ctlrno, id);
  46. p = name+strlen(name);
  47. if(!isnew) {
  48. strcpy(p, "ctl");
  49. if((d->ctl = open(name, ORDWR)) < 0)
  50. goto Error0;
  51. }
  52. strcpy(p, "setup");
  53. if((d->setup = open(name, ORDWR)) < 0){
  54. Error1:
  55. if(d->setup >= 0)
  56. close(d->setup);
  57. goto Error0;
  58. }
  59. strcpy(p, "status");
  60. if((d->status = open(name, OREAD)) < 0)
  61. goto Error1;
  62. d->ctlrno = ctlrno;
  63. d->id = id;
  64. d->ep[0] = newendpt(d, 0, 0);
  65. return d;
  66. }
  67. void
  68. closedev(Device *d)
  69. {
  70. int i;
  71. if(d==nil)
  72. return;
  73. if(decref(d) != 0)
  74. return;
  75. close(d->ctl);
  76. close(d->setup);
  77. close(d->status);
  78. for(i=0; i<nelem(d->ep); i++)
  79. free(d->ep[i]);
  80. free(d);
  81. }
  82. void
  83. setdevclass(Device *d, int n)
  84. {
  85. Endpt *e;
  86. if((e = d->ep[n]) == nil)
  87. return;
  88. if (verbose) fprint(2, "class %d %d %#6.6lux %d %#4.4ux %#4.4ux\n",
  89. d->nif, n, e->csp, e->maxpkt, d->vid, d->did);
  90. fprint(d->ctl, "class %d %d %#6.6lux %d %#4.4ux %#4.4ux",
  91. d->nif, n, e->csp, e->maxpkt, d->vid, d->did);
  92. }
  93. int
  94. describedevice(Device *d)
  95. {
  96. DDevice *dd;
  97. byte buf[24]; /* length field is one byte */
  98. int nr;
  99. werrstr("");
  100. if(debugdebug)
  101. fprint(2, "describedevice\n");
  102. if(setupreq(d->ep[0], RD2H|Rstandard|Rdevice, GET_DESCRIPTOR,
  103. DEVICE<<8|0, 0, sizeof buf) < 0){
  104. fprint(2, "%s: describedevice: error writing usb device "
  105. "request: get device descriptor: %r\n", argv0);
  106. return -1;
  107. }
  108. if((nr = setupreply(d->ep[0], buf, sizeof buf)) < 8) {
  109. fprint(2, "%s: describedevice: error reading usb device "
  110. "descriptor, got %d of %d: %r\n",
  111. argv0, nr, DDEVLEN);
  112. return -1;
  113. }
  114. /* extract gubbins */
  115. pdesc(d, -1, -1, buf, nr);
  116. dd = (DDevice*)buf;
  117. d->csp = CSP(dd->bDeviceClass, dd->bDeviceSubClass, dd->bDeviceProtocol);
  118. d->ep[0]->maxpkt = dd->bMaxPacketSize0;
  119. if (dd->bDeviceClass == 9)
  120. d->class = Hubclass;
  121. else
  122. d->class = Otherclass;
  123. if(nr >= DDEVLEN){
  124. d->nconf = dd->bNumConfigurations;
  125. d->vid = GET2(dd->idVendor);
  126. d->did = GET2(dd->idProduct);
  127. }else
  128. fprint(2, "%s: describedevice: short usb device descriptor\n",
  129. argv0);
  130. return 0;
  131. }
  132. int
  133. loadconfig(Device *d, int n)
  134. {
  135. byte buf[1023];
  136. int nr = -1, len;
  137. if(debugdebug)
  138. fprint(2, "loadconfig\n");
  139. if (setupreq(d->ep[0], RD2H|Rstandard|Rdevice, GET_DESCRIPTOR,
  140. CONFIGURATION<<8|n, 0, sizeof buf) < 0 ||
  141. (nr = setupreply(d->ep[0], buf, sizeof buf)) < 1) {
  142. fprint(2, "%s: error reading usb configuration descriptor: "
  143. "read %d bytes: %r\n", argv0, nr);
  144. return -1;
  145. }
  146. if (buf[1] == CONFIGURATION) {
  147. len = GET2(((DConfig*)buf)->wTotalLength);
  148. if (len < nr)
  149. nr = len;
  150. }
  151. /* extract gubbins */
  152. pdesc(d, n, -1, buf, nr);
  153. return 0;
  154. }
  155. Endpt *
  156. newendpt(Device *d, int id, ulong csp)
  157. {
  158. Endpt *e;
  159. e = mallocz(sizeof(*e), 1);
  160. e->id = id;
  161. e->dev = d;
  162. e->csp = csp;
  163. e->maxpkt = 32;
  164. return e;
  165. }