Rev 3745 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3520 | clevermous | 1 | When the kernel detects a connected USB device, it configures the device in |
2 | terms of USB protocol - SET_ADDRESS + SET_CONFIGURATION, the first |
||
3 | configuration is always selected. The kernel also reads device descriptor to |
||
4 | print some information, reads and parses configuration descriptor. For every |
||
5 | interface the kernel looks for class code of this interface and loads the |
||
6 | corresponding COFF driver. Currently the correspondence is hardcoded into |
||
3577 | clevermous | 7 | the kernel code and looks as follows: 3 = usbhid.obj, 7 = usbprint.obj, |
8 | 8 = usbstor.obj, 9 is handled by the kernel itself, other = usbother.obj. |
||
3520 | clevermous | 9 | |
10 | The driver must be standard driver in COFF format, exporting procedure |
||
11 | named "START" and a variable named "version". Loader calls "START" procedure |
||
12 | as stdcall with one parameter DRV_ENTRY = 1; if initialization is successful, |
||
13 | the "START" procedure is also called by shutdown code with one parameter |
||
14 | DRV_EXIT = -1. |
||
15 | |||
16 | The driver must register itself as a USB driver in "START" procedure. |
||
17 | This is done by call to exported function RegUSBDriver and passing the returned |
||
18 | value as result of "START" procedure. |
||
19 | |||
20 | void* __stdcall RegUSBDriver( |
||
21 | const char* name, |
||
22 | void* handler, |
||
23 | const USBFUNC* usbfunc |
||
24 | ); |
||
25 | |||
26 | The parameter 'name' should match the name of driver, "usbhid" for usbhid.obj. |
||
27 | The parameter 'handler' is optional; if it is non-NULL, it should point to |
||
28 | the standard handler for IOCTL interface as in non-USB drivers. |
||
29 | The parameter 'usbfunc' is a pointer to the following structure: |
||
30 | |||
31 | struc USBFUNC |
||
32 | { |
||
33 | .strucsize dd ? ; size of the structure, including this field |
||
34 | .add_device dd ? ; pointer to AddDevice function in the driver |
||
35 | ; required |
||
36 | .device_disconnect dd ? ; pointer to DeviceDisconnected function in the driver |
||
37 | ; optional, may be NULL |
||
38 | ; other functions may be added in the future |
||
39 | } |
||
40 | |||
41 | The driver should implement the function |
||
42 | |||
43 | void* __stdcall AddDevice( |
||
44 | void* pipe0, |
||
45 | void* configdescr, |
||
46 | void* interfacedescr |
||
47 | ); |
||
48 | |||
3577 | clevermous | 49 | The parameter 'pipe0' is a handle of the control pipe for endpoint zero |
3520 | clevermous | 50 | of the device. It can be used as the argument of USBControlTransferAsync. |
51 | The parameter 'configdescr' points to USB configuration descriptor |
||
52 | and all associated data, as returned by GET_DESCRIPTOR request. |
||
53 | The total length of all associated data is contained in the configuration |
||
54 | descriptor. |
||
55 | The parameter 'interfacedescr' points to USB interface descriptor corresponding |
||
56 | to the interface which is initializing. This is a pointer inside data |
||
57 | associated with the configuration descriptor. |
||
58 | Note that one device can implement many interfaces, so AddDevice may be |
||
59 | called several times with the same 'configdescr' and different 'interfacedescr'. |
||
60 | The returned value NULL means that the initialization has failed. |
||
61 | Any other value means that configuration was successful; the kernel does not |
||
62 | try to interpret the value. It can be, for example, pointer to the internal |
||
3745 | clevermous | 63 | data allocated with Kmalloc, or index in some internal table. |
3520 | clevermous | 64 | |
65 | The driver can implement the function |
||
66 | |||
67 | void __stdcall DeviceDisconnected( |
||
68 | void* devicedata |
||
69 | ); |
||
70 | |||
71 | If this function is implemented, the kernel calls it when the device is |
||
72 | disconnected, passing the returned value of AddDevice as 'devicedata'. |
||
73 | |||
74 | The driver can use the following functions exported by the kernel. |
||
75 | |||
76 | void* __stdcall USBOpenPipe( |
||
77 | void* pipe0, |
||
78 | int endpoint, |
||
79 | int maxpacketsize, |
||
80 | int type, |
||
81 | int interval |
||
82 | ); |
||
83 | |||
84 | The parameter 'pipe0' is a handle of the pipe for endpoint zero for |
||
85 | the device, as passed to AddDevice. It is used to identify the device. |
||
86 | The parameter 'endpoint' is endpoint number as defined by USB. Lower |
||
87 | 4 bits form the number itself, bit 7 - highest bit of low byte - |
||
88 | is 0/1 for OUT/IN endpoints, other bits should be zero. |
||
89 | The parameter 'maxpacketsize' sets the maximum packet size for this pipe. |
||
90 | The parameter 'type' selects the type of the endpoint as defined by USB: |
||
91 | |||
92 | The parameter 'interval' is ignored for control and bulk endpoints. |
||
93 | For interrupt endpoints, it sets the polling interval in milliseconds. |
||
94 | The function returns a handle to the pipe or NULL on failure. |
||
3577 | clevermous | 95 | The output handle becomes invalid when a) it is explicitly closed with |
96 | the following function or b) the function DeviceDisconnected provided |
||
97 | by the driver returns. |
||
3520 | clevermous | 98 | |
3577 | clevermous | 99 | void __stdcall USBClosePipe( |
100 | void* pipe |
||
101 | ); |
||
102 | |||
103 | Releases all resources associated with the given pipe. The only parameter |
||
104 | must be a handle returned by USBOpenPipe. |
||
105 | When a device is disconnected, all associated pipes are closed by the kernel; |
||
106 | there is no need to ever call this function if all pipes are used continuously |
||
107 | while a device is connected. |
||
108 | |||
3520 | clevermous | 109 | void* __stdcall USBNormalTransferAsync( |
110 | void* pipe, |
||
111 | void* buffer, |
||
112 | int size, |
||
113 | void* callback, |
||
114 | void* calldata, |
||
115 | int flags |
||
116 | ); |
||
117 | void* __stdcall USBControlTransferAsync( |
||
118 | void* pipe, |
||
3577 | clevermous | 119 | void* setup, |
3520 | clevermous | 120 | void* buffer, |
121 | int size, |
||
122 | void* callback, |
||
123 | void* calldata, |
||
124 | int flags |
||
125 | ); |
||
126 | |||
127 | The first function inserts a bulk or interrupt transfer to the transfer queue |
||
128 | for given pipe. Type and direction of transfer are fixed for bulk and interrupt |
||
129 | endpoints and are set in USBOpenPipe. The second function inserts a control |
||
130 | transfer to the transfer queue for given pipe. Direction of a control transfer |
||
3577 | clevermous | 131 | is concluded from 'setup' packet, bit 7 of byte 0 is set for IN transfers |
3520 | clevermous | 132 | and cleared for OUT transfers. These function return immediately; when data |
133 | are transferred, the callback function will be called. |
||
134 | |||
135 | The parameter 'pipe' is a handle returned by USBOpenPipe. |
||
3577 | clevermous | 136 | The parameter 'setup' of USBControlTransferAsync points to 8-byte |
3520 | clevermous | 137 | configuration packet as defined by USB. |
138 | The parameter 'buffer' is a pointer to buffer. For IN transfers, it will be |
||
139 | filled with the data. For OUT transfers, it should contain data to be |
||
140 | transferred. It can be NULL for an empty transfer or if no additional data are |
||
141 | required for a control transfer. |
||
142 | The parameter 'size' is size of data to transfer. It can be 0 for an empty |
||
143 | transfer or if no additional data are required for a control transfer. |
||
144 | The parameter 'callback' is a pointer to a function which will be called |
||
145 | when the transfer will be done. |
||
146 | The parameter 'calldata' will be passed as is to the callback function. |
||
147 | For example, it can be NULL, it can be a pointer to device data or it can be |
||
148 | a pointer to data used to pass additional parameters between caller and |
||
149 | callback. The transfer-specific data can also be associated with 'buffer', |
||
150 | preceding (negative offsets from 'buffer') or following (offsets more than |
||
151 | or equal to 'size') the buffer itself. |
||
152 | The parameter 'flags' is the bitmask. |
||
153 | The bit 0 is ignored for OUT transfers, for IN transfers it controls whether |
||
154 | the device can transfer less data than 'size' bytes. If the bit is 0, a small |
||
155 | transfer is an error; if the bit is 1, a small transfer is OK. |
||
156 | All other bits are reserved and should be zero. |
||
157 | The returned value is NULL if an error occured and non-NULL if the transfer |
||
158 | was successfully queued. If an error will occur later, the callback function |
||
159 | will be notified. |
||
160 | |||
161 | void __stdcall CallbackFunction( |
||
162 | void* pipe, |
||
163 | int status, |
||
164 | void* buffer, |
||
165 | int length, |
||
166 | void* calldata |
||
167 | ); |
||
168 | |||
169 | The parameters 'pipe', 'buffer', 'calldata' are the same as for the |
||
170 | corresponding USB*TransferAsync. |
||
171 | The parameter 'length' is the number of bytes transferred. For |
||
172 | control transfers, this includes 8 bytes from SETUP stage, so |
||
173 | |||
174 | The parameter 'status' is nonzero if an error occured. |
||
3745 | clevermous | 175 | USB_STATUS_OK = 0 ; no error |
176 | USB_STATUS_CRC = 1 ; CRC error |
||
177 | USB_STATUS_BITSTUFF = 2 ; bit stuffing violation |
||
178 | USB_STATUS_TOGGLE = 3 ; data toggle mismatch |
||
179 | USB_STATUS_STALL = 4 ; device returned STALL |
||
180 | USB_STATUS_NORESPONSE = 5 ; device not responding |
||
181 | USB_STATUS_PIDCHECK = 6 ; invalid PID check bits |
||
182 | USB_STATUS_WRONGPID = 7 ; unexpected PID value |
||
183 | USB_STATUS_OVERRUN = 8 ; too many data from endpoint |
||
184 | USB_STATUS_UNDERRUN = 9 ; too few data from endpoint |
||
185 | USB_STATUS_BUFOVERRUN = 12 ; overflow of internal controller buffer |
||
186 | USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer |
||
187 | USB_STATUS_CLOSED = 16 ; pipe closed, either explicitly with USBClosePipe |
||
188 | ; or due to device disconnect |
||
4547 | clevermous | 189 | USB_STATUS_CANCELLED = 17 ; transfer cancelled with USBAbortPipe |
3520 | clevermous | 190 | |
191 | If several transfers are queued for the same pipe, their callback functions |
||
192 | are called in the same order as they were queued. |
||
3577 | clevermous | 193 | When a pipe is closed, either explicitly with USBClosePipe, or |
194 | implicitly due to device disconnect, all callback functions are called |
||
195 | with USB_STATUS_CLOSED. The call to DeviceDisconnected() occurs after |
||
3520 | clevermous | 196 | all callbacks. |
3745 | clevermous | 197 | |
4547 | clevermous | 198 | void __stdcall USBAbortPipe(void* pipe); |
199 | Initiates cancellation of all active transfers for the given pipe. Asynchronous. |
||
200 | When a transfer will be cancelled, the associated callback function |
||
201 | will be called with USB_STATUS_CANCELLED. |
||
202 | |||
3745 | clevermous | 203 | void* __stdcall USBGetParam(void* pipe0, int param); |
204 | Returns miscellaneous parameters of the device. |
||
205 | pipe0 is the pointer to the config pipe. |
||
206 | param = 0: return pointer to device descriptor |
||
207 | param = 1: return pointer to config descriptor, same as passed to AddDevice |
||
208 | param = 2: return speed at which the device is operating, one of |
||
209 | USB_SPEED_FS = 0 ; full-speed |
||
210 | USB_SPEED_LS = 1 ; low-speed |
||
211 | USB_SPEED_HS = 2 ; high-speed |