dev.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  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. /*
  14. * epN.M -> N
  15. */
  16. static int
  17. nameid(char *s)
  18. {
  19. char *r;
  20. char nm[20];
  21. r = strrchr(s, 'p');
  22. if(r == nil)
  23. return -1;
  24. strecpy(nm, nm+sizeof(nm), r+1);
  25. r = strchr(nm, '.');
  26. if(r == nil)
  27. return -1;
  28. *r = 0;
  29. return atoi(nm);
  30. }
  31. Dev*
  32. openep(Dev *d, int id)
  33. {
  34. char *mode; /* How many modes? */
  35. Ep *ep;
  36. Altc *ac;
  37. Dev *epd;
  38. Usbdev *ud;
  39. char name[40];
  40. if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)
  41. return nil;
  42. if(d->cfd < 0 || d->usb == nil){
  43. werrstr("device not configured");
  44. return nil;
  45. }
  46. ud = d->usb;
  47. if(id < 0 || id >= nelem(ud->ep) || ud->ep[id] == nil){
  48. werrstr("bad enpoint number");
  49. return nil;
  50. }
  51. ep = ud->ep[id];
  52. mode = "rw";
  53. if(ep->dir == Ein)
  54. mode = "r";
  55. if(ep->dir == Eout)
  56. mode = "w";
  57. snprint(name, sizeof(name), "/dev/usb/ep%d.%d", d->id, id);
  58. if(access(name, AEXIST) == 0){
  59. dprint(2, "%s: %s already exists; trying to open\n", argv0, name);
  60. epd = opendev(name);
  61. if(epd != nil)
  62. epd->maxpkt = ep->maxpkt; /* guess */
  63. return epd;
  64. }
  65. if(devctl(d, "new %d %d %s", id, ep->type, mode) < 0){
  66. dprint(2, "%s: %s: new: %r\n", argv0, d->dir);
  67. return nil;
  68. }
  69. epd = opendev(name);
  70. if(epd == nil)
  71. return nil;
  72. epd->id = id;
  73. if(devctl(epd, "maxpkt %d", ep->maxpkt) < 0)
  74. fprint(2, "%s: %s: openep: maxpkt: %r\n", argv0, epd->dir);
  75. else
  76. dprint(2, "%s: %s: maxpkt %d\n", argv0, epd->dir, ep->maxpkt);
  77. epd->maxpkt = ep->maxpkt;
  78. ac = ep->iface->altc[0];
  79. if(ep->ntds > 1 && devctl(epd, "ntds %d", ep->ntds) < 0)
  80. fprint(2, "%s: %s: openep: ntds: %r\n", argv0, epd->dir);
  81. else
  82. dprint(2, "%s: %s: ntds %d\n", argv0, epd->dir, ep->ntds);
  83. /*
  84. * For iso endpoints and high speed interrupt endpoints the pollival is
  85. * actually 2ⁿ and not n.
  86. * The kernel usb driver must take that into account.
  87. * It's simpler this way.
  88. */
  89. if(ac != nil && (ep->type == Eintr || ep->type == Eiso) && ac->interval != 0)
  90. if(devctl(epd, "pollival %d", ac->interval) < 0)
  91. fprint(2, "%s: %s: openep: pollival: %r\n", argv0, epd->dir);
  92. return epd;
  93. }
  94. Dev*
  95. opendev(char *fn)
  96. {
  97. Dev *d;
  98. int l;
  99. if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)
  100. return nil;
  101. d = emallocz(sizeof(Dev), 1);
  102. incref(&d->Ref);
  103. l = strlen(fn);
  104. d->dfd = -1;
  105. /*
  106. * +30 to allocate extra size to concat "/<epfilename>"
  107. * we should probably remove that feature from the manual
  108. * and from the code after checking out that nobody relies on
  109. * that.
  110. */
  111. d->dir = emallocz(l + 30, 0);
  112. strcpy(d->dir, fn);
  113. strcpy(d->dir+l, "/ctl");
  114. d->cfd = open(d->dir, ORDWR|OCEXEC);
  115. d->dir[l] = 0;
  116. d->id = nameid(fn);
  117. if(d->cfd < 0){
  118. werrstr("can't open endpoint %s: %r", d->dir);
  119. free(d->dir);
  120. free(d);
  121. return nil;
  122. }
  123. dprint(2, "%s: opendev %#p %s\n", argv0, d, fn);
  124. return d;
  125. }
  126. int
  127. opendevdata(Dev *d, int mode)
  128. {
  129. char buf[80]; /* more than enough for a usb path */
  130. seprint(buf, buf+sizeof(buf), "%s/data", d->dir);
  131. d->dfd = open(buf, mode|OCEXEC);
  132. return d->dfd;
  133. }
  134. enum
  135. {
  136. /*
  137. * Max device conf is also limited by max control request size as
  138. * limited by Maxctllen in the kernel usb.h (both limits are arbitrary).
  139. */
  140. Maxdevconf = 4 * 1024, /* asking for 16K kills Newsham's disk */
  141. };
  142. int
  143. loaddevconf(Dev *d, int n)
  144. {
  145. uint8_t *buf;
  146. int nr;
  147. int type;
  148. if(n >= nelem(d->usb->conf)){
  149. werrstr("loaddevconf: bug: out of configurations in device");
  150. fprint(2, "%s: %r\n", argv0);
  151. return -1;
  152. }
  153. buf = emallocz(Maxdevconf, 0);
  154. type = Rd2h|Rstd|Rdev;
  155. nr = usbcmd(d, type, Rgetdesc, Dconf<<8|n, 0, buf, Maxdevconf);
  156. if(nr < Dconflen){
  157. free(buf);
  158. return -1;
  159. }
  160. if(d->usb->conf[n] == nil)
  161. d->usb->conf[n] = emallocz(sizeof(Conf), 1);
  162. nr = parseconf(d->usb, d->usb->conf[n], buf, nr);
  163. free(buf);
  164. return nr;
  165. }
  166. Ep*
  167. mkep(Usbdev *d, int id)
  168. {
  169. Ep *ep;
  170. d->ep[id] = ep = emallocz(sizeof(Ep), 1);
  171. ep->id = id;
  172. return ep;
  173. }
  174. static char*
  175. mkstr(uint8_t *b, int n)
  176. {
  177. Rune r;
  178. char *us;
  179. char *s;
  180. char *e;
  181. if(n <= 2 || (n & 1) != 0)
  182. return strdup("none");
  183. n = (n - 2)/2;
  184. b += 2;
  185. us = s = emallocz(n*UTFmax+1, 0);
  186. e = s + n*UTFmax+1;
  187. for(; --n >= 0; b += 2){
  188. r = GET2(b);
  189. s = seprint(s, e, "%C", r);
  190. }
  191. return us;
  192. }
  193. char*
  194. loaddevstr(Dev *d, int sid)
  195. {
  196. uint8_t buf[128];
  197. int type;
  198. int nr;
  199. if(sid == 0)
  200. return estrdup("none");
  201. type = Rd2h|Rstd|Rdev;
  202. nr=usbcmd(d, type, Rgetdesc, Dstr<<8|sid, 0, buf, sizeof(buf));
  203. return mkstr(buf, nr);
  204. }
  205. int
  206. loaddevdesc(Dev *d)
  207. {
  208. uint8_t buf[Ddevlen+255];
  209. int nr;
  210. int type;
  211. Ep *ep0;
  212. type = Rd2h|Rstd|Rdev;
  213. nr = sizeof(buf);
  214. memset(buf, 0, Ddevlen);
  215. if((nr=usbcmd(d, type, Rgetdesc, Ddev<<8|0, 0, buf, nr)) < 0)
  216. return -1;
  217. /*
  218. * Several hubs are returning descriptors of 17 bytes, not 18.
  219. * We accept them and leave number of configurations as zero.
  220. * (a get configuration descriptor also fails for them!)
  221. */
  222. if(nr < Ddevlen){
  223. print("%s: %s: warning: device with short descriptor\n",
  224. argv0, d->dir);
  225. if(nr < Ddevlen-1){
  226. werrstr("short device descriptor (%d bytes)", nr);
  227. return -1;
  228. }
  229. }
  230. d->usb = emallocz(sizeof(Usbdev), 1);
  231. ep0 = mkep(d->usb, 0);
  232. ep0->dir = Eboth;
  233. ep0->type = Econtrol;
  234. ep0->maxpkt = d->maxpkt = 8; /* a default */
  235. nr = parsedev(d, buf, nr);
  236. if(nr >= 0){
  237. d->usb->vendor = loaddevstr(d, d->usb->vsid);
  238. if(strcmp(d->usb->vendor, "none") != 0){
  239. d->usb->product = loaddevstr(d, d->usb->psid);
  240. d->usb->serial = loaddevstr(d, d->usb->ssid);
  241. }
  242. }
  243. return nr;
  244. }
  245. int
  246. configdev(Dev *d)
  247. {
  248. int i;
  249. if(d->dfd < 0)
  250. opendevdata(d, ORDWR);
  251. if(loaddevdesc(d) < 0)
  252. return -1;
  253. for(i = 0; i < d->usb->nconf; i++)
  254. if(loaddevconf(d, i) < 0)
  255. return -1;
  256. return 0;
  257. }
  258. static void
  259. closeconf(Conf *c)
  260. {
  261. int i;
  262. int a;
  263. if(c == nil)
  264. return;
  265. for(i = 0; i < nelem(c->iface); i++)
  266. if(c->iface[i] != nil){
  267. for(a = 0; a < nelem(c->iface[i]->altc); a++)
  268. free(c->iface[i]->altc[a]);
  269. free(c->iface[i]);
  270. }
  271. free(c);
  272. }
  273. void
  274. closedev(Dev *d)
  275. {
  276. int i;
  277. Usbdev *ud;
  278. if(d==nil || decref(&d->Ref) != 0)
  279. return;
  280. dprint(2, "%s: closedev %#p %s\n", argv0, d, d->dir);
  281. if(d->free != nil)
  282. d->free(d->aux);
  283. if(d->cfd >= 0)
  284. close(d->cfd);
  285. if(d->dfd >= 0)
  286. close(d->dfd);
  287. d->cfd = d->dfd = -1;
  288. free(d->dir);
  289. d->dir = nil;
  290. ud = d->usb;
  291. d->usb = nil;
  292. if(ud != nil){
  293. free(ud->vendor);
  294. free(ud->product);
  295. free(ud->serial);
  296. for(i = 0; i < nelem(ud->ep); i++)
  297. free(ud->ep[i]);
  298. for(i = 0; i < nelem(ud->ddesc); i++)
  299. free(ud->ddesc[i]);
  300. for(i = 0; i < nelem(ud->conf); i++)
  301. closeconf(ud->conf[i]);
  302. free(ud);
  303. }
  304. free(d);
  305. }
  306. static char*
  307. reqstr(int type, int req)
  308. {
  309. char *s;
  310. static char* ds[] = { "dev", "if", "ep", "oth" };
  311. static char buf[40];
  312. if(type&Rd2h)
  313. s = seprint(buf, buf+sizeof(buf), "d2h");
  314. else
  315. s = seprint(buf, buf+sizeof(buf), "h2d");
  316. if(type&Rclass)
  317. s = seprint(s, buf+sizeof(buf), "|cls");
  318. else if(type&Rvendor)
  319. s = seprint(s, buf+sizeof(buf), "|vnd");
  320. else
  321. s = seprint(s, buf+sizeof(buf), "|std");
  322. s = seprint(s, buf+sizeof(buf), "|%s", ds[type&3]);
  323. switch(req){
  324. case Rgetstatus: s = seprint(s, buf+sizeof(buf), " getsts"); break;
  325. case Rclearfeature: s = seprint(s, buf+sizeof(buf), " clrfeat"); break;
  326. case Rsetfeature: s = seprint(s, buf+sizeof(buf), " setfeat"); break;
  327. case Rsetaddress: s = seprint(s, buf+sizeof(buf), " setaddr"); break;
  328. case Rgetdesc: s = seprint(s, buf+sizeof(buf), " getdesc"); break;
  329. case Rsetdesc: s = seprint(s, buf+sizeof(buf), " setdesc"); break;
  330. case Rgetconf: s = seprint(s, buf+sizeof(buf), " getcnf"); break;
  331. case Rsetconf: s = seprint(s, buf+sizeof(buf), " setcnf"); break;
  332. case Rgetiface: s = seprint(s, buf+sizeof(buf), " getif"); break;
  333. case Rsetiface: s = seprint(s, buf+sizeof(buf), " setif"); break;
  334. }
  335. USED(s);
  336. return buf;
  337. }
  338. static int
  339. cmdreq(Dev *d, int type, int req, int value, int index, uint8_t *data,
  340. int count)
  341. {
  342. int ndata, n;
  343. uint8_t *wp;
  344. uint8_t buf[8];
  345. char *hd, *rs;
  346. assert(d != nil);
  347. if(data == nil){
  348. wp = buf;
  349. ndata = 0;
  350. }else{
  351. ndata = count;
  352. wp = emallocz(8+ndata, 0);
  353. }
  354. wp[0] = type;
  355. wp[1] = req;
  356. PUT2(wp+2, value);
  357. PUT2(wp+4, index);
  358. PUT2(wp+6, count);
  359. if(data != nil)
  360. memmove(wp+8, data, ndata);
  361. if(usbdebug>2){
  362. hd = hexstr(wp, ndata+8);
  363. rs = reqstr(type, req);
  364. fprint(2, "%s: %s val %d|%d idx %d cnt %d out[%d] %s\n",
  365. d->dir, rs, value>>8, value&0xFF,
  366. index, count, ndata+8, hd);
  367. free(hd);
  368. }
  369. n = write(d->dfd, wp, 8+ndata);
  370. if(wp != buf)
  371. free(wp);
  372. if(n < 0)
  373. return -1;
  374. if(n != 8+ndata){
  375. dprint(2, "%s: cmd: short write: %d\n", argv0, n);
  376. return -1;
  377. }
  378. return n;
  379. }
  380. static int
  381. cmdrep(Dev *d, void *buf, int nb)
  382. {
  383. char *hd;
  384. nb = read(d->dfd, buf, nb);
  385. if(nb >0 && usbdebug > 2){
  386. hd = hexstr(buf, nb);
  387. fprint(2, "%s: in[%d] %s\n", d->dir, nb, hd);
  388. free(hd);
  389. }
  390. return nb;
  391. }
  392. int
  393. usbcmd(Dev *d, int type, int req, int value, int index, uint8_t *data,
  394. int count)
  395. {
  396. int i, r, nerr;
  397. char err[64];
  398. /*
  399. * Some devices do not respond to commands some times.
  400. * Others even report errors but later work just fine. Retry.
  401. */
  402. r = -1;
  403. *err = 0;
  404. for(i = nerr = 0; i < Uctries; i++){
  405. if(type & Rd2h)
  406. r = cmdreq(d, type, req, value, index, nil, count);
  407. else
  408. r = cmdreq(d, type, req, value, index, data, count);
  409. if(r > 0){
  410. if((type & Rd2h) == 0)
  411. break;
  412. r = cmdrep(d, data, count);
  413. if(r > 0)
  414. break;
  415. if(r == 0)
  416. werrstr("no data from device");
  417. }
  418. nerr++;
  419. if(*err == 0)
  420. rerrstr(err, sizeof(err));
  421. sleep(Ucdelay);
  422. }
  423. if(r > 0 && i >= 2)
  424. /* let the user know the device is not in good shape */
  425. fprint(2, "%s: usbcmd: %s: required %d attempts (%s)\n",
  426. argv0, d->dir, i, err);
  427. return r;
  428. }
  429. int
  430. unstall(Dev *dev, Dev *ep, int dir)
  431. {
  432. int r;
  433. if(dir == Ein)
  434. dir = 0x80;
  435. else
  436. dir = 0;
  437. r = Rh2d|Rstd|Rep;
  438. if(usbcmd(dev, r, Rclearfeature, Fhalt, ep->id|dir, nil, 0)<0){
  439. werrstr("unstall: %s: %r", ep->dir);
  440. return -1;
  441. }
  442. if(devctl(ep, "clrhalt") < 0){
  443. werrstr("clrhalt: %s: %r", ep->dir);
  444. return -1;
  445. }
  446. return 0;
  447. }
  448. /*
  449. * To be sure it uses a single write.
  450. */
  451. int
  452. devctl(Dev *dev, char *fmt, ...)
  453. {
  454. char buf[128];
  455. va_list arg;
  456. char *e;
  457. va_start(arg, fmt);
  458. e = vseprint(buf, buf+sizeof(buf), fmt, arg);
  459. va_end(arg);
  460. return write(dev->cfd, buf, e-buf);
  461. }