Rev 3577 | Go to most recent revision | Details | 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 |
||
7 | the kernel code and looks as follows: 3 = usbhid.obj, 8 = usbstor.obj, |
||
8 | 9 is handled by the kernel itself, other = usbother.obj. |
||
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 | |||
49 | The parameter 'controlpipe' is a handle of the control pipe for endpoint zero |
||
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 |
||
63 | data allocated with Kmalloc, or index in some internal table. Remember that |
||
64 | Kmalloc() is NOT stdcall, it destroys ebx. |
||
65 | |||
66 | The driver can implement the function |
||
67 | |||
68 | void __stdcall DeviceDisconnected( |
||
69 | void* devicedata |
||
70 | ); |
||
71 | |||
72 | If this function is implemented, the kernel calls it when the device is |
||
73 | disconnected, passing the returned value of AddDevice as 'devicedata'. |
||
74 | |||
75 | The driver can use the following functions exported by the kernel. |
||
76 | |||
77 | void* __stdcall USBOpenPipe( |
||
78 | void* pipe0, |
||
79 | int endpoint, |
||
80 | int maxpacketsize, |
||
81 | int type, |
||
82 | int interval |
||
83 | ); |
||
84 | |||
85 | The parameter 'pipe0' is a handle of the pipe for endpoint zero for |
||
86 | the device, as passed to AddDevice. It is used to identify the device. |
||
87 | The parameter 'endpoint' is endpoint number as defined by USB. Lower |
||
88 | 4 bits form the number itself, bit 7 - highest bit of low byte - |
||
89 | is 0/1 for OUT/IN endpoints, other bits should be zero. |
||
90 | The parameter 'maxpacketsize' sets the maximum packet size for this pipe. |
||
91 | The parameter 'type' selects the type of the endpoint as defined by USB: |
||
92 | |||
93 | The parameter 'interval' is ignored for control and bulk endpoints. |
||
94 | For interrupt endpoints, it sets the polling interval in milliseconds. |
||
95 | The function returns a handle to the pipe or NULL on failure. |
||
96 | |||
97 | void* __stdcall USBNormalTransferAsync( |
||
98 | void* pipe, |
||
99 | void* buffer, |
||
100 | int size, |
||
101 | void* callback, |
||
102 | void* calldata, |
||
103 | int flags |
||
104 | ); |
||
105 | void* __stdcall USBControlTransferAsync( |
||
106 | void* pipe, |
||
107 | void* config, |
||
108 | void* buffer, |
||
109 | int size, |
||
110 | void* callback, |
||
111 | void* calldata, |
||
112 | int flags |
||
113 | ); |
||
114 | |||
115 | The first function inserts a bulk or interrupt transfer to the transfer queue |
||
116 | for given pipe. Type and direction of transfer are fixed for bulk and interrupt |
||
117 | endpoints and are set in USBOpenPipe. The second function inserts a control |
||
118 | transfer to the transfer queue for given pipe. Direction of a control transfer |
||
119 | is concluded from 'config' packet, bit 7 of byte 0 is set for IN transfers |
||
120 | and cleared for OUT transfers. These function return immediately; when data |
||
121 | are transferred, the callback function will be called. |
||
122 | |||
123 | The parameter 'pipe' is a handle returned by USBOpenPipe. |
||
124 | The parameter 'config' of USBControlTransferAsync points to 8-byte |
||
125 | configuration packet as defined by USB. |
||
126 | The parameter 'buffer' is a pointer to buffer. For IN transfers, it will be |
||
127 | filled with the data. For OUT transfers, it should contain data to be |
||
128 | transferred. It can be NULL for an empty transfer or if no additional data are |
||
129 | required for a control transfer. |
||
130 | The parameter 'size' is size of data to transfer. It can be 0 for an empty |
||
131 | transfer or if no additional data are required for a control transfer. |
||
132 | The parameter 'callback' is a pointer to a function which will be called |
||
133 | when the transfer will be done. |
||
134 | The parameter 'calldata' will be passed as is to the callback function. |
||
135 | For example, it can be NULL, it can be a pointer to device data or it can be |
||
136 | a pointer to data used to pass additional parameters between caller and |
||
137 | callback. The transfer-specific data can also be associated with 'buffer', |
||
138 | preceding (negative offsets from 'buffer') or following (offsets more than |
||
139 | or equal to 'size') the buffer itself. |
||
140 | The parameter 'flags' is the bitmask. |
||
141 | The bit 0 is ignored for OUT transfers, for IN transfers it controls whether |
||
142 | the device can transfer less data than 'size' bytes. If the bit is 0, a small |
||
143 | transfer is an error; if the bit is 1, a small transfer is OK. |
||
144 | All other bits are reserved and should be zero. |
||
145 | The returned value is NULL if an error occured and non-NULL if the transfer |
||
146 | was successfully queued. If an error will occur later, the callback function |
||
147 | will be notified. |
||
148 | |||
149 | void __stdcall CallbackFunction( |
||
150 | void* pipe, |
||
151 | int status, |
||
152 | void* buffer, |
||
153 | int length, |
||
154 | void* calldata |
||
155 | ); |
||
156 | |||
157 | The parameters 'pipe', 'buffer', 'calldata' are the same as for the |
||
158 | corresponding USB*TransferAsync. |
||
159 | The parameter 'length' is the number of bytes transferred. For |
||
160 | control transfers, this includes 8 bytes from SETUP stage, so |
||
161 | |||
162 | The parameter 'status' is nonzero if an error occured. |
||
163 | USB_STATUS_OK = 0 ; no error |
||
164 | USB_STATUS_CRC = 1 ; CRC error |
||
165 | USB_STATUS_BITSTUFF = 2 ; bit stuffing violation |
||
166 | USB_STATUS_TOGGLE = 3 ; data toggle mismatch |
||
167 | USB_STATUS_STALL = 4 ; device returned STALL |
||
168 | USB_STATUS_NORESPONSE = 5 ; device not responding |
||
169 | USB_STATUS_PIDCHECK = 6 ; invalid PID check bits |
||
170 | USB_STATUS_WRONGPID = 7 ; unexpected PID value |
||
171 | USB_STATUS_OVERRUN = 8 ; too many data from endpoint |
||
172 | USB_STATUS_UNDERRUN = 9 ; too few data from endpoint |
||
173 | USB_STATUS_BUFOVERRUN = 12 ; overflow of internal controller buffer |
||
174 | ; possible only for isochronous transfers |
||
175 | USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer |
||
176 | ; possible only for isochronous transfers |
||
177 | USB_STATUS_DISCONNECTED = 16 ; device disconnected |
||
178 | |||
179 | If several transfers are queued for the same pipe, their callback functions |
||
180 | are called in the same order as they were queued. |
||
181 | When the device is disconnected, all callback functions are called |
||
182 | with USB_STATUS_DISCONNECTED. The call to DeviceDisconnected() occurs after |
||
183 | all callbacks. |