460 lines · 11.3 KB · Text
RawDownload
.TH USB 2.SH NAMEusbcmd,classname,closedev,configdev,devctl,finddevs,loaddevstr,matchdevcsp,opendev,opendevdata,openep,startdevs,unstall,class,subclass,proto,CSP \- USB device driver library.SH SYNOPSIS.EX.ta 8n +8n +8n +8n +8n +8n +8n#include <u.h>#include <libc.h>#include <thread.h>#include "../lib/usb.h".sp 0.3vstruct Dev {	Ref;	char*	dir;		/* path for the endpoint dir */	int	id;		/* usb id for device or ep. number */	int	dfd;		/* descriptor for the data file */	int	cfd;		/* descriptor for the control file */	int	maxpkt;		/* cached from usb description */	Usbdev*	usb;		/* USB description */	void*	aux;		/* for the device driver */	void	(*free)(void*);	/* idem. to release aux */};.sp 0.3vstruct Usbdev {	ulong	csp;		/* USB class/subclass/proto */	int	vid;		/* vendor id */	int	did;		/* product (device) id */	int	dno;		/* device release number */	char*	vendor;	char*	product;	char*	serial;	int	ls;		/* low speed */	int	class;		/* from descriptor */	int	nconf;		/* from descriptor */	Conf*	conf[Nconf];	/* configurations */	Ep*	ep[Nep];	/* all endpoints in device */	Desc*	ddesc[Nddesc];	/* (raw) device specific descriptors */};.sp 0.3vstruct Ep {	uchar	addr;		/* endpt address */	uchar	dir;		/* direction, Ein/Eout */	uchar	type;		/* Econtrol, Eiso, Ebulk, Eintr */	uchar	isotype;	/* Eunknown, Easync, Eadapt, Esync */	int	id;	int	maxpkt;		/* max. packet size */	Conf*	conf;		/* the endpoint belongs to */	Iface*	iface;		/* the endpoint belongs to */};.sp 0.3vstruct Altc {	int	attrib;	int	interval;	void*	aux;		/* for the driver program */};.sp 0.3vstruct Iface {	int 	id;		/* interface number */	ulong	csp;		/* USB class/subclass/proto */	Altc*	altc[Naltc];	Ep*	ep[Nep];	void*	aux;		/* for the driver program */};.sp 0.3vstruct Conf {	int	cval;		/* value for set configuration */	int	attrib;	int	milliamps;	/* maximum power in this config. */	Iface*	iface[Niface];	/* up to 16 interfaces */};.sp 0.3vstruct Desc {	Conf*	conf;		/* where this descriptor was read */	Iface*	iface;		/* last iface before desc in conf. */	Ep*	ep;		/* last endpt before desc in conf. */	Altc*	altc;		/* last alt.c. before desc in conf. */	DDesc	data;		/* unparsed standard USB descriptor */};.sp 0.3vstruct DDesc {	uchar	bLength;	uchar	bDescriptorType;	uchar	bbytes[1];	/* extra bytes allocated here to keep the rest of it */};.sp 0.3v#define Class(csp)	((csp)&0xff)#define Subclass(csp)	(((csp)>>8)&0xff)#define Proto(csp)	(((csp)>>16)&0xff)#define CSP(c, s, p)	((c) | ((s)<<8) | ((p)<<16))#define	GET2(p)		...#define	PUT2(p,v)	...#define	GET4(p)		...#define	PUT4(p,v)	...#define dprint	 if(usbdebug)fprint#define ddprint if(usbdebug > 1)fprint.sp 0.3vint	Ufmt(Fmt *f);char*	classname(int c);void	closedev(Dev *d);int	configdev(Dev *d);int	devctl(Dev *dev, char *fmt, ...);void*	emallocz(ulong size, int zero);char*	estrdup(char *s);int	finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs);char*	hexstr(void *a, int n);char*	loaddevstr(Dev *d, int sid);int	matchdevcsp(char *info, void *a);Dev*	opendev(char *fn);int	opendevdata(Dev *d, int mode);Dev*	openep(Dev *d, int id);void	startdevs(char *args, char *argv[], int argc,		int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**));int	unstall(Dev *dev, Dev *ep, int dir);int	usbcmd(Dev *d, int type, int req,		int value, int index, uchar *data, int count);.sp 0.3vextern int usbdebug;	/* more messages for bigger values */.EE.SH DESCRIPTIONThis library provides convenience structures and functions to writeUSB device drivers.It is not intended for user programs using USB devices.See.IR usb (3)for a description of the interfaces provided for that purpose.For drivers that provide a file system and may be embedded into.IR usbd ,the library includes a file system implementation toolkit described in.IR usbfs (2)..PPUsb drivers rely on.IR usb (3)to perform I/O through USB as well as on.IR usbd (4)to perform the initial configuration for the device's setup endpoint.The rest of the work is up to the driver and is where this library may help..PPIn most cases, a driver locates the devices of interest and configures themby calling.I startdevsandthen sets up additional endpoints as needed (by calling.IR openep )to finally perform I/O by reading and writing thedata files for the endpoints..PPAn endpoint as provided by.IR usb (3)is represented by a.B Devdata structure.The setup endpoint for adevice represents the USB device, because it is the means toconfigure and operate the device.This structure is reference counted.Functions creating.B Devsadjust the number of references to one, initially.The driver is free to call.IR incref(in.IR lock (2))to add references and.I closedevto drop references (and release resources when the last one vanishes).As an aid to the driver, the field.B auxmay keep driver-specific data and the function.B freewill be called (if not null) to release the.B auxstructure when the reference count goes down to zero..PP.I Dev.dirholds the path for the endpoint's directory..PPThe field.B idkeeps the device number for setup endpoints and the endpoint numberfor all other endpoints.For example, it would be.B 3for.B /dev/usb/ep3.0and.B 1for.BR /dev/usb/ep3.1 .It is easy to remember this because the former is created to operateon the device, while the later has been created as a particular endpointto perform I/O..PPFields.B dfdand.B cfdkeep the data andcontrol file descriptors, respectively.When a.B Devis created the control file is open, initially.Opening the datafile requires calling.I opendevdatawith the appropriate mode..PPWhen the device configuration information has been loaded (see below),.B maxpktholds the maximum packet size (in bytes) for the endpoint and.B usbkeeps the rest of the USB information..PPMost of the information in.B usbcomes from parsingvarious device and configuration descriptors provided by the device,by calling one of the functions described later.Only descriptors unknownto the library are kept unparsed at.B usb.ddescas an aid for the driver(which should know how to parse them and what to do with the information)..SS Configuration.I Startdevsis a wrapper that locates devices of interest, loads their configurationinformation, and starts a.IR thread (2)'s.I procfor each device located so that it executes.I fas its main entry point. The entry point is called with a pointer tothe.B Devfor the device it has to process,.BR argc ,and.BR argv .Devices are located either from the arguments (after options) in.IR argv ,if any,or by calling the helper function.I mfwith the argument.I mato determine (for each device available) if the device belongs tothe driver or not. If the function returns -1 then the device is not for us..PPIn many cases,.I matchdevcspmay be supplied as.I mfalong with a (null terminated) vector of CSP values supplied as.IR ma .This function returns 0 for any device with a CSP matching one in thevector supplied as an argument and -1 otherwise.In other cases (eg., when a particular vendor and device ids are theones identifying the device) the driver must include its own functionand supply it as an argument to.IR startdevs .The first argument of the function corresponds to the informationknown about the device (the second line in its.B ctlfile)..I Openepcreates the endpoint number.I idfor the device.I dand returns a.B Devstructure to operate on it (with just the control file open)..PP.I Opendevcreates a.B Devfor the endpoint with directory.IR fn .Usually, the endpoint is a setup endpoint representing a device. The endpointcontrol file is open, but the data file is not. The USB description is void.In most cases drivers call.I startdevsand.I openepand do not call this function directly..PP.I Configdevopens the data file for the device supplied andloads and parses its configuration information.After calling it, the device is ready for I/O and the USB description in.B Dev.usbis valid.When using.IR startdevsit is not desirable to call this function (because.IR startdevsalready calls it)..PPControl requests for an endpoint may be written by calling.I devctlin the style of.IR print (2).It is better not to call.I printdirectly because the control request should be issued as a single.I writesystem call.See.IR usb (3)for a list of available control requests (not to be confused withUSB control transfers performed on a control endpoint)..SS Input/Output.I Opendevdataopens the data file for the device according to the given.IR mode .The mode must match that of the endpoint, doing otherwise is consideredan error.Actual I/O is performed by reading/writing the descriptor kept in the.B dfdfield of.BR Dev ..PPFor control endpoints,it is not necessary to call.I readand.I writedirectly.Instead,.I usbcmdissues a USB control request to the device.I d(not to be confused with a.IR usb (3)control request sent to its control file)..I Usbcmdretries the control request several times upon failure because some devicesrequire it.The format of requests is fixed per the USB standard:.I typeis the type of request and.I reqidentifies the request. Arguments.I valueand.I indexare parameters to the request and the last two arguments,.I dataand.IR count ,are similar to.I readand.I writearguments.However,.I datamay be.B nilif no transfer (other than the control request) has to take place.The library header file includes numerous symbols defined to help writingthe type and arguments for a request..PPThe return value from.I usbcmdis the number of bytes transferred, zero to indicate a stall and -1to indicate an error..PPA common request is to unstall an endpoint that has been stalleddue to some reason by the device (eg., when read or write indicatea count of zero bytes read or written on the endpoint). The function.I unstalldoes this.It is given the device that stalled the endpoint,.IR dev ,thestalled endpoint,.IR ep ,and the direction of the stall (one of.B Einor.BR Eout ).The function takes care of notifying the device of the unstall as wellas notifying the kernel..SS Tools.I Classreturns the class part of the number given, representing a CSP..I Subclassdoes the same for the device subclass and.I Protofor the protocol.The counterpart is.IR CSP ,which builds a CSP from the device class, subclass, and protocol.For some classes,.I classnameknows the name (for those with constants in the library header file)..PPThe macros.I GET2and.I PUT2get and put a (little-endian) two-byte value and are useful toparse descriptors and replies for control requests..PPFunctions.I emalloczand.I estrdupare similar to.I malloczand.I strdupbut abort program operation upon failure..PPThe function.I Ufmtis a format routine suitable for.IR fmtinstall (2)to print a.B Devdata structure.The auxiliary.I hexstrreturns a string representing a dump (in hexadecimal) of.I nbytes starting at.IR a .The string is allocated using.IR malloc (2)and memory must be released by the caller..PP.I Loaddevstrreturns the string obtained by reading the device string descriptor number.IR sid ..SH SOURCE.B /sys/src/cmd/usb/lib.SH "SEE ALSO".IR usbfs (2),.IR usb (3),.IR usb (4),.IR usbd (4)..SH BUGSNot heavily exercised yet.