Warning!, the dump.c I sent Sape has a bug. search for "len = b[0]-1", in pdesc(), replace that with "len = b[0]".
sorry for the mistake. > From: [EMAIL PROTECTED] > To: [email protected] > Reply-To: [email protected] > Date: Tue Feb 12 15:36:36 CET 2008 > Subject: Re: [9fans] usbd problem > > >> 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 > > > !— dump.c.txt > > #include <u.h> > #include <libc.h> > #include <thread.h> > #include <bio.h> > #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<<tab->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; i<indent; i++) > fprint(2, " "); > tag = *s++; > if(tag == Tlong){ > fprint(2, "long report tag"); > return; > } > if((nb = tag&3) == 3) > nb = 4; > v = 0; > for(i=0; i<nb; i++) > v |= s[i] << (i*8); > switch(tag & Tmtype){ > case Treserved: > if(tag == Tlong){ > fprint(2, "long report tag"); > return; > } > fprint(2, "illegal tag"); > return; > case Tmain: > tab = nil; > if (debug & Dbginfo) { > switch(tag & Tmitem){ > case Tinput: > fprint(2, "Input"); > tab = ioflags; > break; > case Toutput: > fprint(2, "Output"); > tab = ioflags; > break; > case Tfeature: > fprint(2, "Feature"); > tab = ioflags; > break; > case Tcoll: > fprint(2, "Collection"); > indent++; > break; > case Tecoll: > fprint(2, "End Collection"); > indent--; > break; > default: > fprint(2, "unexpected item %.2x", tag); > } > fprint(2, "=%#ux", v); > if(tab != nil) > pflag(tab, v); > } > break; > case Tglobal: > if (debug & Dbginfo) { > fprint(2, "Global %#ux: ", v); > switch(tag & Tmitem){ > case Tusagepage: > fprint(2, "Usage Page %#ux", v); > break; > case Tlmin: > fprint(2, "Logical Min %d", v); > break; > case Tlmax: > fprint(2, "Logical Max %d", v); > break; > case Tpmin: > fprint(2, "Physical Min %d", v); > break; > case Tpmax: > fprint(2, "Physical Max %d", v); > break; > case Tunitexp: > fprint(2, "Unit Exponent %d", v); > break; > case Tunit: > fprint(2, "Unit %d", v); > break; > case Trepsize: > fprint(2, "Report size %d", v); > break; > case TrepID: > fprint(2, "Report ID %#x", v); > break; > case Trepcount: > fprint(2, "Report Count %d", v); > break; > case Tpush: > fprint(2, "Push %d", v); > break; > case Tpop: > fprint(2, "Pop %d", v); > break; > default: > fprint(2, "Unknown %#ux", v); > break; > } > } > break; > case Tlocal: > if (debug & Dbginfo) { > fprint(2, "Local %#ux: ", v); > switch(tag & Tmitem){ > case Tusage: > fprint(2, "Usage %d", v); > break; > case Tumin: > fprint(2, "Usage min %d", v); > break; > case Tumax: > fprint(2, "Usage max %d", v); > break; > case Tdindex: > fprint(2, "Designator index %d", v); > break; > case Tdmin: > fprint(2, "Designator min %d", v); > break; > case Tdmax: > fprint(2, "Designator max %d", v); > break; > case Tsindex: > fprint(2, "String index %d", v); > break; > case Tsmin: > fprint(2, "String min %d", v); > break; > case Tsmax: > fprint(2, "String max %d", v); > break; > case Tsetdelim: > fprint(2, "Set delim %#ux", v); > break; > default: > fprint(2, "Unknown %#ux", v); > break; > } > } > break; > } > fprint(2, "\n"); > s += nb; > } > } > > void > phub(Device *, int, ulong, void *b, int n) > { > DHub *d; > > if(n < DHUBLEN) > return; > d = b; > if (debug & Dbginfo) > fprint(2, "nport %d charac %#.4x pwr %dms current %dmA remov > %#.2x", > d->bNbrPorts, 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<n; i++) > fprint(2, " %.2x", b[i]); > } > } > > static void > pcs_config(Device *, int, ulong, void *b, int n) > { > pcs_raw("CS_CONFIG", b, n); > } > > static void > pcs_string(Device *, ulong, void *b, int n) > { > pcs_raw("CS_STRING", b, n); > } > > static void > pcs_endpoint(Device *, int, ulong, void *bb, int n) > { > byte *b = bb; > > if (debug & Dbginfo) { > switch(b[2]) { > case 0x01: > fprint(2, > "CS_ENDPOINT for TerminalID %d, delay %d, format_tag %#ux\n", > b[3], b[4], b[5] | (b[6]<<8)); > break; > case 0x02: > fprint(2, > "CS_INTERFACE FORMAT_TYPE %d, channels %d, subframesize %d, resolution %d, > freqtype %d, ", > b[3], b[4], b[5], b[6], b[7]); > fprint(2, "freq0 %d, freq1 %d\n", > b[8] | b[9]<<8 | b[10]<<16, > b[11] | b[12]<<8 | b[13]<<16); > break; > default: > pcs_raw("CS_INTERFACE", bb, n); > } > } > } > > static void > pcs_interface(Device *, int n, ulong, void *bb, int nb) > { > > if ((debug & Dbginfo) && n >= 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<b[0]; i++) > fprint(2, " %.2x", b[i]); > fprint(2, "\n"); > }else if(debug & Dbginfo) > fprint(2, "\n"); > break; > } > len = b[0]; > n -= len; > b += len; > } > if(n) > fprint(2, "pdesc: %d bytes left unparsed, b[0]=%d, b[-len]=%d, > len=%d\n", n, b[0], b[-len], len); > }
