From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: To: 9fans@cse.psu.edu Subject: Re: [9fans] usbd problem From: "Fco. J. Ballesteros" Date: Tue, 12 Feb 2008 15:42:03 +0100 In-Reply-To: <964c1529df94a5c6ba189fb0520afbc5@plan9.bell-labs.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Topicbox-Message-UUID: 5162d658-ead3-11e9-9d60-3106f5b1d025 Warning!, the dump.c I sent Sape has a bug. search for "len =3D b[0]-1", in pdesc(), replace that with "len =3D b[0]". sorry for the mistake. > From: sape@plan9.bell-labs.com > To: 9fans@cse.psu.edu > Reply-To: 9fans@cse.psu.edu > Date: Tue Feb 12 15:36:36 CET 2008 > Subject: Re: [9fans] usbd problem > =20 > >> 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. > >>=20 > >> Sape > >=20 > > excellent. i'll give it a shot. > >=20 > > - erik > =20 > Give it a shot now: > /sys/src/cmd/usb/lib/dump.c > =20 > =20 > !=E2=80=94 dump.c.txt > =20 > #include > #include > #include > #include > #include "usb.h" > =20 > int verbose; > =20 > typedef struct Flags Flags; > typedef struct Classes Classes; > =20 > struct Flags { > int bit; > char* name0; > char* name1; > }; > =20 > struct Classes { > char* name; > struct { > char* name; > char* proto[4]; > } subclass[4]; > }; > =20 > static Classes classname[] =3D { > [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"}, > }; > =20 > static void pflag(Flags*, uint); > =20 > char * > sclass(char *p, char *e, ulong csp) > { > Classes *cs; > int c, s, pr; > =20 > c =3D Class(csp); > s =3D Subclass(csp); > pr =3D Proto(csp); > if(c < 0 || c >=3D nelem(classname) || (cs =3D &classname[c])->name =3D= =3D nil) > return seprint(p, e, "%d.%d.%d", c, s, pr); > p =3D seprint(p, e, "%s.", cs->name); > if(s < 0 || s >=3D nelem(cs->subclass) || cs->subclass[s].name =3D=3D= nil) > p =3D seprint(p, e, "%d.%d", s, pr); > else{ > p =3D seprint(p, e, "%s.", cs->subclass[s].name); > if(pr < 0 || pr >=3D nelem(cs->subclass[s].proto) || cs->subclass[s]= .proto[pr] =3D=3D nil) > p =3D seprint(p, e, "%d", pr); > else > p =3D seprint(p, e, "%s", cs->subclass[s].proto[pr]); > } > return p; > } > =20 > void > pdevice(Device *, int, ulong, void *b, int n) > { > DDevice *d; > char scbuf[64]; > =20 > if(n < DDEVLEN) > return; > d =3D 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); > } > } > =20 > void > phid(Device *, int, ulong, void *b, int n) > { > DHid *d; > =20 > if(n < DHIDLEN){ > fprint(2, "%s: hid too short\n", argv0); > return; > } > d =3D 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)); > } > =20 > static Flags ioflags[] =3D { > {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}, > }; > =20 > static void > pflag(Flags *tab, uint v) > { > char buf[200], *s; > int n; > =20 > n =3D 0; > buf[0] =3D 0; > for(; tab->name0 !=3D nil; tab++){ > if(v & (1<bit)) > s =3D tab->name1; > else > s =3D tab->name0; > if(s !=3D nil && *s) > n +=3D snprint(buf+n, sizeof(buf)-n, ", %s", s); > } > if((debug & Dbginfo) && buf[0]) > fprint(2, "[%s]", buf+2); > } > =20 > void > preport(Device *, int, ulong, byte *b, int n) > { > byte *s, *es; > int tag, nb, i, indent; > int v; > Flags *tab; > =20 > s =3D b+2; > es =3D b+n; > indent =3D 0; > while(s < es){ > for(i=3D0; i fprint(2, " "); > tag =3D *s++; > if(tag =3D=3D Tlong){ > fprint(2, "long report tag"); > return; > } > if((nb =3D tag&3) =3D=3D 3) > nb =3D 4; > v =3D 0; > for(i=3D0; i v |=3D s[i] << (i*8); > switch(tag & Tmtype){ > case Treserved: > if(tag =3D=3D Tlong){ > fprint(2, "long report tag"); > return; > } > fprint(2, "illegal tag"); > return; > case Tmain: > tab =3D nil; > if (debug & Dbginfo) { > switch(tag & Tmitem){ > case Tinput: > fprint(2, "Input"); > tab =3D ioflags; > break; > case Toutput: > fprint(2, "Output"); > tab =3D ioflags; > break; > case Tfeature: > fprint(2, "Feature"); > tab =3D 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, "=3D%#ux", v); > if(tab !=3D 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 +=3D nb; > } > } > =20 > void > phub(Device *, int, ulong, void *b, int n) > { > DHub *d; > =20 > if(n < DHUBLEN) > return; > d =3D 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]); > } > =20 > void > pstring(Device *, int, ulong, void *b, int n) > { > byte *rb; > char *s; > Rune r; > int l; > =20 > if(n <=3D 2){ > fprint(2, "\"\""); > return; > } > if(n & 1){ > fprint(2, "illegal count\n"); > return; > } > n =3D (n - 2)/2; > rb =3D (byte*)b + 2; > s =3D malloc(n*UTFmax+1); > for(l=3D0; --n >=3D 0; rb +=3D 2){ > r =3D GET2(rb); > l +=3D runetochar(s+l, &r); > } > s[l] =3D 0; > fprint(2, "\"%s\"", s); > free(s); > } > =20 > void > pcs_raw(char *tag, byte *b, int n) > { > int i; > =20 > if (debug & Dbginfo) { > fprint(2, "%s", tag); > for(i=3D2; i fprint(2, " %.2x", b[i]); > } > } > =20 > static void > pcs_config(Device *, int, ulong, void *b, int n) > { > pcs_raw("CS_CONFIG", b, n); > } > =20 > static void > pcs_string(Device *, ulong, void *b, int n) > { > pcs_raw("CS_STRING", b, n); > } > =20 > static void > pcs_endpoint(Device *, int, ulong, void *bb, int n) > { > byte *b =3D bb; > =20 > 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); > } > } > } > =20 > static void > pcs_interface(Device *, int n, ulong, void *bb, int nb) > { > =20 > if ((debug & Dbginfo) && n >=3D 0) > pcs_raw("CS_INTERFACE", bb, nb); > } > =20 > 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]; > =20 > class =3D Class(csp); > dalt =3D -1; > ifc =3D -1; > if (c >=3D 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 =3D -1; > while(n > 2 && b[0] && b[0] <=3D 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 =3D (DConfig*)b; > d->config[c]->nif =3D dc->bNumInterfaces; > d->config[c]->cval =3D dc->bConfigurationValue; > d->config[c]->attrib =3D dc->bmAttributes; > d->config[c]->milliamps =3D dc->MaxPower*2; > d->nif +=3D 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 =3D (DInterface *)b; > class =3D di->bInterfaceClass; > subclass =3D di->bInterfaceSubClass; > proto =3D di->bInterfaceProtocol; > csp =3D 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 pro= to %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 =3D di->bInterfaceNumber; > dalt =3D di->bAlternateSetting; > if (ifc < 0 || ifc >=3D nelem(d->config[c]->iface)) > sysfatal("Bad interface number %d", ifc); > if (dalt < 0 || > dalt >=3D nelem(d->config[c]->iface[ifc]->dalt)) > sysfatal("Bad alternate number %d", dalt); > if (d->config[c] =3D=3D nil) > sysfatal("No config"); > if (ifc =3D=3D 0) { > if (c =3D=3D 0) > d->ep[0]->csp =3D csp; > d->config[c]->csp =3D csp; > } > dif =3D d->config[c]->iface[ifc]; > if (dif =3D=3D nil) { > d->config[c]->iface[ifc] =3D dif =3D > mallocz(sizeof(Dinf), 1); > dif->csp =3D csp; > } > dif->interface =3D di->bInterfaceNumber; > break; > case ENDPOINT: > if(n < DENDPLEN) > return; > de =3D (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] =3D=3D 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 =3D d->config[c]->iface[ifc]; > if (dif =3D=3D nil) > sysfatal("d->config[%d]->iface[%d] =3D=3D nil", > c, ifc); > if (dif->dalt[dalt] =3D=3D nil) > dif->dalt[dalt] =3D mallocz(sizeof(Dalt),1); > dif->dalt[dalt]->attrib =3D de->bmAttributes; > dif->dalt[dalt]->interval =3D de->bInterval; > ep =3D de->bEndpointAddress & 0xf; > dep =3D d->ep[ep]; > if(debug) > fprint(2, "%s: endpoint addr %d\n", argv0, ep); > if(dep =3D=3D nil){ > d->ep[ep] =3D dep =3D newendpt(d, ep, class); > dep->dir =3D de->bEndpointAddress & 0x80 > ? Ein : Eout; > }else if ((dep->addr&0x80) !=3D > (de->bEndpointAddress&0x80)) > dep->dir =3D Eboth; > dep->maxpkt =3D GET2(de->wMaxPacketSize); > dep->addr =3D de->bEndpointAddress; > dep->type =3D de->bmAttributes & 0x03; > dep->isotype =3D (de->bmAttributes>>2) & 0x03; > dep->csp =3D csp; > dep->conf =3D d->config[c]; > dep->iface =3D dif; > for(i =3D 0; i < nelem(dif->endpt); i++) > if(dif->endpt[i] =3D=3D nil){ > dif->endpt[i] =3D dep; > break; > } > if(i =3D=3D nelem(dif->endpt)) > fprint(2, "Too many endpoints\n"); > if (d->nif <=3D ep) > d->nif =3D ep+1; > break; > default: > assert(nelem(dprinter) =3D=3D 0x100); > f =3D dprinter[b[1]]; > if(f !=3D nil){ > (*f)(d, c, dalt<<24 | ifc<<16 | (csp&0xffff), > b, b[0]); > if(debug & Dbginfo) > fprint(2, "\n"); > }else > if(verbose){ > int i; > =20 > switch(b[1]){ > case DEVICE: > fprint(2, "(device)"); > break; > case STRING: > fprint(2, "(string)"); > break; > default: > fprint(2, "(unknown type)"); > } > for(i=3D1; i fprint(2, " %.2x", b[i]); > fprint(2, "\n"); > }else if(debug & Dbginfo) > fprint(2, "\n"); > break; > } > len =3D b[0]; > n -=3D len; > b +=3D len; > } > if(n) > fprint(2, "pdesc: %d bytes left unparsed, b[0]=3D%d, b[-len]=3D%d, l= en=3D%d\n", n, b[0], b[-len], len);=09 > }