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);       
>  }

Reply via email to