dev.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. * Framework for USB devices.
  3. * Some of them may be embedded into usbd and some of
  4. * them may exist as /bin/usb/* binaries on their own.
  5. *
  6. * When embedded, devmain() is given a ref of an already
  7. * configured and open Dev. If devmain()
  8. * does not fail it should release this ref when done and
  9. * use incref to add further refs to it.
  10. */
  11. #include <u.h>
  12. #include <libc.h>
  13. #include <thread.h>
  14. #include "usb.h"
  15. #include "usbd.h"
  16. static Lock masklck;
  17. extern Devtab devtab[];
  18. static char* cputype;
  19. int
  20. getdevnb(uvlong *maskp)
  21. {
  22. int i;
  23. lock(&masklck);
  24. for(i = 0; i < 8 * sizeof *maskp; i++)
  25. if((*maskp & (1ULL<<i)) == 0){
  26. *maskp |= 1ULL<<i;
  27. unlock(&masklck);
  28. return i;
  29. }
  30. unlock(&masklck);
  31. return -1;
  32. }
  33. void
  34. putdevnb(uvlong *maskp, int id)
  35. {
  36. lock(&masklck);
  37. if(id >= 0)
  38. *maskp &= ~(1ULL<<id);
  39. unlock(&masklck);
  40. }
  41. static int
  42. cspmatch(Devtab *dt, int dcsp)
  43. {
  44. int i;
  45. int csp;
  46. for(i = 0; i < nelem(dt->csps); i++)
  47. if((csp=dt->csps[i]) != 0)
  48. if(csp == dcsp)
  49. return 1;
  50. else if((csp&DCL) && (csp&~DCL) == Class(dcsp))
  51. return 1;
  52. return 0;
  53. }
  54. static int
  55. devmatch(Devtab *dt, Usbdev *d)
  56. {
  57. int i;
  58. int c;
  59. Conf *cp;
  60. if(dt->noauto)
  61. return 0;
  62. if(dt->vid != -1 && d->vid != dt->vid)
  63. return 0;
  64. if(dt->did != -1 && d->did != dt->did)
  65. return 0;
  66. if(cspmatch(dt, d->csp))
  67. return 1;
  68. for(c = 0; c < Nconf; c++)
  69. if((cp=d->conf[c]) != nil)
  70. for(i = 0; i < Niface; i++)
  71. if(cp->iface[i] != nil)
  72. if(cspmatch(dt, cp->iface[i]->csp))
  73. return 1;
  74. return 0;
  75. }
  76. /* We can't use procexec to execute drivers, because
  77. * procexec mounts #| at /mnt/temp and we do *not*
  78. * have /mnt/temp at boot time.
  79. * Instead, we use access to guess if we can execute the file.
  80. * and reply as procexec. Be careful that the child inherits
  81. * all the shared state of the thread library. It should run unnoticed.
  82. */
  83. static void
  84. xexec(Channel *c, char *nm, char *args[])
  85. {
  86. int pid;
  87. if(access(nm, AEXEC) == 0){
  88. pid = rfork(RFFDG|RFREND|RFPROC);
  89. switch(pid){
  90. case 0:
  91. exec(nm, args);
  92. _exits("exec");
  93. case -1:
  94. break;
  95. default:
  96. sendul(c, pid);
  97. threadexits(nil);
  98. }
  99. }
  100. }
  101. typedef struct Sarg Sarg;
  102. struct Sarg{
  103. Port *pp;
  104. Devtab* dt;
  105. Channel*rc;
  106. char fname[80];
  107. char args[128];
  108. char *argv[40];
  109. };
  110. static void
  111. startdevproc(void *a)
  112. {
  113. Sarg *sa = a;
  114. Dev *d;
  115. Devtab *dt;
  116. int argc;
  117. char *args, *argse, **argv;
  118. char *fname;
  119. threadsetgrp(threadid());
  120. d = sa->pp->dev;
  121. dt = sa->dt;
  122. args = sa->args;
  123. argse = sa->args + sizeof sa->args;
  124. argv = sa->argv;
  125. fname = sa->fname;
  126. sa->pp->devmaskp = &dt->devmask;
  127. sa->pp->devnb = getdevnb(&dt->devmask);
  128. if(sa->pp->devnb < 0){
  129. sa->pp->devmaskp = nil;
  130. sa->pp->devnb = 0;
  131. }else
  132. args = seprint(args, argse, "-N %d", sa->pp->devnb);
  133. if(dt->args != nil)
  134. seprint(args, argse, " %s", dt->args);
  135. args = sa->args;
  136. dprint(2, "%s: start: %s %s\n", argv0, dt->name, args);
  137. argv[0] = dt->name;
  138. argc = 1;
  139. if(args[0] != 0)
  140. argc += tokenize(args, argv+1, nelem(sa->argv)-2);
  141. argv[argc] = nil;
  142. if(dt->init == nil){
  143. if(d->dfd > 0 ){
  144. close(d->dfd);
  145. d->dfd = -1;
  146. }
  147. rfork(RFCFDG);
  148. open("/dev/null", OREAD);
  149. open("/dev/cons", OWRITE);
  150. open("/dev/cons", OWRITE);
  151. xexec(sa->rc, argv[0], argv);
  152. snprint(fname, sizeof(sa->fname), "/bin/usb/%s", dt->name);
  153. xexec(sa->rc, fname, argv);
  154. snprint(fname, sizeof(sa->fname), "/boot/%s", dt->name);
  155. xexec(sa->rc, fname, argv);
  156. if(cputype == nil)
  157. cputype = getenv("cputype");
  158. if(cputype != nil){
  159. snprint(fname, sizeof(sa->fname), "/%s/bin/%s",
  160. cputype, dt->name);
  161. argv[0] = fname;
  162. xexec(sa->rc, fname, argv);
  163. }
  164. fprint(2, "%s: %s: not found. can't exec\n", argv0, dt->name);
  165. sendul(sa->rc, -1);
  166. threadexits("exec");
  167. }else{
  168. sa->pp->dev = opendev(d->dir);
  169. sendul(sa->rc, 0);
  170. if(dt->init(d, argc, argv) < 0)
  171. fprint(2, "%s: %s: %r\n", argv0, dt->name);
  172. closedev(d);
  173. free(sa);
  174. }
  175. threadexits(nil);
  176. }
  177. static void
  178. writeinfo(Dev *d)
  179. {
  180. char buf[128];
  181. char *s;
  182. char *se;
  183. Usbdev *ud;
  184. Conf *c;
  185. Iface *ifc;
  186. int i, j;
  187. ud = d->usb;
  188. s = buf;
  189. se = buf+sizeof(buf);
  190. s = seprint(s, se, "info %s csp %#08ulx", classname(ud->class), ud->csp);
  191. for(i = 0; i < ud->nconf; i++){
  192. c = ud->conf[i];
  193. if(c == nil)
  194. break;
  195. for(j = 0; j < nelem(c->iface); j++){
  196. ifc = c->iface[j];
  197. if(ifc == nil)
  198. break;
  199. if(ifc->csp != ud->csp)
  200. s = seprint(s, se, " csp %#08ulx", ifc->csp);
  201. }
  202. }
  203. s = seprint(s, se, " vid %06#x did %06#x", ud->vid, ud->did);
  204. seprint(s, se, " %q %q", ud->vendor, ud->product);
  205. devctl(d, "%s", buf);
  206. }
  207. int
  208. startdev(Port *pp)
  209. {
  210. Dev *d;
  211. Usbdev *ud;
  212. Devtab *dt;
  213. Sarg *sa;
  214. Channel *rc;
  215. d = pp->dev;
  216. assert(d);
  217. ud = d->usb;
  218. assert(ud != nil);
  219. writeinfo(d);
  220. if(ud->class == Clhub){
  221. /*
  222. * Hubs are handled directly by this process avoiding
  223. * concurrent operation so that at most one device
  224. * has the config address in use.
  225. * We cancel kernel debug for these eps. too chatty.
  226. */
  227. pp->hub = newhub(d->dir, d);
  228. if(pp->hub == nil)
  229. fprint(2, "%s: %s: %r\n", argv0, d->dir);
  230. else
  231. fprint(2, "usb/hub... ");
  232. if(usbdebug > 1)
  233. devctl(d, "debug 0"); /* polled hubs are chatty */
  234. return pp->hub == nil ? -1 : 0;
  235. }
  236. for(dt = devtab; dt->name != nil; dt++)
  237. if(devmatch(dt, ud))
  238. break;
  239. /*
  240. * From here on the device is for the driver.
  241. * When we return pp->dev contains a Dev just for us
  242. * with only the ctl open. Both devs are released on the last closedev:
  243. * driver's upon I/O errors and ours upon port dettach.
  244. */
  245. if(dt->name == nil){
  246. dprint(2, "%s: no configured entry for %s (csp %#08lx)\n",
  247. argv0, d->dir, ud->csp);
  248. close(d->dfd);
  249. d->dfd = -1;
  250. return 0;
  251. }
  252. sa = emallocz(sizeof(Sarg), 1);
  253. sa->pp = pp;
  254. sa->dt = dt;
  255. rc = sa->rc = chancreate(sizeof(ulong), 1);
  256. procrfork(startdevproc, sa, Stack, RFNOTEG);
  257. if(recvul(rc) != 0)
  258. free(sa);
  259. chanfree(rc);
  260. fprint(2, "usb/%s... ", dt->name);
  261. sleep(Spawndelay); /* in case we re-spawn too fast */
  262. return 0;
  263. }