From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: <964c1529df94a5c6ba189fb0520afbc5@plan9.bell-labs.com> To: 9fans@cse.psu.edu Subject: Re: [9fans] usbd problem Date: Tue, 12 Feb 2008 09:35:52 -0500 From: Sape Mullender In-Reply-To: <94207d56e098473c63793756938b582a@quanstro.net> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="upas-jyltpomumbcbvhclupeempqorv" Topicbox-Message-UUID: 515d84c8-ead3-11e9-9d60-3106f5b1d025 This is a multi-part message in MIME format. --upas-jyltpomumbcbvhclupeempqorv Content-Disposition: inline Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit >> Nemo found a bug in usb/lib/dump.c that may well account for >> this. I incorporated his change (and fixed a bug in his code :-). >> I'll ask Geoff to push it out today. >> >> Sape > > excellent. i'll give it a shot. > > - erik Give it a shot now: /sys/src/cmd/usb/lib/dump.c --upas-jyltpomumbcbvhclupeempqorv Content-Disposition: attachment; filename=dump.c Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit #include #include #include #include #include "usb.h" int verbose; typedef struct Flags Flags; typedef struct Classes Classes; struct Flags { int bit; char* name0; char* name1; }; struct Classes { char* name; struct { char* name; char* proto[4]; } subclass[4]; }; static Classes classname[] = { [CL_AUDIO] {"audio", {[1]{"control"}, [2]{"stream"}, [3]{"midi"}}}, [CL_COMMS] {"comms", {[1] {"abstract", {[1]"AT"}}}}, [CL_HID] {"hid", {[1] {"boot", {[1]"kbd", [2]"mouse"}}}}, [CL_PRINTER] {"printer", {[1]"printer", {[1]"uni", [2]"bi"}}}, [CL_HUB] {"hub", {[1]{"hub"}}}, [CL_DATA] {"data"}, }; static void pflag(Flags*, uint); char * sclass(char *p, char *e, ulong csp) { Classes *cs; int c, s, pr; c = Class(csp); s = Subclass(csp); pr = Proto(csp); if(c < 0 || c >= nelem(classname) || (cs = &classname[c])->name == nil) return seprint(p, e, "%d.%d.%d", c, s, pr); p = seprint(p, e, "%s.", cs->name); if(s < 0 || s >= nelem(cs->subclass) || cs->subclass[s].name == nil) p = seprint(p, e, "%d.%d", s, pr); else{ p = seprint(p, e, "%s.", cs->subclass[s].name); if(pr < 0 || pr >= nelem(cs->subclass[s].proto) || cs->subclass[s].proto[pr] == nil) p = seprint(p, e, "%d", pr); else p = seprint(p, e, "%s", cs->subclass[s].proto[pr]); } return p; } void pdevice(Device *, int, ulong, void *b, int n) { DDevice *d; char scbuf[64]; if(n < DDEVLEN) return; d = b; if(debug & Dbginfo) { fprint(2, "usb (bcd)%c%c%c%c", '0'+((d->bcdUSB[1]>>4)&0xf), '0'+(d->bcdUSB[1]&0xf), '0'+((d->bcdUSB[0]>>4)&0xf), '0'+(d->bcdUSB[0]&0xf)); sclass(scbuf, scbuf + sizeof scbuf, CSP(d->bDeviceClass, d->bDeviceSubClass, d->bDeviceProtocol)), fprint(2, " class %d subclass %d proto %d [%s] max0 %d", d->bDeviceClass, d->bDeviceSubClass, d->bDeviceProtocol, scbuf, d->bMaxPacketSize0); fprint(2, " vendor %#x product %#x device (bcd)%c%c%c%c", GET2(d->idVendor), GET2(d->idProduct), '0'+((d->bcdDevice[1]>>4)&0xf), '0'+(d->bcdDevice[1]&0xf), '0'+((d->bcdDevice[0]>>4)&0xf), '0'+(d->bcdDevice[0]&0xf)); fprint(2, " man %d prod %d serial %d nconfig %d", d->iManufacturer, d->iProduct, d->iSerialNumber, d->bNumConfigurations); } } void phid(Device *, int, ulong, void *b, int n) { DHid *d; if(n < DHIDLEN){ fprint(2, "%s: hid too short\n", argv0); return; } d = b; if(debug & Dbginfo) fprint(2, "HID (bcd)%c%c%c%c country %d nhidclass %d classdtype %#x dlen %d\n", '0'+((d->bcdHID[1]>>4)&0xf), '0'+(d->bcdHID[1]&0xf), '0'+((d->bcdHID[0]>>4)&0xf), '0'+(d->bcdHID[0]&0xf), d->bCountryCode, d->bNumDescriptors, d->bClassDescriptorType, GET2(d->wItemLength)); } static Flags ioflags[] = { {0, "Data", "Constant"}, {1, "Array", "Variable"}, {2, "Absolute", "Relative"}, {3, "NoWrap", "Wrap"}, {4, "Linear", "NonLinear"}, {5, "PreferredState", "No Preferred State"}, {6, "No Null position", "Null state"}, {7, "Non Volatile", "Volatile"}, {8, "Bit Field", "Buffered Bytes"}, {-1, nil, nil}, }; static void pflag(Flags *tab, uint v) { char buf[200], *s; int n; n = 0; buf[0] = 0; for(; tab->name0 != nil; tab++){ if(v & (1<bit)) s = tab->name1; else s = tab->name0; if(s != nil && *s) n += snprint(buf+n, sizeof(buf)-n, ", %s", s); } if((debug & Dbginfo) && buf[0]) fprint(2, "[%s]", buf+2); } void preport(Device *, int, ulong, byte *b, int n) { byte *s, *es; int tag, nb, i, indent; int v; Flags *tab; s = b+2; es = b+n; indent = 0; while(s < es){ for(i=0; ibNbrPorts, GET2(d->wHubCharacteristics), d->bPwrOn2PwrGood*2, d->bHubContrCurrent, d->DeviceRemovable[0]); } void pstring(Device *, int, ulong, void *b, int n) { byte *rb; char *s; Rune r; int l; if(n <= 2){ fprint(2, "\"\""); return; } if(n & 1){ fprint(2, "illegal count\n"); return; } n = (n - 2)/2; rb = (byte*)b + 2; s = malloc(n*UTFmax+1); for(l=0; --n >= 0; rb += 2){ r = GET2(rb); l += runetochar(s+l, &r); } s[l] = 0; fprint(2, "\"%s\"", s); free(s); } void pcs_raw(char *tag, byte *b, int n) { int i; if (debug & Dbginfo) { fprint(2, "%s", tag); for(i=2; i= 0) pcs_raw("CS_INTERFACE", bb, nb); } void pdesc(Device *d, int c, ulong csp, byte *b, int n) { int class, subclass, proto, dalt, i, ep, ifc, len; DConfig *dc; DEndpoint *de; DInterface *di; Dinf *dif; Endpt *dep; void (*f)(Device *, int, ulong, void*, int); char scbuf[64]; class = Class(csp); dalt = -1; ifc = -1; if (c >= nelem(d->config)) { fprint(2, "Too many interfaces (%d of %d)\n", c, nelem(d->config)); return; } if(debug & Dbginfo) fprint(2, "pdesc %d.%d [%d]\n", d->id, c, n); len = -1; while(n > 2 && b[0] && b[0] <= n){ if (debug & Dbginfo) fprint(2, "desc %d.%d [%d] %#2.2x: ", d->id, c, b[0], b[1]); switch (b[1]) { case CONFIGURATION: if(b[0] < DCONFLEN){ if(debug & Dbginfo) fprint(2, "short config %d < %d", b[0], DCONFLEN); return; } dc = (DConfig*)b; d->config[c]->nif = dc->bNumInterfaces; d->config[c]->cval = dc->bConfigurationValue; d->config[c]->attrib = dc->bmAttributes; d->config[c]->milliamps = dc->MaxPower*2; d->nif += d->config[c]->nif; if (debug & Dbginfo) fprint(2, "config %d: tdlen %d ninterface %d iconfig %d attr %#.2x power %dmA\n", dc->bConfigurationValue, GET2(dc->wTotalLength), dc->bNumInterfaces, dc->iConfiguration, dc->bmAttributes, dc->MaxPower*2); break; case INTERFACE: if(n < DINTERLEN){ if(debug & Dbginfo) fprint(2, "short interface %d < %d", b[0], DINTERLEN); return; } di = (DInterface *)b; class = di->bInterfaceClass; subclass = di->bInterfaceSubClass; proto = di->bInterfaceProtocol; csp = CSP(class, subclass, proto); if(debug & Dbginfo){ sclass(scbuf, scbuf + sizeof scbuf, csp); fprint(2, "interface %d: alt %d nept %d class %#x subclass %#x proto %d [%s] iinterface %d\n", di->bInterfaceNumber, di->bAlternateSetting, di->bNumEndpoints, class, subclass, proto, scbuf, di->iInterface); } if (c < 0) { fprint(2, "Unexpected INTERFACE message\n"); return; } ifc = di->bInterfaceNumber; dalt = di->bAlternateSetting; if (ifc < 0 || ifc >= nelem(d->config[c]->iface)) sysfatal("Bad interface number %d", ifc); if (dalt < 0 || dalt >= nelem(d->config[c]->iface[ifc]->dalt)) sysfatal("Bad alternate number %d", dalt); if (d->config[c] == nil) sysfatal("No config"); if (ifc == 0) { if (c == 0) d->ep[0]->csp = csp; d->config[c]->csp = csp; } dif = d->config[c]->iface[ifc]; if (dif == nil) { d->config[c]->iface[ifc] = dif = mallocz(sizeof(Dinf), 1); dif->csp = csp; } dif->interface = di->bInterfaceNumber; break; case ENDPOINT: if(n < DENDPLEN) return; de = (DEndpoint *)b; if(debug & Dbginfo) { fprint(2, "addr %#2.2x attrib %#2.2x maxpkt %d interval %dms", de->bEndpointAddress, de->bmAttributes, GET2(de->wMaxPacketSize), de->bInterval); if(de->bEndpointAddress & 0x80) fprint(2, " [IN]"); else fprint(2, " [OUT]"); switch(de->bmAttributes&0x33){ case 0: fprint(2, " [Control]"); break; case 1: fprint(2, " [Iso]"); switch(de->bmAttributes&0xc){ case 0x4: fprint(2, " [Asynchronous]"); break; case 0x8: fprint(2, " [Adaptive]"); break; case 0xc: fprint(2, " [Synchronous]"); break; } break; case 2: fprint(2, " [Bulk]"); break; case 3: fprint(2, " [Interrupt]"); break; } if(b[0] == 9) fprint(2, "refresh %d synchaddress %d", b[7], b[8]); fprint(2, "\n"); } if (c < 0 || ifc < 0 || dalt < 0) { fprint(2, "Unexpected ENDPOINT message\n"); return; } dif = d->config[c]->iface[ifc]; if (dif == nil) sysfatal("d->config[%d]->iface[%d] == nil", c, ifc); if (dif->dalt[dalt] == nil) dif->dalt[dalt] = mallocz(sizeof(Dalt),1); dif->dalt[dalt]->attrib = de->bmAttributes; dif->dalt[dalt]->interval = de->bInterval; ep = de->bEndpointAddress & 0xf; dep = d->ep[ep]; if(debug) fprint(2, "%s: endpoint addr %d\n", argv0, ep); if(dep == nil){ d->ep[ep] = dep = newendpt(d, ep, class); dep->dir = de->bEndpointAddress & 0x80 ? Ein : Eout; }else if ((dep->addr&0x80) != (de->bEndpointAddress&0x80)) dep->dir = Eboth; dep->maxpkt = GET2(de->wMaxPacketSize); dep->addr = de->bEndpointAddress; dep->type = de->bmAttributes & 0x03; dep->isotype = (de->bmAttributes>>2) & 0x03; dep->csp = csp; dep->conf = d->config[c]; dep->iface = dif; for(i = 0; i < nelem(dif->endpt); i++) if(dif->endpt[i] == nil){ dif->endpt[i] = dep; break; } if(i == nelem(dif->endpt)) fprint(2, "Too many endpoints\n"); if (d->nif <= ep) d->nif = ep+1; break; default: assert(nelem(dprinter) == 0x100); f = dprinter[b[1]]; if(f != nil){ (*f)(d, c, dalt<<24 | ifc<<16 | (csp&0xffff), b, b[0]); if(debug & Dbginfo) fprint(2, "\n"); }else if(verbose){ int i; switch(b[1]){ case DEVICE: fprint(2, "(device)"); break; case STRING: fprint(2, "(string)"); break; default: fprint(2, "(unknown type)"); } for(i=1; i