Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3519 → Rev 3520

/kernel/trunk/docs/usbapi.txt
0,0 → 1,183
When the kernel detects a connected USB device, it configures the device in
terms of USB protocol - SET_ADDRESS + SET_CONFIGURATION, the first
configuration is always selected. The kernel also reads device descriptor to
print some information, reads and parses configuration descriptor. For every
interface the kernel looks for class code of this interface and loads the
corresponding COFF driver. Currently the correspondence is hardcoded into
the kernel code and looks as follows: 3 = usbhid.obj, 8 = usbstor.obj,
9 is handled by the kernel itself, other = usbother.obj.
 
The driver must be standard driver in COFF format, exporting procedure
named "START" and a variable named "version". Loader calls "START" procedure
as stdcall with one parameter DRV_ENTRY = 1; if initialization is successful,
the "START" procedure is also called by shutdown code with one parameter
DRV_EXIT = -1.
 
The driver must register itself as a USB driver in "START" procedure.
This is done by call to exported function RegUSBDriver and passing the returned
value as result of "START" procedure.
 
void* __stdcall RegUSBDriver(
const char* name,
void* handler,
const USBFUNC* usbfunc
);
 
The parameter 'name' should match the name of driver, "usbhid" for usbhid.obj.
The parameter 'handler' is optional; if it is non-NULL, it should point to
the standard handler for IOCTL interface as in non-USB drivers.
The parameter 'usbfunc' is a pointer to the following structure:
 
struc USBFUNC
{
.strucsize dd ? ; size of the structure, including this field
.add_device dd ? ; pointer to AddDevice function in the driver
; required
.device_disconnect dd ? ; pointer to DeviceDisconnected function in the driver
; optional, may be NULL
; other functions may be added in the future
}
 
The driver should implement the function
 
void* __stdcall AddDevice(
void* pipe0,
void* configdescr,
void* interfacedescr
);
 
The parameter 'controlpipe' is a handle of the control pipe for endpoint zero
of the device. It can be used as the argument of USBControlTransferAsync.
The parameter 'configdescr' points to USB configuration descriptor
and all associated data, as returned by GET_DESCRIPTOR request.
The total length of all associated data is contained in the configuration
descriptor.
The parameter 'interfacedescr' points to USB interface descriptor corresponding
to the interface which is initializing. This is a pointer inside data
associated with the configuration descriptor.
Note that one device can implement many interfaces, so AddDevice may be
called several times with the same 'configdescr' and different 'interfacedescr'.
The returned value NULL means that the initialization has failed.
Any other value means that configuration was successful; the kernel does not
try to interpret the value. It can be, for example, pointer to the internal
data allocated with Kmalloc, or index in some internal table. Remember that
Kmalloc() is NOT stdcall, it destroys ebx.
 
The driver can implement the function
 
void __stdcall DeviceDisconnected(
void* devicedata
);
 
If this function is implemented, the kernel calls it when the device is
disconnected, passing the returned value of AddDevice as 'devicedata'.
 
The driver can use the following functions exported by the kernel.
 
void* __stdcall USBOpenPipe(
void* pipe0,
int endpoint,
int maxpacketsize,
int type,
int interval
);
 
The parameter 'pipe0' is a handle of the pipe for endpoint zero for
the device, as passed to AddDevice. It is used to identify the device.
The parameter 'endpoint' is endpoint number as defined by USB. Lower
4 bits form the number itself, bit 7 - highest bit of low byte -
is 0/1 for OUT/IN endpoints, other bits should be zero.
The parameter 'maxpacketsize' sets the maximum packet size for this pipe.
The parameter 'type' selects the type of the endpoint as defined by USB:
0 = control, 1 = isochronous (not supported yet), 2 = bulk, 3 = interrupt.
The parameter 'interval' is ignored for control and bulk endpoints.
For interrupt endpoints, it sets the polling interval in milliseconds.
The function returns a handle to the pipe or NULL on failure.
 
void* __stdcall USBNormalTransferAsync(
void* pipe,
void* buffer,
int size,
void* callback,
void* calldata,
int flags
);
void* __stdcall USBControlTransferAsync(
void* pipe,
void* config,
void* buffer,
int size,
void* callback,
void* calldata,
int flags
);
 
The first function inserts a bulk or interrupt transfer to the transfer queue
for given pipe. Type and direction of transfer are fixed for bulk and interrupt
endpoints and are set in USBOpenPipe. The second function inserts a control
transfer to the transfer queue for given pipe. Direction of a control transfer
is concluded from 'config' packet, bit 7 of byte 0 is set for IN transfers
and cleared for OUT transfers. These function return immediately; when data
are transferred, the callback function will be called.
 
The parameter 'pipe' is a handle returned by USBOpenPipe.
The parameter 'config' of USBControlTransferAsync points to 8-byte
configuration packet as defined by USB.
The parameter 'buffer' is a pointer to buffer. For IN transfers, it will be
filled with the data. For OUT transfers, it should contain data to be
transferred. It can be NULL for an empty transfer or if no additional data are
required for a control transfer.
The parameter 'size' is size of data to transfer. It can be 0 for an empty
transfer or if no additional data are required for a control transfer.
The parameter 'callback' is a pointer to a function which will be called
when the transfer will be done.
The parameter 'calldata' will be passed as is to the callback function.
For example, it can be NULL, it can be a pointer to device data or it can be
a pointer to data used to pass additional parameters between caller and
callback. The transfer-specific data can also be associated with 'buffer',
preceding (negative offsets from 'buffer') or following (offsets more than
or equal to 'size') the buffer itself.
The parameter 'flags' is the bitmask.
The bit 0 is ignored for OUT transfers, for IN transfers it controls whether
the device can transfer less data than 'size' bytes. If the bit is 0, a small
transfer is an error; if the bit is 1, a small transfer is OK.
All other bits are reserved and should be zero.
The returned value is NULL if an error occured and non-NULL if the transfer
was successfully queued. If an error will occur later, the callback function
will be notified.
 
void __stdcall CallbackFunction(
void* pipe,
int status,
void* buffer,
int length,
void* calldata
);
 
The parameters 'pipe', 'buffer', 'calldata' are the same as for the
corresponding USB*TransferAsync.
The parameter 'length' is the number of bytes transferred. For
control transfers, this includes 8 bytes from SETUP stage, so
0 means that SETUP stage failed and 'size'+8 means full transfer.
The parameter 'status' is nonzero if an error occured.
USB_STATUS_OK = 0 ; no error
USB_STATUS_CRC = 1 ; CRC error
USB_STATUS_BITSTUFF = 2 ; bit stuffing violation
USB_STATUS_TOGGLE = 3 ; data toggle mismatch
USB_STATUS_STALL = 4 ; device returned STALL
USB_STATUS_NORESPONSE = 5 ; device not responding
USB_STATUS_PIDCHECK = 6 ; invalid PID check bits
USB_STATUS_WRONGPID = 7 ; unexpected PID value
USB_STATUS_OVERRUN = 8 ; too many data from endpoint
USB_STATUS_UNDERRUN = 9 ; too few data from endpoint
USB_STATUS_BUFOVERRUN = 12 ; overflow of internal controller buffer
; possible only for isochronous transfers
USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer
; possible only for isochronous transfers
USB_STATUS_DISCONNECTED = 16 ; device disconnected
 
If several transfers are queued for the same pipe, their callback functions
are called in the same order as they were queued.
When the device is disconnected, all callback functions are called
with USB_STATUS_DISCONNECTED. The call to DeviceDisconnected() occurs after
all callbacks.