1 typedef struct Altc Altc; 2 typedef struct Conf Conf; 3 typedef struct DConf DConf; 4 typedef struct DDesc DDesc; 5 typedef struct DDev DDev; 6 typedef struct DEp DEp; 7 typedef struct DIface DIface; 8 typedef struct Desc Desc; 9 typedef struct Dev Dev; 10 typedef struct Ep Ep; 11 typedef struct Iface Iface; 12 typedef struct Usbdev Usbdev; 13 14 enum { 15 /* tunable parameters */ 16 Nconf = 16, /* max. configurations per usb device */ 17 Nep = 64, /* max. endpoints per usb device & per interface */ 18 Nddesc = Nep*2, /* max. device-specific descriptors per usb device */ 19 Niface = 16, /* max. interfaces per configuration */ 20 Naltc = 16, /* max. channels per interface */ 21 Uctries = 4, /* no. of tries for usbcmd */ 22 Ucdelay = 50, /* delay before retrying */ 23 24 /* request type */ 25 Rh2d = 0<<7, /* host to device */ 26 Rd2h = 1<<7, /* device to host */ 27 28 Rstd = 0<<5, /* types */ 29 Rclass = 1<<5, 30 Rvendor = 2<<5, 31 32 Rdev = 0, /* recipients */ 33 Riface = 1, 34 Rep = 2, /* endpoint */ 35 Rother = 3, 36 37 /* standard requests */ 38 Rgetstatus = 0, 39 Rclearfeature = 1, 40 Rsetfeature = 3, 41 Rsetaddress = 5, 42 Rgetdesc = 6, 43 Rsetdesc = 7, 44 Rgetconf = 8, 45 Rsetconf = 9, 46 Rgetiface = 10, 47 Rsetiface = 11, 48 Rsynchframe = 12, 49 50 Rgetcur = 0x81, 51 Rgetmin = 0x82, 52 Rgetmax = 0x83, 53 Rgetres = 0x84, 54 Rsetcur = 0x01, 55 Rsetmin = 0x02, 56 Rsetmax = 0x03, 57 Rsetres = 0x04, 58 59 /* dev classes */ 60 Clnone = 0, /* not in usb */ 61 Claudio = 1, 62 Clcomms = 2, 63 Clhid = 3, 64 Clprinter = 7, 65 Clstorage = 8, 66 Clhub = 9, 67 Cldata = 10, 68 69 /* standard descriptor sizes */ 70 Ddevlen = 18, 71 Dconflen = 9, 72 Difacelen = 9, 73 Deplen = 7, 74 75 /* descriptor types */ 76 Ddev = 1, 77 Dconf = 2, 78 Dstr = 3, 79 Diface = 4, 80 Dep = 5, 81 Dreport = 0x22, 82 Dfunction = 0x24, 83 Dphysical = 0x23, 84 85 /* feature selectors */ 86 Fdevremotewakeup = 1, 87 Fhalt = 0, 88 89 /* device state */ 90 Detached = 0, 91 Attached, 92 Enabled, 93 Assigned, 94 Configured, 95 96 /* endpoint direction */ 97 Ein = 0, 98 Eout, 99 Eboth, 100 101 /* endpoint type */ 102 Econtrol = 0, 103 Eiso = 1, 104 Ebulk = 2, 105 Eintr = 3, 106 107 /* endpoint isotype */ 108 Eunknown = 0, 109 Easync = 1, 110 Eadapt = 2, 111 Esync = 3, 112 113 /* config attrib */ 114 Cbuspowered = 1<<7, 115 Cselfpowered = 1<<6, 116 Cremotewakeup = 1<<5, 117 118 /* report types */ 119 Tmtype = 3<<2, 120 Tmitem = 0xF0, 121 Tmain = 0<<2, 122 Tinput = 0x80, 123 Toutput = 0x90, 124 Tfeature = 0xB0, 125 Tcoll = 0xA0, 126 Tecoll = 0xC0, 127 Tglobal = 1<<2, 128 Tusagepage = 0x00, 129 Tlmin = 0x10, 130 Tlmax = 0x20, 131 Tpmin = 0x30, 132 Tpmax = 0x40, 133 Tunitexp = 0x50, 134 Tunit = 0x60, 135 Trepsize = 0x70, 136 TrepID = 0x80, 137 Trepcount = 0x90, 138 Tpush = 0xA0, 139 Tpop = 0xB0, 140 Tlocal = 2<<2, 141 Tusage = 0x00, 142 Tumin = 0x10, 143 Tumax = 0x20, 144 Tdindex = 0x30, 145 Tdmin = 0x40, 146 Tdmax = 0x50, 147 Tsindex = 0x70, 148 Tsmin = 0x80, 149 Tsmax = 0x90, 150 Tsetdelim = 0xA0, 151 Treserved = 3<<2, 152 Tlong = 0xFE, 153 154 }; 155 156 /* 157 * Usb device (when used for ep0s) or endpoint. 158 * RC: One ref because of existing, another one per ogoing I/O. 159 * per-driver resources (including FS if any) are released by aux 160 * once the last ref is gone. This may include other Devs using 161 * to access endpoints for actual I/O. 162 */ 163 struct Dev 164 { 165 Ref; 166 char* dir; /* path for the endpoint dir */ 167 int id; /* usb id for device or ep. number */ 168 int dfd; /* descriptor for the data file */ 169 int cfd; /* descriptor for the control file */ 170 int maxpkt; /* cached from usb description */ 171 Ref nerrs; /* number of errors in requests */ 172 Usbdev* usb; /* USB description */ 173 void* aux; /* for the device driver */ 174 void (*free)(void*); /* idem. to release aux */ 175 }; 176 177 /* 178 * device description as reported by USB (unpacked). 179 */ 180 struct Usbdev 181 { 182 ulong csp; /* USB class/subclass/proto */ 183 int vid; /* vendor id */ 184 int did; /* product (device) id */ 185 char* vendor; 186 char* product; 187 char* serial; 188 int vsid; 189 int psid; 190 int ssid; 191 int class; /* from descriptor */ 192 int nconf; /* from descriptor */ 193 Conf* conf[Nconf]; /* configurations */ 194 Ep* ep[Nep]; /* all endpoints in device */ 195 Desc* ddesc[Nddesc]; /* (raw) device specific descriptors */ 196 }; 197 198 struct Ep 199 { 200 uchar addr; /* endpt address, 0-15 (|0x80 if Ein) */ 201 uchar dir; /* direction, Ein/Eout */ 202 uchar type; /* Econtrol, Eiso, Ebulk, Eintr */ 203 uchar isotype; /* Eunknown, Easync, Eadapt, Esync */ 204 int id; 205 int maxpkt; /* max. packet size */ 206 int ntds; /* nb. of Tds per µframe */ 207 Conf* conf; /* the endpoint belongs to */ 208 Iface* iface; /* the endpoint belongs to */ 209 }; 210 211 struct Altc 212 { 213 int attrib; 214 int interval; 215 void* aux; /* for the driver program */ 216 }; 217 218 struct Iface 219 { 220 int id; /* interface number */ 221 ulong csp; /* USB class/subclass/proto */ 222 Altc* altc[Naltc]; 223 Ep* ep[Nep]; 224 void* aux; /* for the driver program */ 225 }; 226 227 struct Conf 228 { 229 int cval; /* value for set configuration */ 230 int attrib; 231 int milliamps; /* maximum power in this config. */ 232 Iface* iface[Niface]; 233 }; 234 235 /* 236 * Device-specific descriptors. 237 * They show up mixed with other descriptors 238 * within a configuration. 239 * These are unknown to the library but handed to the driver. 240 */ 241 struct Desc 242 { 243 Conf* conf; /* where this descriptor was read */ 244 Iface* iface; /* last iface before desc in conf. */ 245 Ep* ep; /* last endpt before desc in conf. */ 246 Altc* altc; /* last alt.c. before desc in conf. */ 247 DDesc data; /* unparsed standard USB descriptor */ 248 }; 249 250 struct DDesc 251 { 252 uchar bLength; 253 uchar bDescriptorType; 254 uchar bbytes[1]; 255 /* extra bytes allocated here to keep the rest of it */ 256 }; 257 258 /* 259 * layout of standard descriptor types 260 */ 261 struct DDev 262 { 263 uchar bLength; 264 uchar bDescriptorType; 265 uchar bcdUSB[2]; 266 uchar bDevClass; 267 uchar bDevSubClass; 268 uchar bDevProtocol; 269 uchar bMaxPacketSize0; 270 uchar idVendor[2]; 271 uchar idProduct[2]; 272 uchar bcdDev[2]; 273 uchar iManufacturer; 274 uchar iProduct; 275 uchar iSerialNumber; 276 uchar bNumConfigurations; 277 }; 278 279 struct DConf 280 { 281 uchar bLength; 282 uchar bDescriptorType; 283 uchar wTotalLength[2]; 284 uchar bNumInterfaces; 285 uchar bConfigurationValue; 286 uchar iConfiguration; 287 uchar bmAttributes; 288 uchar MaxPower; 289 }; 290 291 struct DIface 292 { 293 uchar bLength; 294 uchar bDescriptorType; 295 uchar bInterfaceNumber; 296 uchar bAlternateSetting; 297 uchar bNumEndpoints; 298 uchar bInterfaceClass; 299 uchar bInterfaceSubClass; 300 uchar bInterfaceProtocol; 301 uchar iInterface; 302 }; 303 304 struct DEp 305 { 306 uchar bLength; 307 uchar bDescriptorType; 308 uchar bEndpointAddress; 309 uchar bmAttributes; 310 uchar wMaxPacketSize[2]; 311 uchar bInterval; 312 }; 313 314 #define Class(csp) ((csp) & 0xff) 315 #define Subclass(csp) (((csp)>>8) & 0xff) 316 #define Proto(csp) (((csp)>>16) & 0xff) 317 #define CSP(c, s, p) ((c) | (s)<<8 | (p)<<16) 318 319 #define GET2(p) (((p)[1] & 0xFF)<<8 | ((p)[0] & 0xFF)) 320 #define PUT2(p,v) {(p)[0] = (v); (p)[1] = (v)>>8;} 321 #define GET4(p) (((p)[3]&0xFF)<<24 | ((p)[2]&0xFF)<<16 | \ 322 ((p)[1]&0xFF)<<8 | ((p)[0]&0xFF)) 323 #define PUT4(p,v) {(p)[0] = (v); (p)[1] = (v)>>8; \ 324 (p)[2] = (v)>>16; (p)[3] = (v)>>24;} 325 326 #define dprint if(usbdebug)fprint 327 #define ddprint if(usbdebug > 1)fprint 328 329 #pragma varargck type "U" Dev* 330 #pragma varargck argpos devctl 2 331 332 int Ufmt(Fmt *f); 333 char* classname(int c); 334 void closedev(Dev *d); 335 int configdev(Dev *d); 336 int devctl(Dev *dev, char *fmt, ...); 337 void* emallocz(ulong size, int zero); 338 char* estrdup(char *s); 339 int matchdevcsp(char *info, void *a); 340 int finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs); 341 char* hexstr(void *a, int n); 342 int loaddevconf(Dev *d, int n); 343 int loaddevdesc(Dev *d); 344 char* loaddevstr(Dev *d, int sid); 345 Dev* opendev(char *fn); 346 int opendevdata(Dev *d, int mode); 347 Dev* openep(Dev *d, int id); 348 int parseconf(Usbdev *d, Conf *c, uchar *b, int n); 349 int parsedesc(Usbdev *d, Conf *c, uchar *b, int n); 350 int parsedev(Dev *xd, uchar *b, int n); 351 void startdevs(char *args, char *argv[], int argc, int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**)); 352 int unstall(Dev *dev, Dev *ep, int dir); 353 int usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count); 354 355 356 extern int usbdebug; /* more messages for bigger values */ 357 358 359