usb.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  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 "usb.h"
  12. enum {
  13. /* fundamental constants */
  14. Uctries = 4, /* no. of tries for usbcmd */
  15. Ucdelay = 50, /* delay before retrying */
  16. /* request type */
  17. Rh2d = 0<<7, /* host to device */
  18. Rd2h = 1<<7, /* device to host */
  19. Rstd = 0<<5, /* types */
  20. Rclass = 1<<5,
  21. Rvendor = 2<<5,
  22. Rdevice = 0, /* recipients */
  23. Riface = 1,
  24. Rendpt = 2, /* endpoint */
  25. Rother = 3,
  26. /* standard requests */
  27. Rgetstatus = 0,
  28. Rclearfeature = 1,
  29. Rsetfeature = 3,
  30. Rsetaddress = 5,
  31. Rgetdesc = 6, // set/get descriptor (addressed with type and index)
  32. Rsetdesc = 7,
  33. Rgetconf = 8, // set/get configuration (1 byte)
  34. Rsetconf = 9,
  35. Rgetiface = 10, // set/get interface(index) + alt setting(value) (1 byte)
  36. Rsetiface = 11,
  37. Rsynchframe = 12,
  38. Rgetcur = 0x81,
  39. Rgetmin = 0x82,
  40. Rgetmax = 0x83,
  41. Rgetres = 0x84,
  42. Rsetcur = 0x01,
  43. Rsetmin = 0x02,
  44. Rsetmax = 0x03,
  45. Rsetres = 0x04,
  46. /* dev classes */
  47. Clnone = 0, /* not in usb */
  48. Claudio = 1,
  49. Clcomms = 2,
  50. Clhid = 3,
  51. Clprinter = 7,
  52. Clstorage = 8,
  53. Clhub = 9,
  54. Cldata = 10,
  55. /* standard descriptor sizes */
  56. Ddevicelen = 18,
  57. Dconfiglen = 9,
  58. Difacelen = 9,
  59. Dendptlen = 7,
  60. /* descriptor types */
  61. Ddevice = 1,
  62. Dconfig = 2,
  63. Dstring = 3,
  64. Diface = 4,
  65. Dendpt = 5,
  66. Dreport = 0x22,
  67. Dfunction = 0x24,
  68. Dphysical = 0x23,
  69. /* feature selectors */
  70. Fdevremotewakeup = 1,
  71. Fhalt = 0,
  72. /* device state */
  73. Detached = 0,
  74. Attached,
  75. Enabled,
  76. Assigned,
  77. Configured,
  78. /* endpoint direction */
  79. Ein = 0,
  80. Eout,
  81. Eboth,
  82. /* endpoint type */
  83. Econtrol = 0,
  84. Eiso = 1,
  85. Ebulk = 2,
  86. Eintr = 3,
  87. /* endpoint isotype */
  88. Eunknown = 0,
  89. Easync = 1,
  90. Eadapt = 2,
  91. Esync = 3,
  92. /* config attrib */
  93. Cbuspowered = 1<<7,
  94. Cselfpowered = 1<<6,
  95. Cremotewakeup = 1<<5,
  96. /* report types */
  97. Tmtype = 3<<2,
  98. Tmitem = 0xF0,
  99. Tmain = 0<<2,
  100. Tinput = 0x80,
  101. Toutput = 0x90,
  102. Tfeature = 0xB0,
  103. Tcoll = 0xA0,
  104. Tecoll = 0xC0,
  105. Tglobal = 1<<2,
  106. Tusagepage = 0x00,
  107. Tlmin = 0x10,
  108. Tlmax = 0x20,
  109. Tpmin = 0x30,
  110. Tpmax = 0x40,
  111. Tunitexp = 0x50,
  112. Tunit = 0x60,
  113. Trepsize = 0x70,
  114. TrepID = 0x80,
  115. Trepcount = 0x90,
  116. Tpush = 0xA0,
  117. Tpop = 0xB0,
  118. Tlocal = 2<<2,
  119. Tusage = 0x00,
  120. Tumin = 0x10,
  121. Tumax = 0x20,
  122. Tdindex = 0x30,
  123. Tdmin = 0x40,
  124. Tdmax = 0x50,
  125. Tsindex = 0x70,
  126. Tsmin = 0x80,
  127. Tsmax = 0x90,
  128. Tsetdelim = 0xA0,
  129. Treserved = 3<<2,
  130. Tint32_t = 0xFE,
  131. };
  132. typedef struct Usbdevdesc Usbdevdesc;
  133. typedef struct Usbconfdesc Usbconfdesc;
  134. typedef struct Usbstringdesc0 Usbstringdesc0;
  135. typedef struct Usbstringdesc Usbstringdesc;
  136. typedef struct Usbifacedesc Usbifacedesc;
  137. typedef struct Usbendptdesc Usbendptdesc;
  138. struct Usbdevdesc {
  139. uint8_t bLength;
  140. uint8_t bDescriptorType;
  141. // Device Descriptor (0x01, Ddevice)
  142. uint8_t bcdUSB[2];
  143. // USB Specification Number which device complies too.
  144. uint8_t bDeviceClass;
  145. /* Class Code (Assigned by USB Org)
  146. * 0x00: each interface specifies it’s own class code
  147. * 0xFF, the class code is vendor specified.
  148. * Otherwise field is valid Class Code. */
  149. uint8_t bDeviceSubClass;
  150. // Subclass Code (Assigned by USB Org)
  151. uint8_t bDeviceProtocol;
  152. // Protocol Code (Assigned by USB Org)
  153. uint8_t bMaxPacketSize;
  154. // Valid Sizes are 8, 16, 32, 64
  155. uint8_t idVendor[2];
  156. uint8_t idProduct[2];
  157. uint8_t bcDdeviceice[2];
  158. uint8_t iManufacturer;
  159. uint8_t iProduct;
  160. uint8_t iSerialNumber;
  161. uint8_t bNumConfigurations;
  162. };
  163. struct Usbconfdesc {
  164. uint8_t bLength;
  165. uint8_t bDescriptorType;
  166. // Configuration Descriptor (0x02, Dconfig)
  167. uint8_t wTotalLength[2];
  168. // Total length in bytes of data returned
  169. uint8_t bNumInterfaces;
  170. // Number of Interfaces
  171. uint8_t bConfigurationValue;
  172. // Value to use as an argument to select this configuration
  173. uint8_t iConfiguration;
  174. // Index of String Descriptor describing this configuration
  175. uint8_t bmAttributes;
  176. /* D7 Reserved, set to 1. (USB 1.0 Bus Powered)
  177. * D6 Self Powered
  178. * D5 Remote Wakeup
  179. * D4..0 Reserved, set to 0. */
  180. uint8_t bMaxPower;
  181. // Maximum Power Consumption in 2mA units
  182. };
  183. struct Usbstringdesc0 {
  184. uint8_t bLength;
  185. // Size of Descriptor in Bytes
  186. uint8_t bDescriptorType;
  187. // String Descriptor (0x03, Dstring)
  188. uint8_t wLANGID0[2];
  189. // Supported Language Code Zero. bLength indicates how many wLANGIDs there are.
  190. };
  191. struct Usbstringdesc {
  192. uint8_t bLength;
  193. // Size of Descriptor in Bytes
  194. uint8_t bDescriptorType;
  195. // String Descriptor (0x03, Dstring)
  196. uint8_t bString[1];
  197. // Unicode Encoded String
  198. };
  199. struct Usbifacedesc {
  200. uint8_t bLength;
  201. // Size of Descriptor in Bytes (9 Bytes)
  202. uint8_t bDescriptorType;
  203. // Interface Descriptor (0x04, Diface)
  204. uint8_t bInterfaceNumber;
  205. // Number of Interface
  206. uint8_t bAlternateSetting;
  207. // Value used to select alternative setting
  208. uint8_t bNumEndpoints;
  209. // Number of Endpoints used for this interface
  210. uint8_t bInterfaceClass;
  211. // Class Code (Assigned by USB Org)
  212. uint8_t bInterfaceSubClass;
  213. // Subclass Code (Assigned by USB Org)
  214. uint8_t bInterfaceProtocol;
  215. // Protocol Code (Assigned by USB Org)
  216. uint8_t iInterface;
  217. // Index of String Descriptor Describing this interface
  218. uint8_t extra[256-9];
  219. };
  220. struct Usbendptdesc {
  221. uint8_t bLength;
  222. // Size of Descriptor in Bytes (7 bytes)
  223. uint8_t bDescriptorType;
  224. // Endpoint Descriptor (0x05, Dendpt)
  225. uint8_t bEndpointAddress;
  226. /* Endpoint Address
  227. * Bits 0..3b Endpoint Number.
  228. * Bits 4..6b Reserved. Set to Zero
  229. * Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints) */
  230. uint8_t bmAttributes;
  231. /* Bits 0..1 Transfer Type
  232. * 00 = Control
  233. * 01 = Isochronous
  234. * 10 = Bulk
  235. * 11 = Interrupt
  236. * Bits 2..7 are reserved. If Isochronous endpoint,
  237. * Bits 3..2 = Synchronisation Type (Iso Mode)
  238. * 00 = No Synchonisation
  239. * 01 = Asynchronous
  240. * 10 = Adaptive
  241. * 11 = Synchronous
  242. * Bits 5..4 = Usage Type (Iso Mode)
  243. * 00 = Data Endpoint
  244. * 01 = Feedback Endpoint
  245. * 10 = Explicit Feedback Data Endpoint
  246. * 11 = Reserved */
  247. uint8_t wMaxPacketSize[2];
  248. // Maximum Packet Size this endpoint is capable of sending or receiving
  249. uint8_t bInterval;
  250. /* Interval for polling endpoint data transfers. Value in frame counts.
  251. * Ignored for Bulk & Control Endpoints. Isochronous must equal 1,
  252. * may range from 1 to 255 for interrupt endpoints. */
  253. };
  254. static void
  255. put16(uint8_t *buf, uint16_t val)
  256. {
  257. buf[0] = val & 0xff;
  258. buf[1] = (val >> 8) & 0xff;
  259. }
  260. static uint16_t
  261. get16(uint8_t *buf)
  262. {
  263. uint16_t val;
  264. val = (uint16_t)buf[0] + ((uint16_t)buf[1] << 8);
  265. return val;
  266. }
  267. static int
  268. cmdreq(int fd, int type, int req, int value, int index, uint8_t *data, int count)
  269. {
  270. int ndata, n;
  271. uint8_t *wp;
  272. uint8_t buf[8];
  273. if(data == nil){
  274. wp = buf;
  275. ndata = 0;
  276. }else{
  277. ndata = count;
  278. wp = malloc(8+ndata);
  279. }
  280. wp[0] = type;
  281. wp[1] = req;
  282. put16(wp+2, value);
  283. put16(wp+4, index);
  284. put16(wp+6, count);
  285. if(data != nil)
  286. memmove(wp+8, data, ndata);
  287. n = write(fd, wp, 8+ndata);
  288. if(wp != buf)
  289. free(wp);
  290. if(n < 0)
  291. return -1;
  292. if(n != 8+ndata){
  293. fprint(2, "%s: cmd: short write: %d\n", argv0, n);
  294. return -1;
  295. }
  296. return n;
  297. }
  298. static int
  299. cmdrep(int fd, void *buf, int nb)
  300. {
  301. nb = read(fd, buf, nb);
  302. return nb;
  303. }
  304. static int
  305. usbcmd(int fd, int type, int req, int value, int index, uint8_t *data, int count)
  306. {
  307. int i, r, nerr;
  308. char err[64];
  309. /*
  310. * Some devices do not respond to commands some times.
  311. * Others even report errors but later work just fine. Retry.
  312. */
  313. r = -1;
  314. *err = 0;
  315. for(i = nerr = 0; i < Uctries; i++){
  316. if(type & Rd2h)
  317. r = cmdreq(fd, type, req, value, index, nil, count);
  318. else
  319. r = cmdreq(fd, type, req, value, index, data, count);
  320. if(r > 0){
  321. if((type & Rd2h) == 0)
  322. break;
  323. r = cmdrep(fd, data, count);
  324. if(r > 0)
  325. break;
  326. if(r == 0)
  327. werrstr("no data from device");
  328. }
  329. nerr++;
  330. if(*err == 0)
  331. rerrstr(err, sizeof(err));
  332. sleep(Ucdelay);
  333. }
  334. if(r > 0 && i >= 2)
  335. fprint(2, "usbcmd required %d attempts (%s)\n", i, err);
  336. return r;
  337. }
  338. int
  339. usbdescread(int fd, uint8_t *buf, int len, int desctype, int index)
  340. {
  341. return usbcmd(fd, Rd2h|Rstd|Rdevice, Rgetdesc, desctype<<8|0, index, buf, len);
  342. }
  343. int
  344. usbconfprint(int fd, Usbconfig *cp)
  345. {
  346. int nwr, ntot;
  347. int i;
  348. ntot = 0;
  349. nwr = fprint(fd, "config %d iface %d alt %d\n", cp->config, cp->iface, cp->alt);
  350. if(nwr == -1)
  351. return -1;
  352. ntot += nwr;
  353. for(i = 0; i < cp->nendpt; i++){
  354. nwr = fprint(
  355. fd,
  356. " endpt[%d]: addr %d type %d maxpkt %d pollival %d\n",
  357. i,
  358. cp->endpt[i].addr,
  359. cp->endpt[i].type,
  360. cp->endpt[i].maxpkt,
  361. cp->endpt[i].pollival
  362. );
  363. if(nwr == -1)
  364. return -1;
  365. ntot += nwr;
  366. }
  367. if(cp->nextra > 0){
  368. for(i = 0; i < cp->nextra; i++){
  369. nwr = fprint(fd, "%s0x%02x%s", i%16==0 ? "\t" : "", cp->extra[i], i < cp->nextra-1 ? ", " : "\n");
  370. if(nwr == -1)
  371. return -1;
  372. ntot += nwr;
  373. }
  374. }
  375. return ntot;
  376. }
  377. int
  378. usbconfread(int fd, Usbconfig **confp)
  379. {
  380. Usbconfig *confs;
  381. int nconfs, aconfs;
  382. uint8_t buf[1024];
  383. Usbdevdesc devdesc;
  384. Usbconfdesc confdesc;
  385. Usbifacedesc ifacedesc;
  386. Usbendptdesc endptdesc;
  387. int nrd;
  388. int cfg, ncfg;
  389. int ifi, niface;
  390. int epi;
  391. nrd = usbdescread(fd, buf, sizeof buf, Ddevice, 0);
  392. if(nrd == -1)
  393. sysfatal("readdesc Ddevice");
  394. memmove(&devdesc, buf, sizeof devdesc);
  395. nconfs = 0;
  396. aconfs = 4;
  397. confs = malloc(aconfs * sizeof confs[0]);
  398. ncfg = devdesc.bNumConfigurations;
  399. for(cfg = 0; cfg < ncfg; cfg++){
  400. int off = 0;
  401. nrd = usbdescread(fd, buf, sizeof buf, Dconfig, cfg);
  402. if(nrd == -1)
  403. sysfatal("readdesc Dconfig");
  404. if(off >= nrd || off+buf[off] > nrd){
  405. print("premature end of config data");
  406. goto done;
  407. }
  408. if(buf[off+1] != Dconfig)
  409. sysfatal("non-config descriptor %d\n", confdesc.bDescriptorType);
  410. memmove(&confdesc, buf+off, buf[off]);
  411. off += confdesc.bLength;
  412. niface = confdesc.bNumInterfaces;
  413. for(ifi = 0; ifi < niface; ifi++){
  414. Usbconfig *cp;
  415. ifskip:
  416. if(off >= nrd || off+buf[off] > nrd){
  417. print("premature end of config data");
  418. goto done;
  419. }
  420. if(buf[off+1] != Diface){
  421. print("non-iface descriptor %d in config\n", buf[off+1]);
  422. off += buf[off];
  423. goto ifskip;
  424. }
  425. memmove(&ifacedesc, buf+off, buf[off]);
  426. if(nconfs == aconfs){
  427. aconfs += 4;
  428. confs = realloc(confs, aconfs * sizeof confs[0]);
  429. }
  430. cp = &confs[nconfs++];
  431. memset(cp, 0, sizeof cp[0]);
  432. cp->config = confdesc.bConfigurationValue;
  433. cp->iface = ifacedesc.bInterfaceNumber;
  434. cp->alt = ifacedesc.bAlternateSetting;
  435. cp->nendpt = ifacedesc.bNumEndpoints;
  436. if(cp->nendpt > nelem(cp->endpt)){
  437. print("out of endpoints in usbconfig (need %d have %d)\n", cp->nendpt, nelem(cp->endpt));
  438. cp->nendpt = nelem(cp->endpt);
  439. }
  440. off += ifacedesc.bLength;
  441. for(epi = 0; epi < cp->nendpt; epi++){
  442. epskip:
  443. if(off >= nrd || off+buf[off] > nrd){
  444. print("premature end of config data\n");
  445. goto done;
  446. }
  447. if(buf[off+1] != Dendpt){
  448. if(cp->nextra+buf[off] <= sizeof cp->extra){
  449. memmove(cp->extra + cp->nextra, buf+off, buf[off]);
  450. cp->nextra += buf[off];
  451. } else {
  452. print("out of extra space in usbconfig, desc type 0x%02x\n", buf[off+1]);
  453. }
  454. off += buf[off];
  455. goto epskip;
  456. }
  457. memmove(&endptdesc, buf+off, buf[off]);
  458. off += endptdesc.bLength;
  459. cp->endpt[epi].addr = endptdesc.bEndpointAddress;
  460. cp->endpt[epi].type = endptdesc.bmAttributes;
  461. cp->endpt[epi].maxpkt = get16(endptdesc.wMaxPacketSize);
  462. cp->endpt[epi].pollival = endptdesc.bInterval;
  463. }
  464. }
  465. }
  466. done:
  467. aconfs = nconfs;
  468. confs = realloc(confs, aconfs * sizeof confs[0]);
  469. *confp = confs;
  470. return nconfs;
  471. }
  472. int
  473. usbopen(int fd, Usbconfig *cp, int epi, int *ctlp)
  474. {
  475. char *p, buf[1024];
  476. int epaddr, eptype, isread;
  477. int ctl, epctl, epdata;
  478. int n;
  479. ctl = -1;
  480. epctl = -1;
  481. epdata = -1;
  482. epaddr = cp->endpt[epi].addr&7;
  483. eptype = cp->endpt[epi].type&3;
  484. isread = (cp->endpt[epi].addr&128) != 0;
  485. if(usbcmd(fd, Rh2d|Rstd|Rdevice, Rsetconf, cp->config, 0, nil, 0) == -1){
  486. fprint(2, "usbopen: Rsetconf fail\n");
  487. goto fail;
  488. }
  489. if(usbcmd(fd, Rh2d|Rstd|Riface, Rsetiface, cp->alt, cp->iface, nil, 0) == -1){
  490. fprint(2, "usbopen: Rsetiface fail\n");
  491. goto fail;
  492. }
  493. fd2path(fd, buf, sizeof buf);
  494. if((p = strrchr(buf, '/')) == nil){
  495. fprint(2, "usbopen: no '.' in data path '%s'\n", buf);
  496. goto fail;
  497. }
  498. strcpy(p, "/ctl");
  499. if((ctl = open(buf, ORDWR)) == -1){
  500. fprint(2, "usbopen: open '%s' failed: %r\n", buf);
  501. goto fail;
  502. }
  503. n = snprint(buf, sizeof buf, "new %d %d %s", epaddr, eptype, isread ? "r" : "w");
  504. if(write(ctl, buf, n) != n){
  505. fprint(2, "usbopen: write failed '%s': %r\n", buf);
  506. //goto fail;
  507. }
  508. fd2path(fd, buf, sizeof buf);
  509. if((p = strrchr(buf, '.')) == nil){
  510. fprint(2, "usbopen: no '.' in ctl path '%s'\n", buf);
  511. goto fail;
  512. }
  513. snprint(p, sizeof buf - (p-buf), ".%d/ctl", epaddr);
  514. if((epctl = open(buf, ORDWR)) == -1){
  515. fprint(2, "usbopen: open '%s': %r\n", buf);
  516. goto fail;
  517. }
  518. n = snprint(buf, sizeof buf, "maxpkt %d", cp->endpt[epi].maxpkt);
  519. if(write(epctl, buf, n) != n){
  520. fprint(2, "usbopen: '%s': %r\n", buf);
  521. goto fail;
  522. }
  523. if(eptype == Eintr || eptype == Eiso){
  524. n = snprint(buf, sizeof buf, "pollival %d", cp->endpt[epi].pollival);
  525. if(write(epctl, buf, n) != n){
  526. fprint(2, "usbopen: pollival failed\n");
  527. goto fail;
  528. }
  529. }
  530. fd2path(fd, buf, sizeof buf);
  531. if((p = strrchr(buf, '.')) == nil){
  532. fprint(2, "usbopen: no '.' in ctl path '%s'\n", buf);
  533. goto fail;
  534. }
  535. snprint(p, sizeof buf - (p-buf), ".%d/data", epaddr);
  536. if((epdata = open(buf, isread ? OREAD : OWRITE)) == -1){
  537. fprint(2, "usbopen: open '%s': %r\n", buf);
  538. goto fail;
  539. }
  540. if(ctlp != nil)
  541. *ctlp = epctl;
  542. else
  543. close(epctl);
  544. if(ctl != -1)
  545. close(ctl);
  546. return epdata;
  547. fail:
  548. if(ctl != -1)
  549. close(ctl);
  550. if(epctl != -1)
  551. close(epctl);
  552. if(epdata != -1)
  553. close(epdata);
  554. return -1;
  555. }