dump.c 12 KB

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