devs.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <thread.h>
  12. #include <usb/usb.h>
  13. typedef struct Parg Parg;
  14. enum {
  15. Ndevs = 32,
  16. Arglen = 500,
  17. Nargs = 64,
  18. Stack = 16 * 1024,
  19. };
  20. struct Parg {
  21. char* args;
  22. Dev* dev;
  23. int (*f)(Dev*,int,char**);
  24. Channel*rc;
  25. };
  26. static void
  27. workproc(void *a)
  28. {
  29. Parg *pa;
  30. char args[Arglen];
  31. char *argv[Nargs];
  32. int argc;
  33. Channel *rc;
  34. Dev *d;
  35. int (*f)(Dev*,int,char**);
  36. pa = a;
  37. threadsetname("workproc %s", pa->dev->dir);
  38. strecpy(args, args+sizeof(args), pa->args); /* don't leak */
  39. d = pa->dev;
  40. f = pa->f;
  41. rc = pa->rc;
  42. free(pa->args);
  43. free(pa);
  44. argc = tokenize(args, argv, nelem(argv)-1);
  45. argv[argc] = nil;
  46. if(f(d, argc, argv) < 0){
  47. closedev(d);
  48. fprint(2, "%s: devmain: %r\n", argv0);
  49. sendul(rc, -1);
  50. threadexits("devmain: %r");
  51. }
  52. sendul(rc, 0);
  53. threadexits(nil);
  54. }
  55. int
  56. matchdevcsp(char *info, void *a)
  57. {
  58. char sbuf[40];
  59. int *csps;
  60. csps = a;
  61. for(; *csps != 0; csps++){
  62. snprint(sbuf, sizeof(sbuf), "csp %#08x", *csps);
  63. if(strstr(info, sbuf) != nil)
  64. return 0;
  65. }
  66. return -1;
  67. }
  68. int
  69. finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs)
  70. {
  71. int fd, i, n, nd, nr;
  72. char *nm;
  73. char dbuf[512], fbuf[40];
  74. Dir *d;
  75. fd = open("/dev/usb", OREAD);
  76. if(fd < 0)
  77. sysfatal("/dev/usb: %r");
  78. nd = dirreadall(fd, &d);
  79. close(fd);
  80. if(nd < 2)
  81. sysfatal("/dev/usb: no devs");
  82. for(i = n = 0; i < nd && n < ndirs; i++){
  83. nm = d[i].name;
  84. if(strcmp(nm, "ctl") == 0 || strstr(nm, ".0") == nil)
  85. continue;
  86. snprint(fbuf, sizeof(fbuf), "/dev/usb/%s/ctl", nm);
  87. fd = open(fbuf, OREAD);
  88. if(fd < 0)
  89. continue; /* may be gone */
  90. nr = read(fd, dbuf, sizeof(dbuf)-1);
  91. close(fd);
  92. if(nr < 0)
  93. continue;
  94. dbuf[nr] = 0;
  95. if(strstr(dbuf, "enabled ") != nil && strstr(dbuf, " busy") == nil)
  96. if(matchf(dbuf, farg) == 0)
  97. dirs[n++] = smprint("/dev/usb/%s", nm);
  98. }
  99. free(d);
  100. if(usbdebug > 1)
  101. for(nd = 0; nd < n; nd++)
  102. fprint(2, "finddevs: %s\n", dirs[nd]);
  103. return n;
  104. }
  105. void
  106. startdevs(char *args, char *argv[], int argc, int (*mf)(char*, void*),
  107. void *ma, int (*df)(Dev*, int, char**))
  108. {
  109. int i, ndirs, ndevs;
  110. char *dirs[Ndevs];
  111. char **dp;
  112. Parg *parg;
  113. Dev *dev;
  114. Channel *rc;
  115. if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)
  116. sysfatal("#u: %r");
  117. if(argc > 0){
  118. ndirs = argc;
  119. dp = argv;
  120. }else{
  121. dp = dirs;
  122. ndirs = finddevs(mf, ma, dp, Ndevs);
  123. if(ndirs == nelem(dirs))
  124. fprint(2, "%s: too many devices\n", argv0);
  125. }
  126. ndevs = 0;
  127. rc = chancreate(sizeof(uint32_t), 0);
  128. if(rc == nil)
  129. sysfatal("no memory");
  130. for(i = 0; i < ndirs; i++){
  131. fprint(2, "%s: startdevs: opening #%d %s\n", argv0, i, dp[i]);
  132. dev = opendev(dp[i]);
  133. if(dev == nil)
  134. fprint(2, "%s: %s: %r\n", argv0, dp[i]);
  135. else if(configdev(dev) < 0){
  136. fprint(2, "%s: %s: config: %r\n", argv0, dp[i]);
  137. closedev(dev);
  138. }else{
  139. dprint(2, "%s: %U", argv0, dev);
  140. parg = emallocz(sizeof(Parg), 0);
  141. parg->args = estrdup(args);
  142. parg->dev = dev;
  143. parg->rc = rc;
  144. parg->f = df;
  145. proccreate(workproc, parg, Stack);
  146. if(recvul(rc) == 0)
  147. ndevs++;
  148. }
  149. if(dp != argv)
  150. free(dirs[i]);
  151. }
  152. chanfree(rc);
  153. if(ndevs == 0)
  154. sysfatal("no unhandled devices found");
  155. }