1 /* 2 * USB implementation for Plan 9 3 * (c) 1998, 1999 C H Forsyth 4 */ 5 6 enum { 7 Dbginfo = 0x01, 8 Dbgfs = 0x02, 9 Dbgproc = 0x04, 10 Dbgcontrol = 0x08, 11 }; 12 13 extern int debug, debugdebug, verbose; 14 15 typedef uchar byte; 16 17 #ifndef CHANNOP 18 typedef struct Ref Ref; 19 20 #define threadprint fprint 21 #endif 22 23 /* 24 * USB definitions 25 */ 26 27 typedef struct DConfig DConfig; 28 typedef struct DDevice DDevice; 29 typedef struct DEndpoint DEndpoint; 30 typedef struct DHid DHid; 31 typedef struct DHub DHub; 32 typedef struct DInterface DInterface; 33 typedef struct Dconf Dconf; 34 typedef struct Dalt Dalt; 35 typedef struct Device Device; 36 typedef struct Dinf Dinf; 37 typedef struct Endpt Endpt; 38 39 typedef struct Namelist Namelist; 40 41 #ifndef nelem 42 #define nelem(x) (sizeof((x))/sizeof((x)[0])) 43 #endif 44 45 #define GET2(p) ((((p)[1]&0xFF)<<8)|((p)[0]&0xFF)) 46 #define PUT2(p,v) {((p)[0] = (v)); ((p)[1] = (v)>>8);} 47 48 enum 49 { 50 TokIN = 0x69, 51 TokOUT = 0xE1, 52 TokSETUP = 0x2D, 53 54 /* request type */ 55 RH2D = 0<<7, 56 RD2H = 1<<7, 57 Rstandard = 0<<5, 58 Rclass = 1<<5, 59 Rvendor = 2<<5, 60 Rdevice = 0, 61 Rinterface = 1, 62 Rendpt = 2, 63 Rother = 3, 64 65 /* standard requests */ 66 GET_STATUS = 0, 67 CLEAR_FEATURE = 1, 68 SET_FEATURE = 3, 69 SET_ADDRESS = 5, 70 GET_DESCRIPTOR = 6, 71 SET_DESCRIPTOR = 7, 72 GET_CONFIGURATION = 8, 73 SET_CONFIGURATION = 9, 74 GET_INTERFACE = 10, 75 SET_INTERFACE = 11, 76 SYNCH_FRAME = 12, 77 78 GET_CUR = 0x81, 79 GET_MIN = 0x82, 80 GET_MAX = 0x83, 81 GET_RES = 0x84, 82 SET_CUR = 0x01, 83 SET_MIN = 0x02, 84 SET_MAX = 0x03, 85 SET_RES = 0x04, 86 87 /* hub class feature selectors */ 88 C_HUB_LOCAL_POWER = 0, 89 C_HUB_OVER_CURRENT, 90 PORT_CONNECTION = 0, 91 PORT_ENABLE = 1, 92 PORT_SUSPEND = 2, 93 PORT_OVER_CURRENT = 3, 94 PORT_RESET = 4, 95 PORT_POWER = 8, 96 PORT_LOW_SPEED = 9, 97 C_PORT_CONNECTION = 16, 98 C_PORT_ENABLE, 99 C_PORT_SUSPEND, 100 C_PORT_OVER_CURRENT, 101 C_PORT_RESET, 102 103 /* descriptor types */ 104 DEVICE = 1, 105 CONFIGURATION = 2, 106 STRING = 3, 107 INTERFACE = 4, 108 ENDPOINT = 5, 109 HID = 0x21, 110 REPORT = 0x22, 111 PHYSICAL = 0x23, 112 HUB = 0x29, 113 114 /* feature selectors */ 115 DEVICE_REMOTE_WAKEUP = 1, 116 ENDPOINT_STALL = 0, 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 /* parameters */ 155 Nendpt = 16, 156 157 /* device state */ 158 Detached = 0, 159 Attached, 160 Enabled, 161 Assigned, 162 Configured, 163 164 /* classes */ 165 Noclass = 0, 166 Hubclass, 167 Otherclass, 168 169 /* endpoint direction */ 170 Ein = 0, 171 Eout, 172 Eboth, 173 174 /* endpoint type */ 175 Econtrol = 0, 176 Eiso = 1, 177 Ebulk = 2, 178 Eintr = 3, 179 180 /* endpoint isotype */ 181 Eunknown = 0, 182 Easync = 1, 183 Eadapt = 2, 184 Esync = 3, 185 }; 186 187 enum 188 { 189 CL_AUDIO = 1, 190 CL_COMMS = 2, 191 CL_HID = 3, 192 CL_PRINTER = 7, 193 CL_STORAGE = 8, 194 CL_HUB = 9, 195 CL_DATA = 10, 196 }; 197 198 struct Endpt 199 { 200 uchar addr; /* endpoint address, 0-15 (|0x80 if direction==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 class; 206 ulong csp; 207 int maxpkt; 208 Device* dev; 209 Dconf* conf; 210 Dinf* iface; 211 }; 212 213 struct Dalt 214 { 215 int attrib; 216 int interval; 217 void* devspec; /* device specific settings */ 218 }; 219 220 struct Dinf 221 { 222 int interface; /* interface number */ 223 ulong csp; /* USB class/subclass/proto */ 224 Dalt* dalt[16]; 225 Endpt* endpt[16]; 226 }; 227 228 struct Dconf 229 { 230 ulong csp; /* USB class/subclass/proto */ 231 int nif; /* number of interfaces */ 232 int cval; /* value for set configuration */ 233 int attrib; 234 int milliamps; /* maximum power in this configuration */ 235 Dinf* iface[16]; /* up to 16 interfaces */ 236 }; 237 238 /* Dconf.attrib */ 239 enum 240 { 241 Cbuspowered = 1<<7, 242 Cselfpowered = 1<<6, 243 Cremotewakeup = 1<<5, 244 }; 245 246 struct Device 247 { 248 Ref; 249 int ctlrno; 250 int ctl; 251 int setup; 252 int status; 253 int state; 254 int id; 255 int class; 256 int npt; 257 int ls; /* low speed */ 258 ulong csp; /* USB class/subclass/proto */ 259 int nconf; 260 int nif; /* number of interfaces (sum of per-conf `nif's) */ 261 int vid; /* vendor id */ 262 int did; /* product (device) id */ 263 Dconf* config[16]; 264 Endpt* ep[Nendpt]; 265 // Device* setupfd; /* for usbprobe */ 266 // Device* cfd; /* for usbprobe */ 267 }; 268 269 /* 270 * layout of standard descriptor types 271 */ 272 struct DDevice 273 { 274 byte bLength; 275 byte bDescriptorType; 276 byte bcdUSB[2]; 277 byte bDeviceClass; 278 byte bDeviceSubClass; 279 byte bDeviceProtocol; 280 byte bMaxPacketSize0; 281 byte idVendor[2]; 282 byte idProduct[2]; 283 byte bcdDevice[2]; 284 byte iManufacturer; 285 byte iProduct; 286 byte iSerialNumber; 287 byte bNumConfigurations; 288 }; 289 #define DDEVLEN 18 290 291 struct DConfig 292 { 293 byte bLength; 294 byte bDescriptorType; 295 byte wTotalLength[2]; 296 byte bNumInterfaces; 297 byte bConfigurationValue; 298 byte iConfiguration; 299 byte bmAttributes; 300 byte MaxPower; 301 }; 302 #define DCONFLEN 9 303 304 struct DInterface 305 { 306 byte bLength; 307 byte bDescriptorType; 308 byte bInterfaceNumber; 309 byte bAlternateSetting; 310 byte bNumEndpoints; 311 byte bInterfaceClass; 312 byte bInterfaceSubClass; 313 byte bInterfaceProtocol; 314 byte iInterface; 315 }; 316 #define DINTERLEN 9 317 318 struct DEndpoint 319 { 320 byte bLength; 321 byte bDescriptorType; 322 byte bEndpointAddress; 323 byte bmAttributes; 324 byte wMaxPacketSize[2]; 325 byte bInterval; 326 }; 327 #define DENDPLEN 7 328 329 struct DHid 330 { 331 byte bLength; 332 byte bDescriptorType; 333 byte bcdHID[2]; 334 byte bCountryCode; 335 byte bNumDescriptors; 336 byte bClassDescriptorType; 337 byte wItemLength[2]; 338 }; 339 #define DHIDLEN 9 340 341 struct DHub 342 { 343 byte bLength; 344 byte bDescriptorType; 345 byte bNbrPorts; 346 byte wHubCharacteristics[2]; 347 byte bPwrOn2PwrGood; 348 byte bHubContrCurrent; 349 byte DeviceRemovable[1]; /* variable length */ 350 /* byte PortPwrCtrlMask; /* variable length, deprecated in USB v1.1 */ 351 }; 352 #define DHUBLEN 9 353 354 struct Namelist 355 { 356 short index; 357 char *name; 358 }; 359 360 typedef struct Drivetab 361 { 362 ulong csp; 363 void (*driver)(Device *d); 364 } Drivetab; 365 366 #define Class(csp) ((csp)&0xff) 367 #define Subclass(csp) (((csp)>>8)&0xff) 368 #define Proto(csp) (((csp)>>16)&0xff) 369 #define CSP(c, s, p) ((c) | ((s)<<8) | ((p)<<16)) 370 371 extern void (*dprinter[0x100])(Device *, int, ulong, void *b, int n); 372 373 /* 374 * format routines 375 */ 376 void pdesc (Device *, int, ulong, byte *, int); 377 void preport (Device *, int, ulong, byte *, int); 378 void pstring (Device *, int, ulong, void *, int); 379 void phub (Device *, int, ulong, void *, int); 380 void pdevice (Device *, int, ulong, void *, int); 381 void phid (Device *, int, ulong, void *, int); 382 void pcs_raw(char *tag, byte *b, int n); 383 384 /* 385 * interface 386 */ 387 void usbfmtinit(void); 388 Device* opendev(int, int); 389 void closedev(Device*); 390 int describedevice(Device*); 391 int loadconfig(Device *d, int n); 392 Endpt * newendpt(Device *d, int id, ulong csp); 393 int setupcmd(Endpt*, int, int, int, int, byte*, int); 394 int setupreq(Endpt*, int, int, int, int, int); 395 int setupreply(Endpt*, void*, int); 396 void setdevclass(Device *d, int n); 397 void * emalloc(ulong); 398 void * emallocz(ulong, int); 399 400 char * namefor(Namelist *, int); 401 402 #pragma varargck type "D" Device* 403