dump.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include <bio.h>
  5. #include "usb.h"
  6. int verbose;
  7. typedef struct Flags Flags;
  8. typedef struct Classes Classes;
  9. struct Flags {
  10. int bit;
  11. char* name0;
  12. char* name1;
  13. };
  14. struct Classes {
  15. char* name;
  16. struct {
  17. char* name;
  18. char* proto[4];
  19. } subclass[4];
  20. };
  21. static Classes classname[] = {
  22. [CL_AUDIO] {"audio", {[1]{"control"}, [2]{"stream"}, [3]{"midi"}}},
  23. [CL_COMMS] {"comms", {[1] {"abstract", {[1]"AT"}}}},
  24. [CL_HID] {"hid", {[1] {"boot", {[1]"kbd", [2]"mouse"}}}},
  25. [CL_PRINTER] {"printer", {[1]"printer", {[1]"uni", [2]"bi"}}},
  26. [CL_HUB] {"hub", {[1]{"hub"}}},
  27. [CL_DATA] {"data"},
  28. };
  29. static void pflag(Flags*, uint);
  30. char *
  31. sclass(char *p, char *e, ulong csp)
  32. {
  33. Classes *cs;
  34. int c, s, pr;
  35. c = Class(csp);
  36. s = Subclass(csp);
  37. pr = Proto(csp);
  38. if(c < 0 || c >= nelem(classname) || (cs = &classname[c])->name == nil)
  39. return seprint(p, e, "%d.%d.%d", c, s, pr);
  40. p = seprint(p, e, "%s.", cs->name);
  41. if(s < 0 || s >= nelem(cs->subclass) || cs->subclass[s].name == nil)
  42. p = seprint(p, e, "%d.%d", s, pr);
  43. else{
  44. p = seprint(p, e, "%s.", cs->subclass[s].name);
  45. if(pr < 0 || pr >= nelem(cs->subclass[s].proto) || cs->subclass[s].proto[pr] == nil)
  46. p = seprint(p, e, "%d", pr);
  47. else
  48. p = seprint(p, e, "%s", cs->subclass[s].proto[pr]);
  49. }
  50. return p;
  51. }
  52. void
  53. pdevice(Device *, int, ulong, void *b, int n)
  54. {
  55. DDevice *d;
  56. char scbuf[64];
  57. if(n < DDEVLEN)
  58. return;
  59. d = b;
  60. if(debug & Dbginfo) {
  61. fprint(2, "usb (bcd)%c%c%c%c",
  62. '0'+((d->bcdUSB[1]>>4)&0xf), '0'+(d->bcdUSB[1]&0xf),
  63. '0'+((d->bcdUSB[0]>>4)&0xf), '0'+(d->bcdUSB[0]&0xf));
  64. sclass(scbuf, scbuf + sizeof scbuf,
  65. CSP(d->bDeviceClass, d->bDeviceSubClass, d->bDeviceProtocol)),
  66. fprint(2, " class %d subclass %d proto %d [%s] max0 %d",
  67. d->bDeviceClass, d->bDeviceSubClass, d->bDeviceProtocol,
  68. scbuf,
  69. d->bMaxPacketSize0);
  70. fprint(2, " vendor %#x product %#x device (bcd)%c%c%c%c",
  71. GET2(d->idVendor), GET2(d->idProduct),
  72. '0'+((d->bcdDevice[1]>>4)&0xf), '0'+(d->bcdDevice[1]&0xf),
  73. '0'+((d->bcdDevice[0]>>4)&0xf), '0'+(d->bcdDevice[0]&0xf));
  74. fprint(2, " man %d prod %d serial %d nconfig %d",
  75. d->iManufacturer, d->iProduct, d->iSerialNumber,
  76. d->bNumConfigurations);
  77. }
  78. }
  79. void
  80. phid(Device *, int, ulong, void *b, int n)
  81. {
  82. DHid *d;
  83. if(n < DHIDLEN){
  84. fprint(2, "%s: hid too short\n", argv0);
  85. return;
  86. }
  87. d = b;
  88. if(debug & Dbginfo)
  89. fprint(2, "HID (bcd)%c%c%c%c country %d nhidclass %d classdtype %#x dlen %d\n",
  90. '0'+((d->bcdHID[1]>>4)&0xf), '0'+(d->bcdHID[1]&0xf),
  91. '0'+((d->bcdHID[0]>>4)&0xf), '0'+(d->bcdHID[0]&0xf),
  92. d->bCountryCode, d->bNumDescriptors,
  93. d->bClassDescriptorType, GET2(d->wItemLength));
  94. }
  95. static Flags ioflags[] = {
  96. {0, "Data", "Constant"},
  97. {1, "Array", "Variable"},
  98. {2, "Absolute", "Relative"},
  99. {3, "NoWrap", "Wrap"},
  100. {4, "Linear", "NonLinear"},
  101. {5, "PreferredState", "No Preferred State"},
  102. {6, "No Null position", "Null state"},
  103. {7, "Non Volatile", "Volatile"},
  104. {8, "Bit Field", "Buffered Bytes"},
  105. {-1, nil, nil},
  106. };
  107. static void
  108. pflag(Flags *tab, uint v)
  109. {
  110. char buf[200], *s;
  111. int n;
  112. n = 0;
  113. buf[0] = 0;
  114. for(; tab->name0 != nil; tab++){
  115. if(v & (1<<tab->bit))
  116. s = tab->name1;
  117. else
  118. s = tab->name0;
  119. if(s != nil && *s)
  120. n += snprint(buf+n, sizeof(buf)-n, ", %s", s);
  121. }
  122. if((debug & Dbginfo) && buf[0])
  123. fprint(2, "[%s]", buf+2);
  124. }
  125. void
  126. preport(Device *, int, ulong, byte *b, int n)
  127. {
  128. byte *s, *es;
  129. int tag, nb, i, indent;
  130. int v;
  131. Flags *tab;
  132. s = b+2;
  133. es = b+n;
  134. indent = 0;
  135. while(s < es){
  136. for(i=0; i<indent; i++)
  137. fprint(2, " ");
  138. tag = *s++;
  139. if(tag == Tlong){
  140. fprint(2, "long report tag");
  141. return;
  142. }
  143. if((nb = tag&3) == 3)
  144. nb = 4;
  145. v = 0;
  146. for(i=0; i<nb; i++)
  147. v |= s[i] << (i*8);
  148. switch(tag & Tmtype){
  149. case Treserved:
  150. if(tag == Tlong){
  151. fprint(2, "long report tag");
  152. return;
  153. }
  154. fprint(2, "illegal tag");
  155. return;
  156. case Tmain:
  157. tab = nil;
  158. if (debug & Dbginfo) {
  159. switch(tag & Tmitem){
  160. case Tinput:
  161. fprint(2, "Input");
  162. tab = ioflags;
  163. break;
  164. case Toutput:
  165. fprint(2, "Output");
  166. tab = ioflags;
  167. break;
  168. case Tfeature:
  169. fprint(2, "Feature");
  170. tab = ioflags;
  171. break;
  172. case Tcoll:
  173. fprint(2, "Collection");
  174. indent++;
  175. break;
  176. case Tecoll:
  177. fprint(2, "End Collection");
  178. indent--;
  179. break;
  180. default:
  181. fprint(2, "unexpected item %.2x", tag);
  182. }
  183. fprint(2, "=%#ux", v);
  184. if(tab != nil)
  185. pflag(tab, v);
  186. }
  187. break;
  188. case Tglobal:
  189. if (debug & Dbginfo) {
  190. fprint(2, "Global %#ux: ", v);
  191. switch(tag & Tmitem){
  192. case Tusagepage:
  193. fprint(2, "Usage Page %#ux", v);
  194. break;
  195. case Tlmin:
  196. fprint(2, "Logical Min %d", v);
  197. break;
  198. case Tlmax:
  199. fprint(2, "Logical Max %d", v);
  200. break;
  201. case Tpmin:
  202. fprint(2, "Physical Min %d", v);
  203. break;
  204. case Tpmax:
  205. fprint(2, "Physical Max %d", v);
  206. break;
  207. case Tunitexp:
  208. fprint(2, "Unit Exponent %d", v);
  209. break;
  210. case Tunit:
  211. fprint(2, "Unit %d", v);
  212. break;
  213. case Trepsize:
  214. fprint(2, "Report size %d", v);
  215. break;
  216. case TrepID:
  217. fprint(2, "Report ID %#x", v);
  218. break;
  219. case Trepcount:
  220. fprint(2, "Report Count %d", v);
  221. break;
  222. case Tpush:
  223. fprint(2, "Push %d", v);
  224. break;
  225. case Tpop:
  226. fprint(2, "Pop %d", v);
  227. break;
  228. default:
  229. fprint(2, "Unknown %#ux", v);
  230. break;
  231. }
  232. }
  233. break;
  234. case Tlocal:
  235. if (debug & Dbginfo) {
  236. fprint(2, "Local %#ux: ", v);
  237. switch(tag & Tmitem){
  238. case Tusage:
  239. fprint(2, "Usage %d", v);
  240. break;
  241. case Tumin:
  242. fprint(2, "Usage min %d", v);
  243. break;
  244. case Tumax:
  245. fprint(2, "Usage max %d", v);
  246. break;
  247. case Tdindex:
  248. fprint(2, "Designator index %d", v);
  249. break;
  250. case Tdmin:
  251. fprint(2, "Designator min %d", v);
  252. break;
  253. case Tdmax:
  254. fprint(2, "Designator max %d", v);
  255. break;
  256. case Tsindex:
  257. fprint(2, "String index %d", v);
  258. break;
  259. case Tsmin:
  260. fprint(2, "String min %d", v);
  261. break;
  262. case Tsmax:
  263. fprint(2, "String max %d", v);
  264. break;
  265. case Tsetdelim:
  266. fprint(2, "Set delim %#ux", v);
  267. break;
  268. default:
  269. fprint(2, "Unknown %#ux", v);
  270. break;
  271. }
  272. }
  273. break;
  274. }
  275. fprint(2, "\n");
  276. s += nb;
  277. }
  278. }
  279. void
  280. phub(Device *, int, ulong, void *b, int n)
  281. {
  282. DHub *d;
  283. if(n < DHUBLEN)
  284. return;
  285. d = b;
  286. if (debug & Dbginfo)
  287. fprint(2, "nport %d charac %#.4x pwr %dms current %dmA remov %#.2x",
  288. d->bNbrPorts, GET2(d->wHubCharacteristics),
  289. d->bPwrOn2PwrGood*2, d->bHubContrCurrent,
  290. d->DeviceRemovable[0]);
  291. }
  292. void
  293. pstring(Device *, int, ulong, void *b, int n)
  294. {
  295. byte *rb;
  296. char *s;
  297. Rune r;
  298. int l;
  299. if(n <= 2){
  300. fprint(2, "\"\"");
  301. return;
  302. }
  303. if(n & 1){
  304. fprint(2, "illegal count\n");
  305. return;
  306. }
  307. n = (n - 2)/2;
  308. rb = (byte*)b + 2;
  309. s = malloc(n*UTFmax+1);
  310. for(l=0; --n >= 0; rb += 2){
  311. r = GET2(rb);
  312. l += runetochar(s+l, &r);
  313. }
  314. s[l] = 0;
  315. fprint(2, "\"%s\"", s);
  316. free(s);
  317. }
  318. void
  319. pcs_raw(char *tag, byte *b, int n)
  320. {
  321. int i;
  322. if (debug & Dbginfo) {
  323. fprint(2, "%s", tag);
  324. for(i=2; i<n; i++)
  325. fprint(2, " %.2x", b[i]);
  326. }
  327. }
  328. static void
  329. pcs_config(Device *, int, ulong, void *b, int n)
  330. {
  331. pcs_raw("CS_CONFIG", b, n);
  332. }
  333. static void
  334. pcs_string(Device *, ulong, void *b, int n)
  335. {
  336. pcs_raw("CS_STRING", b, n);
  337. }
  338. static void
  339. pcs_endpoint(Device *, int, ulong, void *bb, int n)
  340. {
  341. byte *b = bb;
  342. if (debug & Dbginfo) {
  343. switch(b[2]) {
  344. case 0x01:
  345. fprint(2,
  346. "CS_ENDPOINT for TerminalID %d, delay %d, format_tag %#ux\n",
  347. b[3], b[4], b[5] | (b[6]<<8));
  348. break;
  349. case 0x02:
  350. fprint(2,
  351. "CS_INTERFACE FORMAT_TYPE %d, channels %d, subframesize %d, resolution %d, freqtype %d, ",
  352. b[3], b[4], b[5], b[6], b[7]);
  353. fprint(2, "freq0 %d, freq1 %d\n",
  354. b[8] | b[9]<<8 | b[10]<<16,
  355. b[11] | b[12]<<8 | b[13]<<16);
  356. break;
  357. default:
  358. pcs_raw("CS_INTERFACE", bb, n);
  359. }
  360. }
  361. }
  362. static void
  363. pcs_interface(Device *, int n, ulong, void *bb, int nb)
  364. {
  365. if ((debug & Dbginfo) && n >= 0)
  366. pcs_raw("CS_INTERFACE", bb, nb);
  367. }
  368. void
  369. pdesc(Device *d, int c, ulong csp, byte *b, int n)
  370. {
  371. int class, subclass, proto, dalt, i, ep, ifc, len;
  372. DConfig *dc;
  373. DEndpoint *de;
  374. DInterface *di;
  375. Dinf *dif;
  376. Endpt *dep;
  377. void (*f)(Device *, int, ulong, void*, int);
  378. char scbuf[64];
  379. class = Class(csp);
  380. dalt = -1;
  381. ifc = -1;
  382. if (c >= nelem(d->config)) {
  383. fprint(2, "Too many interfaces (%d of %d)\n",
  384. c, nelem(d->config));
  385. return;
  386. }
  387. if(debug & Dbginfo)
  388. fprint(2, "pdesc %d.%d [%d]\n", d->id, c, n);
  389. len = -1;
  390. while(n > 2 && b[0] && b[0] <= n){
  391. if (debug & Dbginfo)
  392. fprint(2, "desc %d.%d [%d] %#2.2x: ", d->id, c, b[0], b[1]);
  393. switch (b[1]) {
  394. case CONFIGURATION:
  395. if(b[0] < DCONFLEN){
  396. if(debug & Dbginfo)
  397. fprint(2, "short config %d < %d", b[0], DCONFLEN);
  398. return;
  399. }
  400. dc = (DConfig*)b;
  401. d->config[c]->nif = dc->bNumInterfaces;
  402. d->config[c]->cval = dc->bConfigurationValue;
  403. d->config[c]->attrib = dc->bmAttributes;
  404. d->config[c]->milliamps = dc->MaxPower*2;
  405. d->nif += d->config[c]->nif;
  406. if (debug & Dbginfo)
  407. fprint(2, "config %d: tdlen %d ninterface %d iconfig %d attr %#.2x power %dmA\n",
  408. dc->bConfigurationValue,
  409. GET2(dc->wTotalLength),
  410. dc->bNumInterfaces, dc->iConfiguration,
  411. dc->bmAttributes, dc->MaxPower*2);
  412. break;
  413. case INTERFACE:
  414. if(n < DINTERLEN){
  415. if(debug & Dbginfo)
  416. fprint(2, "short interface %d < %d", b[0], DINTERLEN);
  417. return;
  418. }
  419. di = (DInterface *)b;
  420. class = di->bInterfaceClass;
  421. subclass = di->bInterfaceSubClass;
  422. proto = di->bInterfaceProtocol;
  423. csp = CSP(class, subclass, proto);
  424. if(debug & Dbginfo){
  425. sclass(scbuf, scbuf + sizeof scbuf, csp);
  426. fprint(2, "interface %d: alt %d nept %d class %#x subclass %#x proto %d [%s] iinterface %d\n",
  427. di->bInterfaceNumber,
  428. di->bAlternateSetting,
  429. di->bNumEndpoints, class, subclass,
  430. proto, scbuf, di->iInterface);
  431. }
  432. if (c < 0) {
  433. fprint(2, "Unexpected INTERFACE message\n");
  434. return;
  435. }
  436. ifc = di->bInterfaceNumber;
  437. dalt = di->bAlternateSetting;
  438. if (ifc < 0 || ifc >= nelem(d->config[c]->iface))
  439. sysfatal("Bad interface number %d", ifc);
  440. if (dalt < 0 ||
  441. dalt >= nelem(d->config[c]->iface[ifc]->dalt))
  442. sysfatal("Bad alternate number %d", dalt);
  443. if (d->config[c] == nil)
  444. sysfatal("No config");
  445. if (ifc == 0) {
  446. if (c == 0)
  447. d->ep[0]->csp = csp;
  448. d->config[c]->csp = csp;
  449. }
  450. dif = d->config[c]->iface[ifc];
  451. if (dif == nil) {
  452. d->config[c]->iface[ifc] = dif =
  453. mallocz(sizeof(Dinf), 1);
  454. dif->csp = csp;
  455. }
  456. dif->interface = di->bInterfaceNumber;
  457. break;
  458. case ENDPOINT:
  459. if(n < DENDPLEN)
  460. return;
  461. de = (DEndpoint *)b;
  462. if(debug & Dbginfo) {
  463. fprint(2, "addr %#2.2x attrib %#2.2x maxpkt %d interval %dms",
  464. de->bEndpointAddress, de->bmAttributes,
  465. GET2(de->wMaxPacketSize), de->bInterval);
  466. if(de->bEndpointAddress & 0x80)
  467. fprint(2, " [IN]");
  468. else
  469. fprint(2, " [OUT]");
  470. switch(de->bmAttributes&0x33){
  471. case 0:
  472. fprint(2, " [Control]");
  473. break;
  474. case 1:
  475. fprint(2, " [Iso]");
  476. switch(de->bmAttributes&0xc){
  477. case 0x4:
  478. fprint(2, " [Asynchronous]");
  479. break;
  480. case 0x8:
  481. fprint(2, " [Adaptive]");
  482. break;
  483. case 0xc:
  484. fprint(2, " [Synchronous]");
  485. break;
  486. }
  487. break;
  488. case 2:
  489. fprint(2, " [Bulk]");
  490. break;
  491. case 3:
  492. fprint(2, " [Interrupt]");
  493. break;
  494. }
  495. if(b[0] == 9)
  496. fprint(2, "refresh %d synchaddress %d",
  497. b[7], b[8]);
  498. fprint(2, "\n");
  499. }
  500. if (c < 0 || ifc < 0 || dalt < 0) {
  501. fprint(2, "Unexpected ENDPOINT message\n");
  502. return;
  503. }
  504. dif = d->config[c]->iface[ifc];
  505. if (dif == nil)
  506. sysfatal("d->config[%d]->iface[%d] == nil",
  507. c, ifc);
  508. if (dif->dalt[dalt] == nil)
  509. dif->dalt[dalt] = mallocz(sizeof(Dalt),1);
  510. dif->dalt[dalt]->attrib = de->bmAttributes;
  511. dif->dalt[dalt]->interval = de->bInterval;
  512. ep = de->bEndpointAddress & 0xf;
  513. dep = d->ep[ep];
  514. if(debug)
  515. fprint(2, "%s: endpoint addr %d\n", argv0, ep);
  516. if(dep == nil){
  517. d->ep[ep] = dep = newendpt(d, ep, class);
  518. dep->dir = de->bEndpointAddress & 0x80
  519. ? Ein : Eout;
  520. }else if ((dep->addr&0x80) !=
  521. (de->bEndpointAddress&0x80))
  522. dep->dir = Eboth;
  523. dep->maxpkt = GET2(de->wMaxPacketSize);
  524. dep->addr = de->bEndpointAddress;
  525. dep->type = de->bmAttributes & 0x03;
  526. dep->isotype = (de->bmAttributes>>2) & 0x03;
  527. dep->csp = csp;
  528. dep->conf = d->config[c];
  529. dep->iface = dif;
  530. for(i = 0; i < nelem(dif->endpt); i++)
  531. if(dif->endpt[i] == nil){
  532. dif->endpt[i] = dep;
  533. break;
  534. }
  535. if(i == nelem(dif->endpt))
  536. fprint(2, "Too many endpoints\n");
  537. if (d->nif <= ep)
  538. d->nif = ep+1;
  539. break;
  540. default:
  541. assert(nelem(dprinter) == 0x100);
  542. f = dprinter[b[1]];
  543. if(f != nil){
  544. (*f)(d, c, dalt<<24 | ifc<<16 | (csp&0xffff),
  545. b, b[0]);
  546. if(debug & Dbginfo)
  547. fprint(2, "\n");
  548. }else
  549. if(verbose){
  550. int i;
  551. switch(b[1]){
  552. case DEVICE:
  553. fprint(2, "(device)");
  554. break;
  555. case STRING:
  556. fprint(2, "(string)");
  557. break;
  558. default:
  559. fprint(2, "(unknown type)");
  560. }
  561. for(i=1; i<b[0]; i++)
  562. fprint(2, " %.2x", b[i]);
  563. fprint(2, "\n");
  564. }else if(debug & Dbginfo)
  565. fprint(2, "\n");
  566. break;
  567. }
  568. len = b[0];
  569. n -= len;
  570. b += len;
  571. }
  572. if(n)
  573. fprint(2, "pdesc: %d bytes left unparsed, b[0]=%d, b[-len]=%d, len=%d\n", n, b[0], b[-len], len);
  574. }