usbd.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "usb.h"
  5. #include "dat.h"
  6. #include "fns.h"
  7. #define STACKSIZE 128*1024
  8. static int dontfork;
  9. Ref busy;
  10. int debug;
  11. typedef struct Enum Enum;
  12. struct Enum
  13. {
  14. Hub *hub;
  15. int port;
  16. };
  17. void (*dprinter[])(Device *, int, ulong, void *b, int n) = {
  18. [STRING] pstring,
  19. [DEVICE] pdevice,
  20. [0x29] phub,
  21. };
  22. static void
  23. usage(void)
  24. {
  25. fprint(2, "usage: usbd\n");
  26. threadexitsall("usage");
  27. }
  28. void
  29. work(void *a)
  30. {
  31. int port;
  32. Hub *hub;
  33. Enum *arg;
  34. hub = a;
  35. for (port = 1; port <= hub->nport; port++) {
  36. if (debug)
  37. fprint(2, "enumerate port %H.%d\n", hub, port);
  38. arg = emallocz(sizeof(Enum), 1);
  39. arg->hub = hub;
  40. arg->port = port;
  41. incref(&busy);
  42. threadcreate(enumerate, arg, STACKSIZE);
  43. }
  44. decref(&busy);
  45. for(;;) {
  46. yield();
  47. if (busy.ref == 0)
  48. sleep(2000);
  49. }
  50. }
  51. void
  52. threadmain(int argc, char **argv)
  53. {
  54. int i;
  55. Hub *h;
  56. ARGBEGIN{
  57. case 'f':
  58. dontfork=1;
  59. break;
  60. case 'd':
  61. debug++;
  62. break;
  63. case 'v':
  64. verbose = 1;
  65. break;
  66. }ARGEND
  67. if (argc)
  68. usage();
  69. if (access("/dev/usb0", 0) < 0 && bind("#U", "/dev", MAFTER) < 0)
  70. sysfatal("%s: can't bind #U after /dev: %r\n", argv0);
  71. usbfmtinit();
  72. fmtinstall('H', Hfmt);
  73. /* always fork off usb[1—n] */
  74. for(i=1; (h = roothub(i)) != nil; i++) {
  75. incref(&busy);
  76. proccreate(work, h, STACKSIZE);
  77. }
  78. /* usb0 might be handled in this proc */
  79. if((h = roothub(0)) != nil){
  80. incref(&busy);
  81. if (dontfork) {
  82. work(h);
  83. } else {
  84. rfork(RFNOTEG);
  85. proccreate(work, h, STACKSIZE);
  86. /* don't hold window open */
  87. close(0);
  88. close(1);
  89. if(!debug && !verbose)
  90. close(2);
  91. }
  92. }
  93. if (debug)
  94. fprint(2, "done\n");
  95. while (busy.ref)
  96. sleep(100);
  97. threadexits(nil);
  98. }
  99. void
  100. enumerate(void *v)
  101. {
  102. int i, port;
  103. Device *d;
  104. Enum *arg;
  105. Hub *h, *nh;
  106. arg = v;
  107. h = arg->hub;
  108. port = arg->port;
  109. free(arg);
  110. for (;;) {
  111. if((portstatus(h, port) & (1<<PORT_CONNECTION)) == 0) {
  112. decref(&busy);
  113. if (verbose)
  114. fprint(2, "usbd: %H: port %d empty\n", h, port);
  115. do {
  116. yield();
  117. if (debugdebug)
  118. fprint(2, "usbd: probing %H.%d\n",
  119. h, port);
  120. sleep(500);
  121. } while((portstatus(h, port) & (1<<PORT_CONNECTION)) == 0);
  122. incref(&busy);
  123. }
  124. if(verbose)
  125. fprint(2, "usbd: %H: port %d attached\n", h, port);
  126. d = configure(h, port);
  127. if(d == nil) {
  128. if(verbose)
  129. fprint(2, "usbd: can't configure port %H.%d\n", h, port);
  130. decref(&busy);
  131. threadexits("configure");
  132. }
  133. if(d->class == Hubclass) {
  134. if(debug)
  135. fprint(2, "usbd: %H.%d: hub %d attached\n",
  136. h, port, d->id);
  137. setconfig(d, 1);
  138. nh = newhub(h, d);
  139. if(nh == nil) {
  140. detach(h, port);
  141. decref(&busy);
  142. threadexits("describehub");
  143. }
  144. if(debug)
  145. fprint(2, "usbd: traversing hub %H\n", nh);
  146. /* TO DO: initialise status endpoint */
  147. for(i=1; i<=nh->nport; i++)
  148. portpower(nh, i, 1);
  149. sleep(nh->pwrms);
  150. for(i=1; i<=nh->nport; i++) {
  151. arg = emallocz(sizeof(Enum), 1);
  152. arg->hub = nh;
  153. arg->port = i;
  154. incref(&busy);
  155. threadcreate(enumerate, arg, STACKSIZE);
  156. }
  157. }else{
  158. if(debug)
  159. fprint(2,
  160. "usbd: %H.%d: %d: not hub, %s speed\n",
  161. h, port, d->id, d->ls?"low":"high");
  162. setconfig(d, 1); /* TO DO */
  163. //unconscionable kludge (testing camera)
  164. if(d->class == 10) setup0(d, RH2D|Rinterface, SET_INTERFACE, 10, 0, 0);
  165. }
  166. decref(&busy);
  167. while(portstatus(h, port) & (1<<PORT_CONNECTION)) {
  168. if (debugdebug)
  169. fprint(2, "checking %H.%d\n", h, port);
  170. yield();
  171. if (d->state == Detached) {
  172. if (verbose)
  173. fprint(2,
  174. "%H: port %d detached by parent hub\n",
  175. h, port);
  176. /* parent hub died */
  177. threadexits(nil);
  178. }
  179. }
  180. if(verbose)
  181. fprint(2, "%H: port %d detached\n", h, port);
  182. detach(h, port);
  183. }
  184. }
  185. Device*
  186. configure(Hub *h, int port)
  187. {
  188. Port *p;
  189. Device *d;
  190. int i, s, maxpkt, ls;
  191. portenable(h, port, 1);
  192. sleep(20);
  193. portreset(h, port);
  194. sleep(20);
  195. s = portstatus(h, port);
  196. if (debug)
  197. fprint(2, "%H.%d status %#ux\n", h, port, s);
  198. if ((s & (1<<PORT_CONNECTION)) == 0)
  199. return nil;
  200. if ((s & (1<<PORT_SUSPEND)) == 0) {
  201. if (debug)
  202. fprint(2, "enabling port %H.%d\n", h, port);
  203. portenable(h, port, 1);
  204. s = portstatus(h, port);
  205. if (debug)
  206. fprint(2, "%H.%d status now %#ux\n", h, port, s);
  207. }
  208. ls = (s & (1<<PORT_LOW_SPEED)) != 0;
  209. devspeed(h->dev0, ls);
  210. maxpkt = getmaxpkt(h->dev0);
  211. if(maxpkt < 0) {
  212. Error0:
  213. portenable(h, port, 0);
  214. return nil;
  215. }
  216. d = opendev(h->ctlrno, -1);
  217. d->ls = ls;
  218. d->state = Enabled;
  219. d->ep[0]->maxpkt = maxpkt;
  220. if(fprint(d->ctl, "maxpkt 0 %d", maxpkt) < 0) {
  221. Error1:
  222. closedev(d);
  223. goto Error0;
  224. }
  225. if(setaddress(h->dev0, d->id) < 0)
  226. goto Error1;
  227. d->state = Assigned;
  228. devspeed(d, ls);
  229. if(describedevice(d) < 0)
  230. goto Error1;
  231. /* read configurations 0 to n */
  232. for(i=0; i<d->nconf; i++) {
  233. if(d->config[i] == nil)
  234. d->config[i] = mallocz(sizeof(*d->config[i]),1);
  235. loadconfig(d, i);
  236. }
  237. for(i=0; i<16; i++)
  238. setdevclass(d, i);
  239. p = &h->port[port-1];
  240. p->d = d;
  241. return d;
  242. }
  243. void
  244. detach(Hub *h, int port)
  245. {
  246. Port *p;
  247. Device *d;
  248. p = &h->port[port-1];
  249. if(p->hub != nil) {
  250. freehub(p->hub);
  251. p->hub = nil;
  252. }
  253. d = p->d;
  254. d->state = Detached; /* return i/o error on access */
  255. closedev(d);
  256. }