NAME
usbcmd, classname, closedev, configdev, devctl, finddevs, loaddevstr,
matchdevcsp, opendev, opendevdata, openep, startdevs, unstall,
class, subclass, proto, CSP – USB device driver library |
SYNOPSIS
#include <u.h> #include <libc.h> #include <thread.h> #include "../lib/usb.h" struct Dev {
struct Usbdev {
struct Ep {
struct Altc {
struct Iface {
struct Conf {
struct Desc {
struct DDesc {
#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 int 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 usbcmd(Dev *d, int type, int req,
|
DESCRIPTION
This library provides convenience structures and functions to
write USB device drivers. It is not intended for user programs
using USB devices. See usb(3) for a description of the interfaces
provided for that purpose. For drivers that provide a file system
and may be embedded into usbd, the library includes a file system
implementation toolkit described in usbfs(2). Usb drivers rely on usb(3) to perform I/O through USB as well as on 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. In most cases, a driver locates the devices of interest and configures them by calling startdevs and then sets up additional endpoints as needed (by calling openep) to finally perform I/O by reading and writing the data files for the endpoints. An endpoint as provided by usb(3) is represented by a Dev data structure. The setup endpoint for a device represents the USB device, because it is the means to configure and operate the device. This structure is reference counted. Functions creating Devs adjust the number of references to one, initially. The driver is free to call incref (in lock(2)) to add references and closedev to drop references (and release resources when the last one vanishes). As an aid to the driver, the field aux may keep driver–specific data and the function free will be called (if not null) to release the aux structure when the reference count goes down to zero. Dev.dir holds the path for the endpoint's directory. The field id keeps the device number for setup endpoints and the endpoint number for all other endpoints. For example, it would be 3 for /dev/usb/ep3.0 and 1 for /dev/usb/ep3.1. It is easy to remember this because the former is created to operate on the device, while the later has been created as a particular endpoint to perform I/O. Fields dfd and cfd keep the data and control file descriptors, respectively. When a Dev is created the control file is open, initially. Opening the data file requires calling opendevdata with the appropriate mode. When the device configuration information has been loaded (see below), maxpkt holds the maximum packet size (in bytes) for the endpoint and usb keeps the rest of the USB information.
Most of the information in usb comes from parsing various device
and configuration descriptors provided by the device, by calling
one of the functions described later. Only descriptors unknown
to the library are kept unparsed at usb.ddesc as an aid for the
driver (which should know how to parse them and what to
do with the information). Configuration In many cases, matchdevcsp may be supplied as mf along with a (null terminated) vector of CSP values supplied as ma. This function returns 0 for any device with a CSP matching one in the vector supplied as an argument and –1 otherwise. In other cases (eg., when a particular vendor and device ids are the ones identifying the device) the driver must include its own function and supply it as an argument to startdevs. The first argument of the function corresponds to the information known about the device (the second line in its ctl file). Openep creates the endpoint number id for the device d and returns a Dev structure to operate on it (with just the control file open). Opendev creates a Dev for the endpoint with directory fn. Usually, the endpoint is a setup endpoint representing a device. The endpoint control file is open, but the data file is not. The USB description is void. In most cases drivers call startdevs and openep and do not call this function directly. Configdev opens the data file for the device supplied and loads and parses its configuration information. After calling it, the device is ready for I/O and the USB description in Dev.usb is valid. When using startdevs it is not desirable to call this function (because startdevs already calls it).
Control requests for an endpoint may be written by calling devctl
in the style of print(2). It is better not to call print directly
because the control request should be issued as a single write
system call. See usb(3) for a list of available control requests
(not to be confused with USB control transfers performed on a
control
endpoint). Input/Output For control endpoints, it is not necessary to call read and write directly. Instead, usbcmd issues a USB control request to the device d (not to be confused with a usb(3) control request sent to its control file). Usbcmd retries the control request several times upon failure because some devices require it. The format of requests is fixed per the USB standard: type is the type of request and req identifies the request. Arguments value and index are parameters to the request and the last two arguments, data and count, are similar to read and write arguments. However, data may be nil if no transfer (other than the control request) has to take place. The library header file includes numerous symbols defined to help writing the type and arguments for a request. The return value from usbcmd is the number of bytes transferred, zero to indicate a stall and –1 to indicate an error.
A common request is to unstall an endpoint that has been stalled
due to some reason by the device (eg., when read or write indicate
a count of zero bytes read or written on the endpoint). The function
unstall does this. It is given the device that stalled the endpoint,
dev, the stalled endpoint, ep, and the direction of the
stall (one of Ein or Eout). The function takes care of notifying
the device of the unstall as well as notifying the kernel. Tools The macros GET2 and PUT2 get and put a (little–endian) two–byte value and are useful to parse descriptors and replies for control requests. Functions emallocz and estrdup are similar to mallocz and strdup but abort program operation upon failure. The function Ufmt is a format routine suitable for fmtinstall(2) to print a Dev data structure. The auxiliary hexstr returns a string representing a dump (in hexadecimal) of n bytes starting at a. The string is allocated using malloc(2) and memory must be released by the caller.
Loaddevstr returns the string obtained by reading the device string
descriptor number sid. |
SOURCE
/sys/src/cmd/usb/lib |
SEE ALSO
usbfs(2), usb(3), usb(4), usbd(4). |
BUGS
Not heavily exercised yet. |