From: Sape Mullender <sape@plan9.bell-labs.com>
To: 9fans@cse.psu.edu
Subject: Re: [9fans] usbd problem
Date: Tue, 12 Feb 2008 09:35:52 -0500 [thread overview]
Message-ID: <964c1529df94a5c6ba189fb0520afbc5@plan9.bell-labs.com> (raw)
In-Reply-To: <94207d56e098473c63793756938b582a@quanstro.net>
[-- Attachment #1: Type: text/plain, Size: 296 bytes --]
>> 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
[-- Attachment #2: dump.c --]
[-- Type: text/plain, Size: 14184 bytes --]
#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);
}
next prev parent reply other threads:[~2008-02-12 14:35 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-02-12 1:36 erik quanstrom
2008-02-12 8:20 ` Richard Miller
2008-02-12 13:59 ` Sape Mullender
2008-02-12 14:13 ` erik quanstrom
2008-02-12 14:35 ` Sape Mullender [this message]
2008-02-12 14:42 ` Fco. J. Ballesteros
2008-02-13 0:50 ` erik quanstrom
2008-02-13 14:32 ` Richard Miller
2008-02-13 14:45 ` erik quanstrom
2008-02-13 14:52 ` Richard Miller
2008-02-13 15:04 ` erik quanstrom
2008-02-13 16:18 ` Sape Mullender
2008-02-13 16:37 ` erik quanstrom
2008-02-13 17:09 ` Sape Mullender
2008-02-12 8:21 Richard Miller
2008-02-12 13:21 ` erik quanstrom
2008-02-12 21:24 ` Richard Miller
2008-02-12 21:28 ` geoff
2008-02-12 21:33 ` Richard Miller
2008-02-12 21:37 ` erik quanstrom
2008-02-12 22:18 ` Richard Miller
2008-02-12 23:05 ` geoff
2008-02-13 6:31 ` arisawa
2008-02-13 8:25 ` Richard Miller
2008-02-13 8:54 ` arisawa
2008-02-13 10:58 ` Richard Miller
2008-02-13 14:13 ` Richard Miller
2008-02-13 18:49 ` geoff
2008-02-13 15:54 ` Richard Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=964c1529df94a5c6ba189fb0520afbc5@plan9.bell-labs.com \
--to=sape@plan9.bell-labs.com \
--cc=9fans@cse.psu.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).