1*906943f9SDavid du Colombier typedef struct Altc Altc; 2*906943f9SDavid du Colombier typedef struct Conf Conf; 3*906943f9SDavid du Colombier typedef struct DConf DConf; 4*906943f9SDavid du Colombier typedef struct DDesc DDesc; 5*906943f9SDavid du Colombier typedef struct DDev DDev; 6*906943f9SDavid du Colombier typedef struct DEp DEp; 7*906943f9SDavid du Colombier typedef struct DIface DIface; 8*906943f9SDavid du Colombier typedef struct Desc Desc; 9*906943f9SDavid du Colombier typedef struct Dev Dev; 10*906943f9SDavid du Colombier typedef struct Ep Ep; 11*906943f9SDavid du Colombier typedef struct Iface Iface; 12*906943f9SDavid du Colombier typedef struct Usbdev Usbdev; 137f0337cdSDavid du Colombier 149a747e4fSDavid du Colombier 159a747e4fSDavid du Colombier enum 169a747e4fSDavid du Colombier { 17*906943f9SDavid du Colombier Uctries = 4, /* nb. of tries for usbcmd */ 18*906943f9SDavid du Colombier Ucdelay = 50, /* delay before retrying */ 191b3e7169SDavid du Colombier 20*906943f9SDavid du Colombier /* request type */ 21*906943f9SDavid du Colombier Rh2d = 0<<7, /* host to device */ 22*906943f9SDavid du Colombier Rd2h = 1<<7, /* device to host */ 23*906943f9SDavid du Colombier 24*906943f9SDavid du Colombier Rstd = 0<<5, /* types */ 257f0337cdSDavid du Colombier Rclass = 1<<5, 267f0337cdSDavid du Colombier Rvendor = 2<<5, 271b3e7169SDavid du Colombier 28*906943f9SDavid du Colombier Rdev = 0, /* recipients */ 29*906943f9SDavid du Colombier Riface = 1, 30*906943f9SDavid du Colombier Rep = 2, /* endpoint */ 317f0337cdSDavid du Colombier Rother = 3, 327f0337cdSDavid du Colombier 337f0337cdSDavid du Colombier /* standard requests */ 34*906943f9SDavid du Colombier Rgetstatus = 0, 35*906943f9SDavid du Colombier Rclearfeature = 1, 36*906943f9SDavid du Colombier Rsetfeature = 3, 37*906943f9SDavid du Colombier Rsetaddress = 5, 38*906943f9SDavid du Colombier Rgetdesc = 6, 39*906943f9SDavid du Colombier Rsetdesc = 7, 40*906943f9SDavid du Colombier Rgetconf = 8, 41*906943f9SDavid du Colombier Rsetconf = 9, 42*906943f9SDavid du Colombier Rgetiface = 10, 43*906943f9SDavid du Colombier Rsetiface = 11, 44*906943f9SDavid du Colombier Rsynchframe = 12, 457f0337cdSDavid du Colombier 46*906943f9SDavid du Colombier Rgetcur = 0x81, 47*906943f9SDavid du Colombier Rgetmin = 0x82, 48*906943f9SDavid du Colombier Rgetmax = 0x83, 49*906943f9SDavid du Colombier Rgetres = 0x84, 50*906943f9SDavid du Colombier Rsetcur = 0x01, 51*906943f9SDavid du Colombier Rsetmin = 0x02, 52*906943f9SDavid du Colombier Rsetmax = 0x03, 53*906943f9SDavid du Colombier Rsetres = 0x04, 547f0337cdSDavid du Colombier 55*906943f9SDavid du Colombier /* dev classes */ 56*906943f9SDavid du Colombier Clnone = 0, /* not in usb */ 57*906943f9SDavid du Colombier Claudio = 1, 58*906943f9SDavid du Colombier Clcomms = 2, 59*906943f9SDavid du Colombier Clhid = 3, 60*906943f9SDavid du Colombier Clprinter = 7, 61*906943f9SDavid du Colombier Clstorage = 8, 62*906943f9SDavid du Colombier Clhub = 9, 63*906943f9SDavid du Colombier Cldata = 10, 64*906943f9SDavid du Colombier 65*906943f9SDavid du Colombier /* standard descriptor sizes */ 66*906943f9SDavid du Colombier Ddevlen = 18, 67*906943f9SDavid du Colombier Dconflen = 9, 68*906943f9SDavid du Colombier Difacelen = 9, 69*906943f9SDavid du Colombier Deplen = 7, 707f0337cdSDavid du Colombier 717f0337cdSDavid du Colombier /* descriptor types */ 72*906943f9SDavid du Colombier Ddev = 1, 73*906943f9SDavid du Colombier Dconf = 2, 74*906943f9SDavid du Colombier Dstr = 3, 75*906943f9SDavid du Colombier Diface = 4, 76*906943f9SDavid du Colombier Dep = 5, 77*906943f9SDavid du Colombier Dreport = 0x22, 78*906943f9SDavid du Colombier Dfunction = 0x24, 79*906943f9SDavid du Colombier Dphysical = 0x23, 807f0337cdSDavid du Colombier 817f0337cdSDavid du Colombier /* feature selectors */ 82*906943f9SDavid du Colombier Fdevremotewakeup = 1, 83*906943f9SDavid du Colombier Fhalt = 0, 84*906943f9SDavid du Colombier 85*906943f9SDavid du Colombier /* parameters */ 86*906943f9SDavid du Colombier Nep = 16, 87*906943f9SDavid du Colombier Niface = 16, 88*906943f9SDavid du Colombier Naltc = 16, 89*906943f9SDavid du Colombier Nddesc = 32, 90*906943f9SDavid du Colombier Nconf = 16, 91*906943f9SDavid du Colombier 92*906943f9SDavid du Colombier /* device state */ 93*906943f9SDavid du Colombier Detached = 0, 94*906943f9SDavid du Colombier Attached, 95*906943f9SDavid du Colombier Enabled, 96*906943f9SDavid du Colombier Assigned, 97*906943f9SDavid du Colombier Configured, 98*906943f9SDavid du Colombier 99*906943f9SDavid du Colombier /* endpoint direction */ 100*906943f9SDavid du Colombier Ein = 0, 101*906943f9SDavid du Colombier Eout, 102*906943f9SDavid du Colombier Eboth, 103*906943f9SDavid du Colombier 104*906943f9SDavid du Colombier /* endpoint type */ 105*906943f9SDavid du Colombier Econtrol = 0, 106*906943f9SDavid du Colombier Eiso = 1, 107*906943f9SDavid du Colombier Ebulk = 2, 108*906943f9SDavid du Colombier Eintr = 3, 109*906943f9SDavid du Colombier 110*906943f9SDavid du Colombier /* endpoint isotype */ 111*906943f9SDavid du Colombier Eunknown = 0, 112*906943f9SDavid du Colombier Easync = 1, 113*906943f9SDavid du Colombier Eadapt = 2, 114*906943f9SDavid du Colombier Esync = 3, 115*906943f9SDavid du Colombier 116*906943f9SDavid du Colombier /* config attrib */ 117*906943f9SDavid du Colombier Cbuspowered = 1<<7, 118*906943f9SDavid du Colombier Cselfpowered = 1<<6, 119*906943f9SDavid du Colombier Cremotewakeup = 1<<5, 1207f0337cdSDavid du Colombier 1217f0337cdSDavid du Colombier /* report types */ 1227f0337cdSDavid du Colombier Tmtype = 3<<2, 1237f0337cdSDavid du Colombier Tmitem = 0xF0, 1247f0337cdSDavid du Colombier Tmain = 0<<2, 1257f0337cdSDavid du Colombier Tinput = 0x80, 1267f0337cdSDavid du Colombier Toutput = 0x90, 1277f0337cdSDavid du Colombier Tfeature = 0xB0, 1287f0337cdSDavid du Colombier Tcoll = 0xA0, 1297f0337cdSDavid du Colombier Tecoll = 0xC0, 1307f0337cdSDavid du Colombier Tglobal = 1<<2, 1317f0337cdSDavid du Colombier Tusagepage = 0x00, 1327f0337cdSDavid du Colombier Tlmin = 0x10, 1337f0337cdSDavid du Colombier Tlmax = 0x20, 1347f0337cdSDavid du Colombier Tpmin = 0x30, 1357f0337cdSDavid du Colombier Tpmax = 0x40, 1367f0337cdSDavid du Colombier Tunitexp = 0x50, 1377f0337cdSDavid du Colombier Tunit = 0x60, 1387f0337cdSDavid du Colombier Trepsize = 0x70, 1397f0337cdSDavid du Colombier TrepID = 0x80, 1407f0337cdSDavid du Colombier Trepcount = 0x90, 1417f0337cdSDavid du Colombier Tpush = 0xA0, 1427f0337cdSDavid du Colombier Tpop = 0xB0, 1437f0337cdSDavid du Colombier Tlocal = 2<<2, 1447f0337cdSDavid du Colombier Tusage = 0x00, 1457f0337cdSDavid du Colombier Tumin = 0x10, 1467f0337cdSDavid du Colombier Tumax = 0x20, 1477f0337cdSDavid du Colombier Tdindex = 0x30, 1487f0337cdSDavid du Colombier Tdmin = 0x40, 1497f0337cdSDavid du Colombier Tdmax = 0x50, 1507f0337cdSDavid du Colombier Tsindex = 0x70, 1517f0337cdSDavid du Colombier Tsmin = 0x80, 1527f0337cdSDavid du Colombier Tsmax = 0x90, 1537f0337cdSDavid du Colombier Tsetdelim = 0xA0, 1547f0337cdSDavid du Colombier Treserved = 3<<2, 1557f0337cdSDavid du Colombier Tlong = 0xFE, 1567f0337cdSDavid du Colombier 1577f0337cdSDavid du Colombier }; 1587f0337cdSDavid du Colombier 159*906943f9SDavid du Colombier /* 160*906943f9SDavid du Colombier * Usb device (when used for ep0s) or endpoint. 161*906943f9SDavid du Colombier * RC: One ref because of existing, another one per ogoing I/O. 162*906943f9SDavid du Colombier * per-driver resources (including FS if any) are released by aux 163*906943f9SDavid du Colombier * once the last ref is gone. This may include other Devs using 164*906943f9SDavid du Colombier * to access endpoints for actual I/O. 165*906943f9SDavid du Colombier */ 166*906943f9SDavid du Colombier struct Dev 1677f0337cdSDavid du Colombier { 168*906943f9SDavid du Colombier Ref; 169*906943f9SDavid du Colombier char* dir; /* path for the endpoint dir */ 170*906943f9SDavid du Colombier int id; /* usb id for device or ep. number */ 171*906943f9SDavid du Colombier int dfd; /* descriptor for the data file */ 172*906943f9SDavid du Colombier int cfd; /* descriptor for the control file */ 173*906943f9SDavid du Colombier int maxpkt; /* cached from usb description */ 174*906943f9SDavid du Colombier Ref nerrs; /* number of errors in requests */ 175*906943f9SDavid du Colombier Usbdev* usb; /* USB description */ 176*906943f9SDavid du Colombier void* aux; /* for the device driver */ 177*906943f9SDavid du Colombier void (*free)(void*); /* idem. to release aux */ 1787f0337cdSDavid du Colombier }; 1797f0337cdSDavid du Colombier 180*906943f9SDavid du Colombier /* 181*906943f9SDavid du Colombier * device description as reported by USB (unpacked). 182*906943f9SDavid du Colombier */ 183*906943f9SDavid du Colombier struct Usbdev 1847f0337cdSDavid du Colombier { 185*906943f9SDavid du Colombier ulong csp; /* USB class/subclass/proto */ 186*906943f9SDavid du Colombier int vid; /* vendor id */ 187*906943f9SDavid du Colombier int did; /* product (device) id */ 188*906943f9SDavid du Colombier char* vendor; 189*906943f9SDavid du Colombier char* product; 190*906943f9SDavid du Colombier char* serial; 191*906943f9SDavid du Colombier int vsid; 192*906943f9SDavid du Colombier int psid; 193*906943f9SDavid du Colombier int ssid; 194*906943f9SDavid du Colombier int class; /* from descriptor */ 195*906943f9SDavid du Colombier int nconf; /* from descriptor */ 196*906943f9SDavid du Colombier Conf* conf[Nconf]; /* configurations */ 197*906943f9SDavid du Colombier Ep* ep[Nep]; /* all endpoints in device */ 198*906943f9SDavid du Colombier Desc* ddesc[Nddesc]; /* (raw) device specific descriptors */ 199*906943f9SDavid du Colombier }; 200*906943f9SDavid du Colombier 201*906943f9SDavid du Colombier struct Ep 202*906943f9SDavid du Colombier { 203*906943f9SDavid du Colombier uchar addr; /* endpt address, 0-15 (|0x80 if Ein) */ 20415174232SDavid du Colombier uchar dir; /* direction, Ein/Eout */ 20515174232SDavid du Colombier uchar type; /* Econtrol, Eiso, Ebulk, Eintr */ 20615174232SDavid du Colombier uchar isotype; /* Eunknown, Easync, Eadapt, Esync */ 2077f0337cdSDavid du Colombier int id; 208*906943f9SDavid du Colombier int maxpkt; /* max. packet size */ 209*906943f9SDavid du Colombier int ntds; /* nb. of Tds per µframe */ 210*906943f9SDavid du Colombier Conf* conf; /* the endpoint belongs to */ 211*906943f9SDavid du Colombier Iface* iface; /* the endpoint belongs to */ 2127f0337cdSDavid du Colombier }; 2137f0337cdSDavid du Colombier 214*906943f9SDavid du Colombier struct Altc 2157f0337cdSDavid du Colombier { 2167f0337cdSDavid du Colombier int attrib; 2177f0337cdSDavid du Colombier int interval; 218*906943f9SDavid du Colombier void* aux; /* for the driver program */ 2197f0337cdSDavid du Colombier }; 2207f0337cdSDavid du Colombier 221*906943f9SDavid du Colombier struct Iface 2227f0337cdSDavid du Colombier { 223*906943f9SDavid du Colombier int id; /* interface number */ 2247f0337cdSDavid du Colombier ulong csp; /* USB class/subclass/proto */ 225*906943f9SDavid du Colombier Altc* altc[Naltc]; 226*906943f9SDavid du Colombier Ep* ep[Nep]; 227*906943f9SDavid du Colombier void* aux; /* for the driver program */ 2287f0337cdSDavid du Colombier }; 2297f0337cdSDavid du Colombier 230*906943f9SDavid du Colombier struct Conf 2317f0337cdSDavid du Colombier { 2327f0337cdSDavid du Colombier int cval; /* value for set configuration */ 2337f0337cdSDavid du Colombier int attrib; 234*906943f9SDavid du Colombier int milliamps; /* maximum power in this config. */ 235*906943f9SDavid du Colombier Iface* iface[Niface]; /* up to 16 interfaces */ 2367f0337cdSDavid du Colombier }; 2377f0337cdSDavid du Colombier 238*906943f9SDavid du Colombier /* 239*906943f9SDavid du Colombier * Device-specific descriptors. 240*906943f9SDavid du Colombier * They show up mixed with other descriptors 241*906943f9SDavid du Colombier * within a configuration. 242*906943f9SDavid du Colombier * These are unknown to the library but handed to the driver. 243*906943f9SDavid du Colombier */ 244*906943f9SDavid du Colombier struct Desc 2457f0337cdSDavid du Colombier { 246*906943f9SDavid du Colombier Conf* conf; /* where this descriptor was read */ 247*906943f9SDavid du Colombier Iface* iface; /* last iface before desc in conf. */ 248*906943f9SDavid du Colombier Ep* ep; /* last endpt before desc in conf. */ 249*906943f9SDavid du Colombier Altc* altc; /* last alt.c. before desc in conf. */ 250*906943f9SDavid du Colombier DDesc data; /* unparsed standard USB descriptor */ 2519a747e4fSDavid du Colombier }; 2529a747e4fSDavid du Colombier 253*906943f9SDavid du Colombier struct DDesc 2547f0337cdSDavid du Colombier { 255*906943f9SDavid du Colombier uchar bLength; 256*906943f9SDavid du Colombier uchar bDescriptorType; 257*906943f9SDavid du Colombier uchar bbytes[1]; 258*906943f9SDavid du Colombier /* extra bytes allocated here to keep the rest of it */ 2597f0337cdSDavid du Colombier }; 2607f0337cdSDavid du Colombier 2617f0337cdSDavid du Colombier /* 2627f0337cdSDavid du Colombier * layout of standard descriptor types 2637f0337cdSDavid du Colombier */ 264*906943f9SDavid du Colombier struct DDev 2657f0337cdSDavid du Colombier { 266*906943f9SDavid du Colombier uchar bLength; 267*906943f9SDavid du Colombier uchar bDescriptorType; 268*906943f9SDavid du Colombier uchar bcdUSB[2]; 269*906943f9SDavid du Colombier uchar bDevClass; 270*906943f9SDavid du Colombier uchar bDevSubClass; 271*906943f9SDavid du Colombier uchar bDevProtocol; 272*906943f9SDavid du Colombier uchar bMaxPacketSize0; 273*906943f9SDavid du Colombier uchar idVendor[2]; 274*906943f9SDavid du Colombier uchar idProduct[2]; 275*906943f9SDavid du Colombier uchar bcdDev[2]; 276*906943f9SDavid du Colombier uchar iManufacturer; 277*906943f9SDavid du Colombier uchar iProduct; 278*906943f9SDavid du Colombier uchar iSerialNumber; 279*906943f9SDavid du Colombier uchar bNumConfigurations; 2807f0337cdSDavid du Colombier }; 2817f0337cdSDavid du Colombier 282*906943f9SDavid du Colombier struct DConf 2837f0337cdSDavid du Colombier { 284*906943f9SDavid du Colombier uchar bLength; 285*906943f9SDavid du Colombier uchar bDescriptorType; 286*906943f9SDavid du Colombier uchar wTotalLength[2]; 287*906943f9SDavid du Colombier uchar bNumInterfaces; 288*906943f9SDavid du Colombier uchar bConfigurationValue; 289*906943f9SDavid du Colombier uchar iConfiguration; 290*906943f9SDavid du Colombier uchar bmAttributes; 291*906943f9SDavid du Colombier uchar MaxPower; 292*906943f9SDavid du Colombier }; 293*906943f9SDavid du Colombier 294*906943f9SDavid du Colombier struct DIface 295*906943f9SDavid du Colombier { 296*906943f9SDavid du Colombier uchar bLength; 297*906943f9SDavid du Colombier uchar bDescriptorType; 298*906943f9SDavid du Colombier uchar bInterfaceNumber; 299*906943f9SDavid du Colombier uchar bAlternateSetting; 300*906943f9SDavid du Colombier uchar bNumEndpoints; 301*906943f9SDavid du Colombier uchar bInterfaceClass; 302*906943f9SDavid du Colombier uchar bInterfaceSubClass; 303*906943f9SDavid du Colombier uchar bInterfaceProtocol; 304*906943f9SDavid du Colombier uchar iInterface; 305*906943f9SDavid du Colombier }; 306*906943f9SDavid du Colombier 307*906943f9SDavid du Colombier struct DEp 308*906943f9SDavid du Colombier { 309*906943f9SDavid du Colombier uchar bLength; 310*906943f9SDavid du Colombier uchar bDescriptorType; 311*906943f9SDavid du Colombier uchar bEndpointAddress; 312*906943f9SDavid du Colombier uchar bmAttributes; 313*906943f9SDavid du Colombier uchar wMaxPacketSize[2]; 314*906943f9SDavid du Colombier uchar bInterval; 315*906943f9SDavid du Colombier }; 3167f0337cdSDavid du Colombier 3179a747e4fSDavid du Colombier #define Class(csp) ((csp)&0xff) 3189a747e4fSDavid du Colombier #define Subclass(csp) (((csp)>>8)&0xff) 3199a747e4fSDavid du Colombier #define Proto(csp) (((csp)>>16)&0xff) 3209a747e4fSDavid du Colombier #define CSP(c, s, p) ((c) | ((s)<<8) | ((p)<<16)) 321*906943f9SDavid du Colombier #define GET2(p) ((((p)[1]&0xFF)<<8)|((p)[0]&0xFF)) 322*906943f9SDavid du Colombier #define PUT2(p,v) {((p)[0] = (v)); ((p)[1] = (v)>>8);} 323*906943f9SDavid du Colombier #define GET4(p) ((((p)[3]&0xFF)<<24)|(((p)[2]&0xFF)<<16)|(((p)[1]&0xFF)<<8)|((p)[0]&0xFF)) 324*906943f9SDavid du Colombier #define PUT4(p,v) {((p)[0] = (v)); ((p)[1] = (v)>>8); ((p)[2] = (v)>>16); ((p)[3] = (v)>>24);} 325*906943f9SDavid du Colombier #define dprint if(usbdebug)fprint 326*906943f9SDavid du Colombier #define ddprint if(usbdebug > 1)fprint 3279a747e4fSDavid du Colombier 3287f0337cdSDavid du Colombier 329*906943f9SDavid du Colombier # |c/f2p *.c |sort +1 3309a747e4fSDavid du Colombier 331*906943f9SDavid du Colombier #pragma varargck type "U" Dev* 332*906943f9SDavid du Colombier #pragma varargck argpos devctl 2 3339a747e4fSDavid du Colombier 334*906943f9SDavid du Colombier int Ufmt(Fmt *f); 335*906943f9SDavid du Colombier char* classname(int c); 336*906943f9SDavid du Colombier void closedev(Dev *d); 337*906943f9SDavid du Colombier int configdev(Dev *d); 338*906943f9SDavid du Colombier int devctl(Dev *dev, char *fmt, ...); 339*906943f9SDavid du Colombier void* emallocz(ulong size, int zero); 340*906943f9SDavid du Colombier char* estrdup(char *s); 341*906943f9SDavid du Colombier int matchdevcsp(char *info, void *a); 342*906943f9SDavid du Colombier int finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs); 343*906943f9SDavid du Colombier char* hexstr(void *a, int n); 344*906943f9SDavid du Colombier int loaddevconf(Dev *d, int n); 345*906943f9SDavid du Colombier int loaddevdesc(Dev *d); 346*906943f9SDavid du Colombier char* loaddevstr(Dev *d, int sid); 347*906943f9SDavid du Colombier Dev* opendev(char *fn); 348*906943f9SDavid du Colombier int opendevdata(Dev *d, int mode); 349*906943f9SDavid du Colombier Dev* openep(Dev *d, int id); 350*906943f9SDavid du Colombier int parseconf(Usbdev *d, Conf *c, uchar *b, int n); 351*906943f9SDavid du Colombier int parsedesc(Usbdev *d, Conf *c, uchar *b, int n); 352*906943f9SDavid du Colombier int parsedev(Dev *xd, uchar *b, int n); 353*906943f9SDavid du Colombier void startdevs(char *args, char *argv[], int argc, int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**)); 354*906943f9SDavid du Colombier int unstall(Dev *dev, Dev *ep, int dir); 355*906943f9SDavid du Colombier int usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count); 3567f0337cdSDavid du Colombier 357*906943f9SDavid du Colombier 358*906943f9SDavid du Colombier extern int usbdebug; /* more messages for bigger values */ 359*906943f9SDavid du Colombier 360*906943f9SDavid du Colombier 361