1*9a747e4fSDavid du Colombier #include <u.h> 2*9a747e4fSDavid du Colombier #include <libc.h> 3*9a747e4fSDavid du Colombier #include <thread.h> 4*9a747e4fSDavid du Colombier #include <bio.h> 5*9a747e4fSDavid du Colombier #include "usb.h" 6*9a747e4fSDavid du Colombier 7*9a747e4fSDavid du Colombier static char *type[] = 8*9a747e4fSDavid du Colombier { 9*9a747e4fSDavid du Colombier [Econtrol] "Control", 10*9a747e4fSDavid du Colombier [Eiso] "Isochronous", 11*9a747e4fSDavid du Colombier [Ebulk] "Bulk", 12*9a747e4fSDavid du Colombier [Eintr] "Interrupt", 13*9a747e4fSDavid du Colombier }; 14*9a747e4fSDavid du Colombier 15*9a747e4fSDavid du Colombier static char *isotype[] = 16*9a747e4fSDavid du Colombier { 17*9a747e4fSDavid du Colombier [Eunknown] "", 18*9a747e4fSDavid du Colombier [Easync] " (Asynchronous)", 19*9a747e4fSDavid du Colombier [Eadapt] " (Adaptive)", 20*9a747e4fSDavid du Colombier [Esync] " (Synchronous)", 21*9a747e4fSDavid du Colombier }; 22*9a747e4fSDavid du Colombier 23*9a747e4fSDavid du Colombier void 24*9a747e4fSDavid du Colombier dumpstring(int fd, char *prefix, Device *d, int index) 25*9a747e4fSDavid du Colombier { 26*9a747e4fSDavid du Colombier char *s; 27*9a747e4fSDavid du Colombier 28*9a747e4fSDavid du Colombier if(index == 0) 29*9a747e4fSDavid du Colombier return; 30*9a747e4fSDavid du Colombier s = d->strings[index]; 31*9a747e4fSDavid du Colombier if(s == nil) 32*9a747e4fSDavid du Colombier fprint(fd, "%s<string %d>\n", prefix, index); 33*9a747e4fSDavid du Colombier else 34*9a747e4fSDavid du Colombier fprint(fd, "%s%s\n", prefix, s); 35*9a747e4fSDavid du Colombier } 36*9a747e4fSDavid du Colombier 37*9a747e4fSDavid du Colombier void 38*9a747e4fSDavid du Colombier dumpdesc(int fd, char *prefix, Ddesc *desc) 39*9a747e4fSDavid du Colombier { 40*9a747e4fSDavid du Colombier uchar *p; 41*9a747e4fSDavid du Colombier int i, j, len; 42*9a747e4fSDavid du Colombier 43*9a747e4fSDavid du Colombier if(desc->ndesc == 0) 44*9a747e4fSDavid du Colombier return; 45*9a747e4fSDavid du Colombier fprint(fd, "%s%d descriptors\n", prefix, desc->ndesc); 46*9a747e4fSDavid du Colombier p = desc->data; 47*9a747e4fSDavid du Colombier for(i = 0; i < desc->ndesc; i++) { 48*9a747e4fSDavid du Colombier fprint(fd, "%s\t", prefix); 49*9a747e4fSDavid du Colombier len = *p++; 50*9a747e4fSDavid du Colombier for(j = 1; j < len; j++) 51*9a747e4fSDavid du Colombier fprint(fd, "%.2ux ", *p++); 52*9a747e4fSDavid du Colombier fprint(fd, "\n"); 53*9a747e4fSDavid du Colombier } 54*9a747e4fSDavid du Colombier } 55*9a747e4fSDavid du Colombier 56*9a747e4fSDavid du Colombier void 57*9a747e4fSDavid du Colombier dumpdevice(int fd, Device *d) 58*9a747e4fSDavid du Colombier { 59*9a747e4fSDavid du Colombier int i, j, k; 60*9a747e4fSDavid du Colombier Dconf *c; 61*9a747e4fSDavid du Colombier Dinf *intf; 62*9a747e4fSDavid du Colombier Dalt *alt; 63*9a747e4fSDavid du Colombier Endpt *ep; 64*9a747e4fSDavid du Colombier 65*9a747e4fSDavid du Colombier fprint(fd, "device %D: %lud.%lud.%lud %.4x/%.4x\n", 66*9a747e4fSDavid du Colombier d, Class(d->csp), Subclass(d->csp), Proto(d->csp), d->vid, d->did); 67*9a747e4fSDavid du Colombier fprint(fd, "\tUSB version: %x.%.2x\n", d->vers>>8, d->vers&0xff); 68*9a747e4fSDavid du Colombier fprint(fd, "\tmaximum control packet size: %d\n", d->max0); 69*9a747e4fSDavid du Colombier fprint(fd, "\tdevice release: %x.%.2x\n", d->release>>8, d->release&0xff); 70*9a747e4fSDavid du Colombier dumpstring(fd, "\tmanufacturer: ", d, d->manufacturer); 71*9a747e4fSDavid du Colombier dumpstring(fd, "\tproduct: ", d, d->product); 72*9a747e4fSDavid du Colombier dumpstring(fd, "\tserial: ", d, d->serial); 73*9a747e4fSDavid du Colombier fprint(fd, "\tconfigurations: %d\n", d->nconf); 74*9a747e4fSDavid du Colombier for(i = 0; i < d->nconf; i++) { 75*9a747e4fSDavid du Colombier c = &d->config[i]; 76*9a747e4fSDavid du Colombier fprint(fd, "\t\tconfiguration %d: %d interfaces, %dmA required\n", c->cval, c->nif, c->milliamps); 77*9a747e4fSDavid du Colombier dumpstring(fd, "\t\tname: ", d, c->config); 78*9a747e4fSDavid du Colombier fprint(fd, "\t\tattributes:"); 79*9a747e4fSDavid du Colombier if(c->attrib & Cbuspowered) 80*9a747e4fSDavid du Colombier fprint(fd, " buspowered"); 81*9a747e4fSDavid du Colombier if(c->attrib & Cselfpowered) 82*9a747e4fSDavid du Colombier fprint(fd, " selfpowered"); 83*9a747e4fSDavid du Colombier if(c->attrib & Cremotewakeup) 84*9a747e4fSDavid du Colombier fprint(fd, " remotewakeup"); 85*9a747e4fSDavid du Colombier fprint(fd, "\n"); 86*9a747e4fSDavid du Colombier dumpdesc(fd, "\t\t\t", &c->desc); 87*9a747e4fSDavid du Colombier for(j = 0; j < c->nif; j++) { 88*9a747e4fSDavid du Colombier intf = &c->iface[j]; 89*9a747e4fSDavid du Colombier fprint(fd, "\t\tinterface %d: %lud.%lud.%lud\n", j, Class(intf->csp), Subclass(intf->csp), Proto(intf->csp)); 90*9a747e4fSDavid du Colombier dumpstring(fd, "\t\tname: ", d, intf->interface); 91*9a747e4fSDavid du Colombier for(alt = intf->alt; alt != nil; alt = alt->next) { 92*9a747e4fSDavid du Colombier fprint(fd, "\t\t\talternate %d: %d endpoints\n", alt->alt, alt->npt); 93*9a747e4fSDavid du Colombier dumpdesc(fd, "\t\t\t\t", &alt->desc); 94*9a747e4fSDavid du Colombier for(k = 0; k < alt->npt; k++) { 95*9a747e4fSDavid du Colombier ep = &alt->ep[k]; 96*9a747e4fSDavid du Colombier fprint(2, "\t\t\t\tendpoint %d-%s: type %s%s maxpkt %d poll %dms\n", 97*9a747e4fSDavid du Colombier ep->addr, ep->dir == Ein ? "in" : "out", type[ep->type], isotype[ep->isotype], 98*9a747e4fSDavid du Colombier ep->maxpkt, ep->pollms); 99*9a747e4fSDavid du Colombier dumpdesc(fd, "\t\t\t\t\t", &ep->desc); 100*9a747e4fSDavid du Colombier } 101*9a747e4fSDavid du Colombier } 102*9a747e4fSDavid du Colombier } 103*9a747e4fSDavid du Colombier } 104*9a747e4fSDavid du Colombier } 105