1906943f9SDavid du Colombier typedef struct Altc Altc; 2906943f9SDavid du Colombier typedef struct Conf Conf; 3906943f9SDavid du Colombier typedef struct DConf DConf; 4906943f9SDavid du Colombier typedef struct DDesc DDesc; 5906943f9SDavid du Colombier typedef struct DDev DDev; 6906943f9SDavid du Colombier typedef struct DEp DEp; 7906943f9SDavid du Colombier typedef struct DIface DIface; 8906943f9SDavid du Colombier typedef struct Desc Desc; 9906943f9SDavid du Colombier typedef struct Dev Dev; 10906943f9SDavid du Colombier typedef struct Ep Ep; 11906943f9SDavid du Colombier typedef struct Iface Iface; 12906943f9SDavid du Colombier typedef struct Usbdev Usbdev; 137f0337cdSDavid du Colombier 1416146bc9SDavid du Colombier enum { 1517a7aae3SDavid du Colombier /* fundamental constants */ 1617a7aae3SDavid du Colombier Nep = 16, /* max. endpoints per usb device & per interface */ 1717a7aae3SDavid du Colombier 1816146bc9SDavid du Colombier /* tunable parameters */ 1916146bc9SDavid du Colombier Nconf = 16, /* max. configurations per usb device */ 2017a7aae3SDavid du Colombier Nddesc = 8*Nep, /* max. device-specific descriptors per usb device */ 2116146bc9SDavid du Colombier Niface = 16, /* max. interfaces per configuration */ 2239dc1420SDavid du Colombier Naltc = 16, /* max. alt configurations per interface */ 2316146bc9SDavid du Colombier Uctries = 4, /* no. of tries for usbcmd */ 24906943f9SDavid du Colombier Ucdelay = 50, /* delay before retrying */ 251b3e7169SDavid du Colombier 26906943f9SDavid du Colombier /* request type */ 27906943f9SDavid du Colombier Rh2d = 0<<7, /* host to device */ 28906943f9SDavid du Colombier Rd2h = 1<<7, /* device to host */ 29906943f9SDavid du Colombier 30906943f9SDavid du Colombier Rstd = 0<<5, /* types */ 317f0337cdSDavid du Colombier Rclass = 1<<5, 327f0337cdSDavid du Colombier Rvendor = 2<<5, 331b3e7169SDavid du Colombier 34906943f9SDavid du Colombier Rdev = 0, /* recipients */ 35906943f9SDavid du Colombier Riface = 1, 36906943f9SDavid du Colombier Rep = 2, /* endpoint */ 377f0337cdSDavid du Colombier Rother = 3, 387f0337cdSDavid du Colombier 397f0337cdSDavid du Colombier /* standard requests */ 40906943f9SDavid du Colombier Rgetstatus = 0, 41906943f9SDavid du Colombier Rclearfeature = 1, 42906943f9SDavid du Colombier Rsetfeature = 3, 43906943f9SDavid du Colombier Rsetaddress = 5, 44906943f9SDavid du Colombier Rgetdesc = 6, 45906943f9SDavid du Colombier Rsetdesc = 7, 46906943f9SDavid du Colombier Rgetconf = 8, 47906943f9SDavid du Colombier Rsetconf = 9, 48906943f9SDavid du Colombier Rgetiface = 10, 49906943f9SDavid du Colombier Rsetiface = 11, 50906943f9SDavid du Colombier Rsynchframe = 12, 517f0337cdSDavid du Colombier 52*153f606aSDavid du Colombier /* standard requests (USB3.0) */ 53*153f606aSDavid du Colombier Rsethubdepth = 12, 54*153f606aSDavid du Colombier Rgetporterrcnt = 13, 55*153f606aSDavid du Colombier 56906943f9SDavid du Colombier Rgetcur = 0x81, 57906943f9SDavid du Colombier Rgetmin = 0x82, 58906943f9SDavid du Colombier Rgetmax = 0x83, 59906943f9SDavid du Colombier Rgetres = 0x84, 60906943f9SDavid du Colombier Rsetcur = 0x01, 61906943f9SDavid du Colombier Rsetmin = 0x02, 62906943f9SDavid du Colombier Rsetmax = 0x03, 63906943f9SDavid du Colombier Rsetres = 0x04, 647f0337cdSDavid du Colombier 65906943f9SDavid du Colombier /* dev classes */ 66906943f9SDavid du Colombier Clnone = 0, /* not in usb */ 67906943f9SDavid du Colombier Claudio = 1, 68906943f9SDavid du Colombier Clcomms = 2, 69906943f9SDavid du Colombier Clhid = 3, 70906943f9SDavid du Colombier Clprinter = 7, 71906943f9SDavid du Colombier Clstorage = 8, 72906943f9SDavid du Colombier Clhub = 9, 73906943f9SDavid du Colombier Cldata = 10, 74906943f9SDavid du Colombier 75906943f9SDavid du Colombier /* standard descriptor sizes */ 76906943f9SDavid du Colombier Ddevlen = 18, 77906943f9SDavid du Colombier Dconflen = 9, 78906943f9SDavid du Colombier Difacelen = 9, 79906943f9SDavid du Colombier Deplen = 7, 807f0337cdSDavid du Colombier 817f0337cdSDavid du Colombier /* descriptor types */ 82906943f9SDavid du Colombier Ddev = 1, 83906943f9SDavid du Colombier Dconf = 2, 84906943f9SDavid du Colombier Dstr = 3, 85906943f9SDavid du Colombier Diface = 4, 86906943f9SDavid du Colombier Dep = 5, 87906943f9SDavid du Colombier Dreport = 0x22, 88906943f9SDavid du Colombier Dfunction = 0x24, 89906943f9SDavid du Colombier Dphysical = 0x23, 907f0337cdSDavid du Colombier 917f0337cdSDavid du Colombier /* feature selectors */ 92906943f9SDavid du Colombier Fdevremotewakeup = 1, 93906943f9SDavid du Colombier Fhalt = 0, 94906943f9SDavid du Colombier 95906943f9SDavid du Colombier /* device state */ 96906943f9SDavid du Colombier Detached = 0, 97906943f9SDavid du Colombier Attached, 98906943f9SDavid du Colombier Enabled, 99906943f9SDavid du Colombier Assigned, 100906943f9SDavid du Colombier Configured, 101906943f9SDavid du Colombier 102906943f9SDavid du Colombier /* endpoint direction */ 103906943f9SDavid du Colombier Ein = 0, 104906943f9SDavid du Colombier Eout, 105906943f9SDavid du Colombier Eboth, 106906943f9SDavid du Colombier 107906943f9SDavid du Colombier /* endpoint type */ 108906943f9SDavid du Colombier Econtrol = 0, 109906943f9SDavid du Colombier Eiso = 1, 110906943f9SDavid du Colombier Ebulk = 2, 111906943f9SDavid du Colombier Eintr = 3, 112906943f9SDavid du Colombier 113906943f9SDavid du Colombier /* endpoint isotype */ 114906943f9SDavid du Colombier Eunknown = 0, 115906943f9SDavid du Colombier Easync = 1, 116906943f9SDavid du Colombier Eadapt = 2, 117906943f9SDavid du Colombier Esync = 3, 118906943f9SDavid du Colombier 119906943f9SDavid du Colombier /* config attrib */ 120906943f9SDavid du Colombier Cbuspowered = 1<<7, 121906943f9SDavid du Colombier Cselfpowered = 1<<6, 122906943f9SDavid du Colombier Cremotewakeup = 1<<5, 1237f0337cdSDavid du Colombier 1247f0337cdSDavid du Colombier /* report types */ 1257f0337cdSDavid du Colombier Tmtype = 3<<2, 1267f0337cdSDavid du Colombier Tmitem = 0xF0, 1277f0337cdSDavid du Colombier Tmain = 0<<2, 1287f0337cdSDavid du Colombier Tinput = 0x80, 1297f0337cdSDavid du Colombier Toutput = 0x90, 1307f0337cdSDavid du Colombier Tfeature = 0xB0, 1317f0337cdSDavid du Colombier Tcoll = 0xA0, 1327f0337cdSDavid du Colombier Tecoll = 0xC0, 1337f0337cdSDavid du Colombier Tglobal = 1<<2, 1347f0337cdSDavid du Colombier Tusagepage = 0x00, 1357f0337cdSDavid du Colombier Tlmin = 0x10, 1367f0337cdSDavid du Colombier Tlmax = 0x20, 1377f0337cdSDavid du Colombier Tpmin = 0x30, 1387f0337cdSDavid du Colombier Tpmax = 0x40, 1397f0337cdSDavid du Colombier Tunitexp = 0x50, 1407f0337cdSDavid du Colombier Tunit = 0x60, 1417f0337cdSDavid du Colombier Trepsize = 0x70, 1427f0337cdSDavid du Colombier TrepID = 0x80, 1437f0337cdSDavid du Colombier Trepcount = 0x90, 1447f0337cdSDavid du Colombier Tpush = 0xA0, 1457f0337cdSDavid du Colombier Tpop = 0xB0, 1467f0337cdSDavid du Colombier Tlocal = 2<<2, 1477f0337cdSDavid du Colombier Tusage = 0x00, 1487f0337cdSDavid du Colombier Tumin = 0x10, 1497f0337cdSDavid du Colombier Tumax = 0x20, 1507f0337cdSDavid du Colombier Tdindex = 0x30, 1517f0337cdSDavid du Colombier Tdmin = 0x40, 1527f0337cdSDavid du Colombier Tdmax = 0x50, 1537f0337cdSDavid du Colombier Tsindex = 0x70, 1547f0337cdSDavid du Colombier Tsmin = 0x80, 1557f0337cdSDavid du Colombier Tsmax = 0x90, 1567f0337cdSDavid du Colombier Tsetdelim = 0xA0, 1577f0337cdSDavid du Colombier Treserved = 3<<2, 1587f0337cdSDavid du Colombier Tlong = 0xFE, 1597f0337cdSDavid du Colombier 1607f0337cdSDavid du Colombier }; 1617f0337cdSDavid du Colombier 162906943f9SDavid du Colombier /* 163906943f9SDavid du Colombier * Usb device (when used for ep0s) or endpoint. 164906943f9SDavid du Colombier * RC: One ref because of existing, another one per ogoing I/O. 165906943f9SDavid du Colombier * per-driver resources (including FS if any) are released by aux 166906943f9SDavid du Colombier * once the last ref is gone. This may include other Devs using 167906943f9SDavid du Colombier * to access endpoints for actual I/O. 168906943f9SDavid du Colombier */ 169906943f9SDavid du Colombier struct Dev 1707f0337cdSDavid du Colombier { 171906943f9SDavid du Colombier Ref; 172906943f9SDavid du Colombier char* dir; /* path for the endpoint dir */ 173906943f9SDavid du Colombier int id; /* usb id for device or ep. number */ 174906943f9SDavid du Colombier int dfd; /* descriptor for the data file */ 175906943f9SDavid du Colombier int cfd; /* descriptor for the control file */ 176*153f606aSDavid du Colombier int isusb3; /* this is a usb3 device */ 177*153f606aSDavid du Colombier int depth; /* hub depth for usb3 hubs */ 178906943f9SDavid du Colombier int maxpkt; /* cached from usb description */ 179906943f9SDavid du Colombier Ref nerrs; /* number of errors in requests */ 180906943f9SDavid du Colombier Usbdev* usb; /* USB description */ 181906943f9SDavid du Colombier void* aux; /* for the device driver */ 182906943f9SDavid du Colombier void (*free)(void*); /* idem. to release aux */ 1837f0337cdSDavid du Colombier }; 1847f0337cdSDavid du Colombier 185906943f9SDavid du Colombier /* 186906943f9SDavid du Colombier * device description as reported by USB (unpacked). 187906943f9SDavid du Colombier */ 188906943f9SDavid du Colombier struct Usbdev 1897f0337cdSDavid du Colombier { 190906943f9SDavid du Colombier ulong csp; /* USB class/subclass/proto */ 191906943f9SDavid du Colombier int vid; /* vendor id */ 192906943f9SDavid du Colombier int did; /* product (device) id */ 19380e9508eSDavid du Colombier int dno; /* device release number */ 194906943f9SDavid du Colombier char* vendor; 195906943f9SDavid du Colombier char* product; 196906943f9SDavid du Colombier char* serial; 197906943f9SDavid du Colombier int vsid; 198906943f9SDavid du Colombier int psid; 199906943f9SDavid du Colombier int ssid; 200906943f9SDavid du Colombier int class; /* from descriptor */ 201906943f9SDavid du Colombier int nconf; /* from descriptor */ 202906943f9SDavid du Colombier Conf* conf[Nconf]; /* configurations */ 203906943f9SDavid du Colombier Ep* ep[Nep]; /* all endpoints in device */ 204906943f9SDavid du Colombier Desc* ddesc[Nddesc]; /* (raw) device specific descriptors */ 205906943f9SDavid du Colombier }; 206906943f9SDavid du Colombier 207906943f9SDavid du Colombier struct Ep 208906943f9SDavid du Colombier { 209906943f9SDavid du Colombier uchar addr; /* endpt address, 0-15 (|0x80 if Ein) */ 21015174232SDavid du Colombier uchar dir; /* direction, Ein/Eout */ 21115174232SDavid du Colombier uchar type; /* Econtrol, Eiso, Ebulk, Eintr */ 21215174232SDavid du Colombier uchar isotype; /* Eunknown, Easync, Eadapt, Esync */ 2137f0337cdSDavid du Colombier int id; 214906943f9SDavid du Colombier int maxpkt; /* max. packet size */ 215906943f9SDavid du Colombier int ntds; /* nb. of Tds per µframe */ 216906943f9SDavid du Colombier Conf* conf; /* the endpoint belongs to */ 217906943f9SDavid du Colombier Iface* iface; /* the endpoint belongs to */ 2187f0337cdSDavid du Colombier }; 2197f0337cdSDavid du Colombier 220906943f9SDavid du Colombier struct Altc 2217f0337cdSDavid du Colombier { 2227f0337cdSDavid du Colombier int attrib; 2237f0337cdSDavid du Colombier int interval; 224906943f9SDavid du Colombier void* aux; /* for the driver program */ 2257f0337cdSDavid du Colombier }; 2267f0337cdSDavid du Colombier 227906943f9SDavid du Colombier struct Iface 2287f0337cdSDavid du Colombier { 229906943f9SDavid du Colombier int id; /* interface number */ 2307f0337cdSDavid du Colombier ulong csp; /* USB class/subclass/proto */ 231906943f9SDavid du Colombier Altc* altc[Naltc]; 232906943f9SDavid du Colombier Ep* ep[Nep]; 233906943f9SDavid du Colombier void* aux; /* for the driver program */ 2347f0337cdSDavid du Colombier }; 2357f0337cdSDavid du Colombier 236906943f9SDavid du Colombier struct Conf 2377f0337cdSDavid du Colombier { 2387f0337cdSDavid du Colombier int cval; /* value for set configuration */ 2397f0337cdSDavid du Colombier int attrib; 240906943f9SDavid du Colombier int milliamps; /* maximum power in this config. */ 24116146bc9SDavid du Colombier Iface* iface[Niface]; 2427f0337cdSDavid du Colombier }; 2437f0337cdSDavid du Colombier 244906943f9SDavid du Colombier /* 245906943f9SDavid du Colombier * Device-specific descriptors. 246906943f9SDavid du Colombier * They show up mixed with other descriptors 247906943f9SDavid du Colombier * within a configuration. 248906943f9SDavid du Colombier * These are unknown to the library but handed to the driver. 249906943f9SDavid du Colombier */ 25042704577SDavid du Colombier struct DDesc 25142704577SDavid du Colombier { 25242704577SDavid du Colombier uchar bLength; 25342704577SDavid du Colombier uchar bDescriptorType; 25442704577SDavid du Colombier uchar bbytes[1]; 25542704577SDavid du Colombier /* extra bytes allocated here to keep the rest of it */ 25642704577SDavid du Colombier }; 25742704577SDavid du Colombier 258906943f9SDavid du Colombier struct Desc 2597f0337cdSDavid du Colombier { 260906943f9SDavid du Colombier Conf* conf; /* where this descriptor was read */ 261906943f9SDavid du Colombier Iface* iface; /* last iface before desc in conf. */ 262906943f9SDavid du Colombier Ep* ep; /* last endpt before desc in conf. */ 263906943f9SDavid du Colombier Altc* altc; /* last alt.c. before desc in conf. */ 264906943f9SDavid du Colombier DDesc data; /* unparsed standard USB descriptor */ 2659a747e4fSDavid du Colombier }; 2669a747e4fSDavid du Colombier 2677f0337cdSDavid du Colombier /* 2687f0337cdSDavid du Colombier * layout of standard descriptor types 2697f0337cdSDavid du Colombier */ 270906943f9SDavid du Colombier struct DDev 2717f0337cdSDavid du Colombier { 272906943f9SDavid du Colombier uchar bLength; 273906943f9SDavid du Colombier uchar bDescriptorType; 274906943f9SDavid du Colombier uchar bcdUSB[2]; 275906943f9SDavid du Colombier uchar bDevClass; 276906943f9SDavid du Colombier uchar bDevSubClass; 277906943f9SDavid du Colombier uchar bDevProtocol; 278906943f9SDavid du Colombier uchar bMaxPacketSize0; 279906943f9SDavid du Colombier uchar idVendor[2]; 280906943f9SDavid du Colombier uchar idProduct[2]; 281906943f9SDavid du Colombier uchar bcdDev[2]; 282906943f9SDavid du Colombier uchar iManufacturer; 283906943f9SDavid du Colombier uchar iProduct; 284906943f9SDavid du Colombier uchar iSerialNumber; 285906943f9SDavid du Colombier uchar bNumConfigurations; 2867f0337cdSDavid du Colombier }; 2877f0337cdSDavid du Colombier 288906943f9SDavid du Colombier struct DConf 2897f0337cdSDavid du Colombier { 290906943f9SDavid du Colombier uchar bLength; 291906943f9SDavid du Colombier uchar bDescriptorType; 292906943f9SDavid du Colombier uchar wTotalLength[2]; 293906943f9SDavid du Colombier uchar bNumInterfaces; 294906943f9SDavid du Colombier uchar bConfigurationValue; 295906943f9SDavid du Colombier uchar iConfiguration; 296906943f9SDavid du Colombier uchar bmAttributes; 297906943f9SDavid du Colombier uchar MaxPower; 298906943f9SDavid du Colombier }; 299906943f9SDavid du Colombier 300906943f9SDavid du Colombier struct DIface 301906943f9SDavid du Colombier { 302906943f9SDavid du Colombier uchar bLength; 303906943f9SDavid du Colombier uchar bDescriptorType; 304906943f9SDavid du Colombier uchar bInterfaceNumber; 305906943f9SDavid du Colombier uchar bAlternateSetting; 306906943f9SDavid du Colombier uchar bNumEndpoints; 307906943f9SDavid du Colombier uchar bInterfaceClass; 308906943f9SDavid du Colombier uchar bInterfaceSubClass; 309906943f9SDavid du Colombier uchar bInterfaceProtocol; 310906943f9SDavid du Colombier uchar iInterface; 311906943f9SDavid du Colombier }; 312906943f9SDavid du Colombier 313906943f9SDavid du Colombier struct DEp 314906943f9SDavid du Colombier { 315906943f9SDavid du Colombier uchar bLength; 316906943f9SDavid du Colombier uchar bDescriptorType; 317906943f9SDavid du Colombier uchar bEndpointAddress; 318906943f9SDavid du Colombier uchar bmAttributes; 319906943f9SDavid du Colombier uchar wMaxPacketSize[2]; 320906943f9SDavid du Colombier uchar bInterval; 321906943f9SDavid du Colombier }; 3227f0337cdSDavid du Colombier 3239a747e4fSDavid du Colombier #define Class(csp) ((csp) & 0xff) 3249a747e4fSDavid du Colombier #define Subclass(csp) (((csp)>>8) & 0xff) 3259a747e4fSDavid du Colombier #define Proto(csp) (((csp)>>16) & 0xff) 32616146bc9SDavid du Colombier #define CSP(c, s, p) ((c) | (s)<<8 | (p)<<16) 32716146bc9SDavid du Colombier 32816146bc9SDavid du Colombier #define GET2(p) (((p)[1] & 0xFF)<<8 | ((p)[0] & 0xFF)) 32916146bc9SDavid du Colombier #define PUT2(p,v) {(p)[0] = (v); (p)[1] = (v)>>8;} 33016146bc9SDavid du Colombier #define GET4(p) (((p)[3]&0xFF)<<24 | ((p)[2]&0xFF)<<16 | \ 33116146bc9SDavid du Colombier ((p)[1]&0xFF)<<8 | ((p)[0]&0xFF)) 33216146bc9SDavid du Colombier #define PUT4(p,v) {(p)[0] = (v); (p)[1] = (v)>>8; \ 33316146bc9SDavid du Colombier (p)[2] = (v)>>16; (p)[3] = (v)>>24;} 33416146bc9SDavid du Colombier 335906943f9SDavid du Colombier #define dprint if(usbdebug)fprint 336906943f9SDavid du Colombier #define ddprint if(usbdebug > 1)fprint 3379a747e4fSDavid du Colombier 338906943f9SDavid du Colombier #pragma varargck type "U" Dev* 339906943f9SDavid du Colombier #pragma varargck argpos devctl 2 3409a747e4fSDavid du Colombier 341906943f9SDavid du Colombier int Ufmt(Fmt *f); 342906943f9SDavid du Colombier char* classname(int c); 343906943f9SDavid du Colombier void closedev(Dev *d); 344906943f9SDavid du Colombier int configdev(Dev *d); 345906943f9SDavid du Colombier int devctl(Dev *dev, char *fmt, ...); 346906943f9SDavid du Colombier void* emallocz(ulong size, int zero); 347906943f9SDavid du Colombier char* estrdup(char *s); 348906943f9SDavid du Colombier int matchdevcsp(char *info, void *a); 349906943f9SDavid du Colombier int finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs); 350906943f9SDavid du Colombier char* hexstr(void *a, int n); 351906943f9SDavid du Colombier int loaddevconf(Dev *d, int n); 352906943f9SDavid du Colombier int loaddevdesc(Dev *d); 353906943f9SDavid du Colombier char* loaddevstr(Dev *d, int sid); 354906943f9SDavid du Colombier Dev* opendev(char *fn); 355906943f9SDavid du Colombier int opendevdata(Dev *d, int mode); 356906943f9SDavid du Colombier Dev* openep(Dev *d, int id); 357906943f9SDavid du Colombier int parseconf(Usbdev *d, Conf *c, uchar *b, int n); 358906943f9SDavid du Colombier int parsedesc(Usbdev *d, Conf *c, uchar *b, int n); 359906943f9SDavid du Colombier int parsedev(Dev *xd, uchar *b, int n); 360906943f9SDavid du Colombier void startdevs(char *args, char *argv[], int argc, int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**)); 361906943f9SDavid du Colombier int unstall(Dev *dev, Dev *ep, int dir); 362906943f9SDavid du Colombier int usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count); 3637f0337cdSDavid du Colombier 364906943f9SDavid du Colombier 365906943f9SDavid du Colombier extern int usbdebug; /* more messages for bigger values */ 366906943f9SDavid du Colombier 367906943f9SDavid du Colombier 368