/*
* common USB definitions.
*/
typedef struct Udev Udev; /* USB device */
typedef struct Ep Ep; /* Endpoint */
typedef struct Hci Hci; /* Host Controller Interface */
typedef struct Hciimpl Hciimpl; /* Link to the controller impl. */
enum
{
/* fundamental constants */
Ndeveps = 16, /* max nb. of endpoints per device */
/* tunable parameters */
Nhcis = 16, /* max nb. of HCIs */
Neps = 64, /* max nb. of endpoints */
Maxctllen = 8*1024, /* max allowed sized for ctl. xfers */
/* transfer types. keep this order */
Tnone = 0, /* no tranfer type configured */
Tctl, /* wr req + rd/wr data + wr/rd sts */
Tiso, /* stream rd or wr (real time) */
Tbulk, /* stream rd or wr */
Tintr, /* msg rd or wr */
Nttypes, /* number of transfer types */
Epmax = 0xF, /* max ep. addr */
Devmax = 0x7F, /* max dev. addr */
/* Speeds */
Fullspeed = 0,
Lowspeed,
Highspeed,
Nospeed,
/* request type */
Rh2d = 0<<7,
Rd2h = 1<<7,
Rstd = 0<<5,
Rclass = 1<<5,
Rdev = 0,
Rep = 2,
Rother = 3,
/* req offsets */
Rtype = 0,
Rreq = 1,
Rvalue = 2,
Rindex = 4,
Rcount = 6,
Rsetuplen = 8,
/* standard requests */
Rgetstatus = 0,
Rclearfeature = 1,
Rsetfeature = 3,
Rsetaddr = 5,
Rgetdesc = 6,
/* device states */
Dconfig = 0, /* configuration in progress */
Denabled, /* address assigned */
Ddetach, /* device is detached */
/* (root) Hub reply to port status (reported to usbd) */
HPpresent = 0x1,
HPenable = 0x2,
HPsuspend = 0x4,
HPovercurrent = 0x8,
HPreset = 0x10,
HPpower = 0x100,
HPslow = 0x200,
HPhigh = 0x400,
HPstatuschg = 0x10000,
HPchange = 0x20000,
};
/*
* Services provided by the driver.
* epopen allocates hardware structures to prepare the endpoint
* for I/O. This happens when the user opens the data file.
* epclose releases them. This happens when the data file is closed.
* epwrite tries to write the given bytes, waiting until all of them
* have been written (or failed) before returning; but not for Iso.
* epread does the same for reading.
* It can be assumed that endpoints are DMEXCL but concurrent
* read/writes may be issued and the controller must take care.
* For control endpoints, device-to-host requests must be followed by
* a read of the expected length if needed.
* The port requests are called when usbd issues commands for root
* hubs. Port status must return bits as a hub request would do.
* Toggle handling and other details are left for the controller driver
* to avoid mixing too much the controller and the comon device.
* While an endpoint is closed, its toggles are saved in the Ep struct.
*/
struct Hciimpl
{
void *aux; /* for controller info */
void (*init)(Hci*); /* init. controller */
void (*dump)(Hci*); /* debug */
void (*interrupt)(Ureg*, void*); /* service interrupt */
void (*epopen)(Ep*); /* prepare ep. for I/O */
void (*epclose)(Ep*); /* terminate I/O on ep. */
long (*epread)(Ep*,void*,long); /* transmit data for ep */
long (*epwrite)(Ep*,void*,long); /* receive data for ep */
char* (*seprintep)(char*,char*,Ep*); /* debug */
int (*portenable)(Hci*, int, int); /* enable/disable port */
int (*portreset)(Hci*, int, int); /* set/clear port reset */
int (*portstatus)(Hci*, int); /* get port status */
void (*debug)(Hci*, int); /* set/clear debug flag */
};
struct Hci
{
ISAConf; /* hardware info */
int tbdf; /* type+busno+devno+funcno */
int ctlrno; /* controller number */
int nports; /* number of ports in hub */
int highspeed;
Hciimpl; /* HCI driver */
};
/*
* USB endpoint.
* All endpoints are kept in a global array. The first
* block of fields is constant after endpoint creation.
* The rest is configuration information given to all controllers.
* The first endpoint for a device (known as ep0) represents the
* device and is used to configure it and create other endpoints.
* Its QLock also protects per-device data in dev.
* See Hciimpl for clues regarding how this is used by controllers.
*/
struct Ep
{
Ref; /* one per fid (and per dev ep for ep0s) */
/* const once inited. */
int idx; /* index in global eps array */
int nb; /* endpoint number in device */
Hci* hp; /* HCI it belongs to */
Udev* dev; /* device for the endpoint */
Ep* ep0; /* control endpoint for its device */
QLock; /* protect fields below */
char* name; /* for ep file names at #u/ */
int inuse; /* endpoint is open */
int mode; /* OREAD, OWRITE, or ORDWR */
int clrhalt; /* true if halt was cleared on ep. */
int debug; /* per endpoint debug flag */
char* info; /* for humans to read */
long maxpkt; /* maximum packet size */
int ttype; /* tranfer type */
ulong load; /* in µs, for a fransfer of maxpkt bytes */
void* aux; /* for controller specific info */
int rhrepl; /* fake root hub replies */
int toggle[2]; /* saved toggles (while ep is not in use) */
long pollival; /* poll interval ([µ]frames; intr/iso) */
long hz; /* poll frequency (iso) */
long samplesz; /* sample size (iso) */
int ntds; /* nb. of Tds per µframe */
};
/*
* Per-device configuration and cached list of endpoints.
* eps[0]->QLock protects it.
*/
struct Udev
{
int nb; /* USB device number */
int state; /* state for the device */
int ishub; /* hubs can allocate devices */
int isroot; /* is a root hub */
int speed; /* Full/Low/High/No -speed */
int hub; /* dev number for the parent hub */
int port; /* port number in the parent hub */
Ep* eps[Ndeveps]; /* end points for this device (cached) */
};
void addhcitype(char *type, int (*reset)(Hci*));
#define dprint if(debug)print
#define ddprint if(debug>1)print
#define deprint if(debug || ep->debug)print
#define ddeprint if(debug>1 || ep->debug>1)print
#define GET2(p) ((((p)[1]&0xFF)<<8)|((p)[0]&0xFF))
#define PUT2(p,v) {((p)[0] = (v)); ((p)[1] = (v)>>8);}
extern char *usbmodename[];
extern char Estalled[];
extern char *seprintdata(char*,char*,uchar*,int);
|