Subversion Repositories Kolibri OS

Rev

Rev 4423 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4423 Rev 5201
-
 
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 
2
;;                                                              ;;
-
 
3
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
-
 
4
;; Distributed under terms of the GNU General Public License    ;;
-
 
5
;;                                                              ;;
-
 
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 
7
 
-
 
8
$Revision: 5177 $
-
 
9
 
-
 
10
 
1
; Implementation of the USB protocol for device enumeration.
11
; Implementation of the USB protocol for device enumeration.
2
; Manage a USB device when it becomes ready for USB commands:
12
; Manage a USB device when it becomes ready for USB commands:
3
; configure, enumerate, load the corresponding driver(s),
13
; configure, enumerate, load the corresponding driver(s),
4
; pass device information to the driver.
14
; pass device information to the driver.
5
 
15
 
6
; =============================================================================
16
; =============================================================================
7
; ================================= Constants =================================
17
; ================================= Constants =================================
8
; =============================================================================
18
; =============================================================================
9
; USB standard request codes
19
; USB standard request codes
10
USB_GET_STATUS        = 0
20
USB_GET_STATUS        = 0
11
USB_CLEAR_FEATURE     = 1
21
USB_CLEAR_FEATURE     = 1
12
USB_SET_FEATURE       = 3
22
USB_SET_FEATURE       = 3
13
USB_SET_ADDRESS       = 5
23
USB_SET_ADDRESS       = 5
14
USB_GET_DESCRIPTOR    = 6
24
USB_GET_DESCRIPTOR    = 6
15
USB_SET_DESCRIPTOR    = 7
25
USB_SET_DESCRIPTOR    = 7
16
USB_GET_CONFIGURATION = 8
26
USB_GET_CONFIGURATION = 8
17
USB_SET_CONFIGURATION = 9
27
USB_SET_CONFIGURATION = 9
18
USB_GET_INTERFACE     = 10
28
USB_GET_INTERFACE     = 10
19
USB_SET_INTERFACE     = 11
29
USB_SET_INTERFACE     = 11
20
USB_SYNCH_FRAME       = 12
30
USB_SYNCH_FRAME       = 12
21
 
31
 
22
; USB standard descriptor types
32
; USB standard descriptor types
23
USB_DEVICE_DESCR             = 1
33
USB_DEVICE_DESCR             = 1
24
USB_CONFIG_DESCR             = 2
34
USB_CONFIG_DESCR             = 2
25
USB_STRING_DESCR             = 3
35
USB_STRING_DESCR             = 3
26
USB_INTERFACE_DESCR          = 4
36
USB_INTERFACE_DESCR          = 4
27
USB_ENDPOINT_DESCR           = 5
37
USB_ENDPOINT_DESCR           = 5
28
USB_DEVICE_QUALIFIER_DESCR   = 6
38
USB_DEVICE_QUALIFIER_DESCR   = 6
29
USB_OTHER_SPEED_CONFIG_DESCR = 7
39
USB_OTHER_SPEED_CONFIG_DESCR = 7
30
USB_INTERFACE_POWER_DESCR    = 8
40
USB_INTERFACE_POWER_DESCR    = 8
31
 
41
 
32
; Compile-time setting. If set, the code will dump all descriptors as they are
42
; Compile-time setting. If set, the code will dump all descriptors as they are
33
; read to the debug board.
43
; read to the debug board.
34
USB_DUMP_DESCRIPTORS = 1
44
USB_DUMP_DESCRIPTORS = 1
-
 
45
 
-
 
46
; According to the USB specification (9.2.6.3),
-
 
47
; any device must response to SET_ADDRESS in 50 ms, or 5 timer ticks.
-
 
48
; Of course, our world is far from ideal.
-
 
49
; I have seen devices that just NAK everything when being reset from working
-
 
50
; state, but start to work after second reset.
-
 
51
; Our strategy is as follows: give 2 seconds for the first attempt,
-
 
52
; this should be enough for normal devices and not too long to detect buggy ones.
-
 
53
; If the device continues NAKing, reset it and retry several times,
-
 
54
; doubling the interval: 2s -> 4s -> 8s -> 16s. Give up after that.
-
 
55
; Numbers are quite arbitrary.
-
 
56
TIMEOUT_SET_ADDRESS_INITIAL = 200
-
 
57
TIMEOUT_SET_ADDRESS_LAST    = 1600
35
 
58
 
36
; =============================================================================
59
; =============================================================================
37
; ================================ Structures =================================
60
; ================================ Structures =================================
38
; =============================================================================
61
; =============================================================================
39
; USB descriptors. See USB specification for detailed explanations.
62
; USB descriptors. See USB specification for detailed explanations.
40
; First two bytes of every descriptor have the same meaning.
63
; First two bytes of every descriptor have the same meaning.
41
struct usb_descr
64
struct usb_descr
42
bLength                 db      ?
65
bLength                 db      ?
43
; Size of this descriptor in bytes
66
; Size of this descriptor in bytes
44
bDescriptorType         db      ?
67
bDescriptorType         db      ?
45
; One of USB_*_DESCR constants.
68
; One of USB_*_DESCR constants.
46
ends
69
ends
47
 
70
 
48
; USB device descriptor
71
; USB device descriptor
49
struct usb_device_descr usb_descr
72
struct usb_device_descr usb_descr
50
bcdUSB                  dw      ?
73
bcdUSB                  dw      ?
51
; USB Specification Release number in BCD, e.g. 110h = USB 1.1
74
; USB Specification Release number in BCD, e.g. 110h = USB 1.1
52
bDeviceClass            db      ?
75
bDeviceClass            db      ?
53
; USB Device Class Code
76
; USB Device Class Code
54
bDeviceSubClass         db      ?
77
bDeviceSubClass         db      ?
55
; USB Device Subclass Code
78
; USB Device Subclass Code
56
bDeviceProtocol         db      ?
79
bDeviceProtocol         db      ?
57
; USB Device Protocol Code
80
; USB Device Protocol Code
58
bMaxPacketSize0         db      ?
81
bMaxPacketSize0         db      ?
59
; Maximum packet size for zero endpoint
82
; Maximum packet size for zero endpoint
60
idVendor                dw      ?
83
idVendor                dw      ?
61
; Vendor ID
84
; Vendor ID
62
idProduct               dw      ?
85
idProduct               dw      ?
63
; Product ID
86
; Product ID
64
bcdDevice               dw      ?
87
bcdDevice               dw      ?
65
; Device release number in BCD
88
; Device release number in BCD
66
iManufacturer           db      ?
89
iManufacturer           db      ?
67
; Index of string descriptor describing manufacturer
90
; Index of string descriptor describing manufacturer
68
iProduct                db      ?
91
iProduct                db      ?
69
; Index of string descriptor describing product
92
; Index of string descriptor describing product
70
iSerialNumber           db      ?
93
iSerialNumber           db      ?
71
; Index of string descriptor describing serial number
94
; Index of string descriptor describing serial number
72
bNumConfigurations      db      ?
95
bNumConfigurations      db      ?
73
; Number of possible configurations
96
; Number of possible configurations
74
ends
97
ends
75
 
98
 
76
; USB configuration descriptor
99
; USB configuration descriptor
77
struct usb_config_descr usb_descr
100
struct usb_config_descr usb_descr
78
wTotalLength            dw      ?
101
wTotalLength            dw      ?
79
; Total length of data returned for this configuration
102
; Total length of data returned for this configuration
80
bNumInterfaces          db      ?
103
bNumInterfaces          db      ?
81
; Number of interfaces in this configuration
104
; Number of interfaces in this configuration
82
bConfigurationValue     db      ?
105
bConfigurationValue     db      ?
83
; Value for SET_CONFIGURATION control request
106
; Value for SET_CONFIGURATION control request
84
iConfiguration          db      ?
107
iConfiguration          db      ?
85
; Index of string descriptor describing this configuration
108
; Index of string descriptor describing this configuration
86
bmAttributes            db      ?
109
bmAttributes            db      ?
87
; Bit 6 is SelfPowered, bit 5 is RemoteWakeupSupported,
110
; Bit 6 is SelfPowered, bit 5 is RemoteWakeupSupported,
88
; bit 7 must be 1, other bits must be 0
111
; bit 7 must be 1, other bits must be 0
89
bMaxPower               db      ?
112
bMaxPower               db      ?
90
; Maximum power consumption from the bus in 2mA units
113
; Maximum power consumption from the bus in 2mA units
91
ends
114
ends
92
 
115
 
93
; USB interface descriptor
116
; USB interface descriptor
94
struct usb_interface_descr usb_descr
117
struct usb_interface_descr usb_descr
95
; The following two fields work in pair. Sometimes one interface can work
118
; The following two fields work in pair. Sometimes one interface can work
96
; in different modes; e.g. videostream from web-cameras requires different
119
; in different modes; e.g. videostream from web-cameras requires different
97
; bandwidth depending on resolution/quality/compression settings.
120
; bandwidth depending on resolution/quality/compression settings.
98
; Each mode of each interface has its own descriptor with its own endpoints
121
; Each mode of each interface has its own descriptor with its own endpoints
99
; following; all descriptors for one interface have the same bInterfaceNumber,
122
; following; all descriptors for one interface have the same bInterfaceNumber,
100
; and different bAlternateSetting.
123
; and different bAlternateSetting.
101
; By default, any interface operates in mode with bAlternateSetting = 0.
124
; By default, any interface operates in mode with bAlternateSetting = 0.
102
; Often this is the only mode. If there are another modes, the active mode
125
; Often this is the only mode. If there are another modes, the active mode
103
; is selected by SET_INTERFACE(bAlternateSetting) control request.
126
; is selected by SET_INTERFACE(bAlternateSetting) control request.
104
bInterfaceNumber        db      ?
127
bInterfaceNumber        db      ?
105
bAlternateSetting       db      ?
128
bAlternateSetting       db      ?
106
bNumEndpoints           db      ?
129
bNumEndpoints           db      ?
107
; Number of endpoints used by this interface, excluding zero endpoint
130
; Number of endpoints used by this interface, excluding zero endpoint
108
bInterfaceClass         db      ?
131
bInterfaceClass         db      ?
109
; USB Interface Class Code
132
; USB Interface Class Code
110
bInterfaceSubClass      db      ?
133
bInterfaceSubClass      db      ?
111
; USB Interface Subclass Code
134
; USB Interface Subclass Code
112
bInterfaceProtocol      db      ?
135
bInterfaceProtocol      db      ?
113
; USB Interface Protocol Code
136
; USB Interface Protocol Code
114
iInterface              db      ?
137
iInterface              db      ?
115
; Index of string descriptor describing this interface
138
; Index of string descriptor describing this interface
116
ends
139
ends
117
 
140
 
118
; USB endpoint descriptor
141
; USB endpoint descriptor
119
struct usb_endpoint_descr usb_descr
142
struct usb_endpoint_descr usb_descr
120
bEndpointAddress        db      ?
143
bEndpointAddress        db      ?
121
; Lower 4 bits form endpoint number,
144
; Lower 4 bits form endpoint number,
122
; upper bit is 0 for OUT endpoints and 1 for IN endpoints,
145
; upper bit is 0 for OUT endpoints and 1 for IN endpoints,
123
; other bits must be zero
146
; other bits must be zero
124
bmAttributes            db      ?
147
bmAttributes            db      ?
125
; Lower 2 bits form transfer type, one of *_PIPE,
148
; Lower 2 bits form transfer type, one of *_PIPE,
126
; other bits must be zero for non-isochronous endpoints;
149
; other bits must be zero for non-isochronous endpoints;
127
; refer to the USB specification for meaning in isochronous case
150
; refer to the USB specification for meaning in isochronous case
128
wMaxPacketSize          dw      ?
151
wMaxPacketSize          dw      ?
129
; Lower 11 bits form maximum packet size,
152
; Lower 11 bits form maximum packet size,
130
; next two bits specify the number of additional transactions per microframe
153
; next two bits specify the number of additional transactions per microframe
131
; for high-speed periodic endpoints, other bits must be zero.
154
; for high-speed periodic endpoints, other bits must be zero.
132
bInterval               db      ?
155
bInterval               db      ?
133
; Interval for polling endpoint for data transfers.
156
; Interval for polling endpoint for data transfers.
134
; Isochronous and high-speed interrupt endpoints: poll every 2^(bInterval-1)
157
; Isochronous and high-speed interrupt endpoints: poll every 2^(bInterval-1)
135
; (micro)frames
158
; (micro)frames
136
; Full/low-speed interrupt endpoints: poll every bInterval frames
159
; Full/low-speed interrupt endpoints: poll every bInterval frames
137
; High-speed bulk/control OUT endpoints: maximum NAK rate
160
; High-speed bulk/control OUT endpoints: maximum NAK rate
138
ends
161
ends
139
 
162
 
140
; =============================================================================
163
; =============================================================================
141
; =================================== Code ====================================
164
; =================================== Code ====================================
142
; =============================================================================
165
; =============================================================================
143
 
166
 
144
; When a new device is ready to be configured, a controller-specific code
167
; When a new device is ready to be configured, a controller-specific code
145
; calls usb_new_device.
168
; calls usb_new_device.
146
; The sequence of further actions:
169
; The sequence of further actions:
147
; * open pipe for the zero endpoint (usb_new_device);
170
; * open pipe for the zero endpoint (usb_new_device);
148
;   maximum packet size is not known yet, but it must be at least 8 bytes,
171
;   maximum packet size is not known yet, but it must be at least 8 bytes,
149
;   so it is safe to send packets with <= 8 bytes
172
;   so it is safe to send packets with <= 8 bytes
150
; * issue SET_ADDRESS control request (usb_new_device)
173
; * issue SET_ADDRESS control request (usb_new_device)
151
; * set the new device address in the pipe (usb_set_address_callback)
174
; * set the new device address in the pipe (usb_set_address_callback)
152
; * notify a controller-specific code that initialization of other ports
175
; * notify a controller-specific code that initialization of other ports
153
;   can be started (usb_set_address_callback)
176
;   can be started (usb_set_address_callback)
154
; * issue GET_DESCRIPTOR control request for first 8 bytes of device descriptor
177
; * issue GET_DESCRIPTOR control request for first 8 bytes of device descriptor
155
;   (usb_after_set_address)
178
;   (usb_after_set_address)
156
; * first 8 bytes of device descriptor contain the true packet size for zero
179
; * first 8 bytes of device descriptor contain the true packet size for zero
157
;   endpoint, so set the true packet size (usb_get_descr8_callback)
180
;   endpoint, so set the true packet size (usb_get_descr8_callback)
158
; * first 8 bytes of a descriptor contain the full size of this descriptor,
181
; * first 8 bytes of a descriptor contain the full size of this descriptor,
159
;   issue GET_DESCRIPTOR control request for the full device descriptor
182
;   issue GET_DESCRIPTOR control request for the full device descriptor
160
;   (usb_after_set_endpoint_size)
183
;   (usb_after_set_endpoint_size)
161
; * issue GET_DESCRIPTOR control request for first 8 bytes of configuration
184
; * issue GET_DESCRIPTOR control request for first 8 bytes of configuration
162
;   descriptor (usb_get_descr_callback)
185
;   descriptor (usb_get_descr_callback)
163
; * issue GET_DESCRIPTOR control request for full configuration descriptor
186
; * issue GET_DESCRIPTOR control request for full configuration descriptor
164
;   (usb_know_length_callback)
187
;   (usb_know_length_callback)
165
; * issue SET_CONFIGURATION control request (usb_set_config_callback)
188
; * issue SET_CONFIGURATION control request (usb_set_config_callback)
166
; * parse configuration descriptor, load the corresponding driver(s),
189
; * parse configuration descriptor, load the corresponding driver(s),
167
;   pass the configuration descriptor to the driver and let the driver do
190
;   pass the configuration descriptor to the driver and let the driver do
168
;   the further work (usb_got_config_callback)
191
;   the further work (usb_got_config_callback)
169
 
192
 
170
; This function is called from controller-specific part
193
; This function is called from controller-specific part
171
; when a new device is ready to be configured.
194
; when a new device is ready to be configured.
172
; in: ecx -> pseudo-pipe, part of usb_pipe
195
; in: ecx -> pseudo-pipe, part of usb_pipe
173
; in: esi -> usb_controller
196
; in: esi -> usb_controller
174
; in: [esi+usb_controller.ResettingHub] is the pointer to usb_hub for device,
197
; in: [esi+usb_controller.ResettingHub] is the pointer to usb_hub for device,
175
;     NULL if the device is connected to the root hub
198
;     NULL if the device is connected to the root hub
176
; in: [esi+usb_controller.ResettingPort] is the port for the device, zero-based
199
; in: [esi+usb_controller.ResettingPort] is the port for the device, zero-based
177
; in: [esi+usb_controller.ResettingSpeed] is the speed of the device, one of
200
; in: [esi+usb_controller.ResettingSpeed] is the speed of the device, one of
178
;     USB_SPEED_xx.
201
;     USB_SPEED_xx.
179
; out: eax = 0 <=> failed, the caller should disable the port.
202
; out: eax = 0 <=> failed, the caller should disable the port.
180
proc usb_new_device
203
proc usb_new_device
181
        push    ebx edi         ; save used registers to be stdcall
204
        push    ebx edi         ; save used registers to be stdcall
-
 
205
; 1. Check whether we're here because we were trying to reset
-
 
206
; already-registered device in hope to fix something serious.
-
 
207
; If so, skip allocation and go to 6.
-
 
208
        movzx   eax, [esi+usb_controller.ResettingPort]
-
 
209
        mov     edx, [esi+usb_controller.ResettingHub]
-
 
210
        test    edx, edx
-
 
211
        jz      .test_roothub
-
 
212
        mov     edx, [edx+usb_hub.ConnectedDevicesPtr]
-
 
213
        mov     ebx, [edx+eax*4]
-
 
214
        jmp     @f
-
 
215
.test_roothub:
-
 
216
        mov     ebx, [esi+usb_controller.DevicesByPort+eax*4]
-
 
217
@@:
-
 
218
        test    ebx, ebx
-
 
219
        jnz     .try_set_address
182
; 1. Allocate resources. Any device uses the following resources:
220
; 2. Allocate resources. Any device uses the following resources:
183
; - device address in the bus
221
; - device address in the bus
184
; - memory for device data
222
; - memory for device data
185
; - pipe for zero endpoint
223
; - pipe for zero endpoint
186
; If some allocation fails, we must undo our actions. Closing the pipe
224
; If some allocation fails, we must undo our actions. Closing the pipe
187
; is a hard task, so we avoid it and open the pipe as the last resource.
225
; is a hard task, so we avoid it and open the pipe as the last resource.
188
; The order for other two allocations is quite arbitrary.
226
; The order for other two allocations is quite arbitrary.
189
; 1a. Allocate a bus address.
227
; 2a. Allocate a bus address.
190
        push    ecx
228
        push    ecx
191
        call    usb_set_address_request
229
        call    usb_set_address_request
192
        pop     ecx
230
        pop     ecx
193
; 1b. If failed, just return zero.
231
; 2b. If failed, just return zero.
194
        test    eax, eax
232
        test    eax, eax
195
        jz      .nothing
233
        jz      .nothing
196
; 1c. Allocate memory for device data.
234
; 2c. Allocate memory for device data.
197
; For now, we need sizeof.usb_device_data and extra 8 bytes for GET_DESCRIPTOR
235
; For now, we need sizeof.usb_device_data and extra 8 bytes for GET_DESCRIPTOR
198
; input and output, see usb_after_set_address. Later we will reallocate it
236
; input and output, see usb_after_set_address. Later we will reallocate it
199
; to actual size needed for descriptors.
237
; to actual size needed for descriptors.
200
        movi    eax, sizeof.usb_device_data + 8
238
        movi    eax, sizeof.usb_device_data + 8
201
        push    ecx
239
        push    ecx
202
        call    malloc
240
        call    malloc
203
        pop     ecx
241
        pop     ecx
204
; 1d. If failed, free the bus address and return zero.
242
; 2d. If failed, free the bus address and return zero.
205
        test    eax, eax
243
        test    eax, eax
206
        jz      .nomemory
244
        jz      .nomemory
207
; 1e. Open pipe for endpoint zero.
245
; 2e. Open pipe for endpoint zero.
208
; For now, we do not know the actual maximum packet size;
246
; For now, we do not know the actual maximum packet size;
209
; for full-speed devices it can be any of 8, 16, 32, 64 bytes,
247
; for full-speed devices it can be any of 8, 16, 32, 64 bytes,
210
; low-speed devices must have 8 bytes, high-speed devices must have 64 bytes.
248
; low-speed devices must have 8 bytes, high-speed devices must have 64 bytes.
211
; Thus, we must use some fake "maximum packet size" until the actual size
249
; Thus, we must use some fake "maximum packet size" until the actual size
212
; will be known. However, the maximum packet size must be at least 8, and
250
; will be known. However, the maximum packet size must be at least 8, and
213
; initial stages of the configuration process involves only packets of <= 8
251
; initial stages of the configuration process involves only packets of <= 8
214
; bytes, they will be transferred correctly as long as
252
; bytes, they will be transferred correctly as long as
215
; the fake "maximum packet size" is also at least 8.
253
; the fake "maximum packet size" is also at least 8.
216
; Thus, any number >= 8 is suitable for actual hardware.
254
; Thus, any number >= 8 is suitable for actual hardware.
217
; However, software emulation of EHCI in VirtualBox assumes that high-speed
255
; However, software emulation of EHCI in VirtualBox assumes that high-speed
218
; control transfers are those originating from pipes with max packet size = 64,
256
; control transfers are those originating from pipes with max packet size = 64,
219
; even on early stages of the configuration process. This is incorrect,
257
; even on early stages of the configuration process. This is incorrect,
220
; but we have no specific preferences, so let VirtualBox be happy and use 64
258
; but we have no specific preferences, so let VirtualBox be happy and use 64
221
; as the fake "maximum packet size".
259
; as the fake "maximum packet size".
222
        push    eax
260
        push    eax
223
; We will need many zeroes.
261
; We will need many zeroes.
224
; "push edi" is one byte, "push 0" is two bytes; save space, use edi.
262
; "push edi" is one byte, "push 0" is two bytes; save space, use edi.
225
        xor     edi, edi
263
        xor     edi, edi
226
        stdcall usb_open_pipe, ecx, edi, 64, edi, edi
264
        stdcall usb_open_pipe, ecx, edi, 64, edi, edi
227
; Put pointer to pipe into ebx. "xchg eax,reg" is one byte, mov is two bytes.
265
; Put pointer to pipe into ebx. "xchg eax,reg" is one byte, mov is two bytes.
228
        xchg    eax, ebx
266
        xchg    eax, ebx
229
        pop     eax
267
        pop     eax
230
; 1f. If failed, free the memory, the bus address and return zero.
268
; 2f. If failed, free the memory, the bus address and return zero.
231
        test    ebx, ebx
269
        test    ebx, ebx
232
        jz      .freememory
270
        jz      .freememory
233
; 2. Store pointer to device data in the pipe structure.
271
; 3. Store pointer to device data in the pipe structure.
234
        mov     [ebx+usb_pipe.DeviceData], eax
272
        mov     [ebx+usb_pipe.DeviceData], eax
235
; 3. Init device data, using usb_controller.Resetting* variables.
273
; 4. Init device data, using usb_controller.Resetting* variables.
-
 
274
        mov     [eax+usb_device_data.Timer], edi
-
 
275
        mov     dword [eax+usb_device_data.DeviceDescriptor], TIMEOUT_SET_ADDRESS_INITIAL
236
        mov     [eax+usb_device_data.TTHub], edi
276
        mov     [eax+usb_device_data.TTHub], edi
237
        mov     [eax+usb_device_data.TTPort], 0
277
        mov     [eax+usb_device_data.TTPort], 0
238
        mov     [eax+usb_device_data.NumInterfaces], edi
278
        mov     [eax+usb_device_data.NumInterfaces], edi
239
        mov     [eax+usb_device_data.DeviceDescrSize], 0
279
        mov     [eax+usb_device_data.DeviceDescrSize], 0
240
        mov     dl, [esi+usb_controller.ResettingSpeed]
280
        mov     dl, [esi+usb_controller.ResettingSpeed]
241
        mov     [eax+usb_device_data.Speed], dl
281
        mov     [eax+usb_device_data.Speed], dl
242
        mov     [eax+usb_device_data.NumPipes], 1
282
        mov     [eax+usb_device_data.NumPipes], 1
243
        push    ebx
283
        push    ebx
244
        cmp     dl, USB_SPEED_HS
284
        cmp     dl, USB_SPEED_HS
245
        jz      .nott
285
        jz      .nott
246
        mov     ebx, [esi+usb_controller.ResettingHub]
286
        mov     ebx, [esi+usb_controller.ResettingHub]
247
        test    ebx, ebx
287
        test    ebx, ebx
248
        jz      .nott
288
        jz      .nott
249
        mov     cl, [esi+usb_controller.ResettingPort]
289
        mov     cl, [esi+usb_controller.ResettingPort]
250
        mov     edx, [ebx+usb_hub.ConfigPipe]
290
        mov     edx, [ebx+usb_hub.ConfigPipe]
251
        mov     edx, [edx+usb_pipe.DeviceData]
291
        mov     edx, [edx+usb_pipe.DeviceData]
252
        cmp     [edx+usb_device_data.TTHub], 0
292
        cmp     [edx+usb_device_data.TTHub], 0
253
        jz      @f
293
        jz      @f
254
        mov     cl, [edx+usb_device_data.TTPort]
294
        mov     cl, [edx+usb_device_data.TTPort]
255
        mov     ebx, [edx+usb_device_data.TTHub]
295
        mov     ebx, [edx+usb_device_data.TTHub]
256
        jmp     .has_tt
296
        jmp     .has_tt
257
@@:
297
@@:
258
        cmp     [edx+usb_device_data.Speed], USB_SPEED_HS
298
        cmp     [edx+usb_device_data.Speed], USB_SPEED_HS
259
        jnz     .nott
299
        jnz     .nott
260
.has_tt:
300
.has_tt:
261
        mov     [eax+usb_device_data.TTHub], ebx
301
        mov     [eax+usb_device_data.TTHub], ebx
262
        mov     [eax+usb_device_data.TTPort], cl
302
        mov     [eax+usb_device_data.TTPort], cl
263
.nott:
303
.nott:
264
        pop     ebx
304
        pop     ebx
265
        mov     [eax+usb_device_data.ConfigDataSize], edi
305
        mov     [eax+usb_device_data.ConfigDataSize], edi
266
        mov     [eax+usb_device_data.Interfaces], edi
306
        mov     [eax+usb_device_data.Interfaces], edi
267
        movzx   ecx, [esi+usb_controller.ResettingPort]
307
        movzx   ecx, [esi+usb_controller.ResettingPort]
268
        mov     [eax+usb_device_data.Port], cl
308
        mov     [eax+usb_device_data.Port], cl
269
        mov     edx, [esi+usb_controller.ResettingHub]
309
        mov     edx, [esi+usb_controller.ResettingHub]
270
        mov     [eax+usb_device_data.Hub], edx
310
        mov     [eax+usb_device_data.Hub], edx
271
; 4. Store pointer to the config pipe in the hub data.
311
; 5. Store pointer to the config pipe in the hub data.
272
; Config pipe serves as device identifier.
312
; Config pipe serves as device identifier.
273
; Root hubs use the array inside usb_controller structure,
313
; Root hubs use the array inside usb_controller structure,
274
; non-root hubs use the array immediately after usb_hub structure.
314
; non-root hubs use the array immediately after usb_hub structure.
275
        test    edx, edx
315
        test    edx, edx
276
        jz      .roothub
316
        jz      .roothub
277
        mov     edx, [edx+usb_hub.ConnectedDevicesPtr]
317
        mov     edx, [edx+usb_hub.ConnectedDevicesPtr]
278
        mov     [edx+ecx*4], ebx
318
        mov     [edx+ecx*4], ebx
279
        jmp     @f
319
        jmp     @f
280
.roothub:
320
.roothub:
281
        mov     [esi+usb_controller.DevicesByPort+ecx*4], ebx
321
        mov     [esi+usb_controller.DevicesByPort+ecx*4], ebx
282
@@:
322
@@:
283
        call    usb_reinit_pipe_list
323
        call    usb_reinit_pipe_list
284
; 5. Issue SET_ADDRESS control request, using buffer filled in step 1a.
324
; 6. Issue SET_ADDRESS control request, using buffer filled in step 2a.
285
; Use the return value from usb_control_async as our return value;
325
; 6a. Configure timer to force reset after timeout.
-
 
326
; Note: we can't use self-destructing timer, because we need to be able to cancel it,
-
 
327
; and for self-destructing timer we could have race condition in cancelling/destructing.
-
 
328
;        DEBUGF 1,'K : pipe %x\n',ebx
-
 
329
.try_set_address:
-
 
330
        xor     edi, edi
-
 
331
        mov     edx, [ebx+usb_pipe.DeviceData]
-
 
332
        stdcall timer_hs, [edx+usb_device_data.DeviceDescriptor], 7FFFFFFFh, usb_abort_pipe, ebx
-
 
333
        test    eax, eax
-
 
334
        jz      .nothing
-
 
335
        mov     edx, [ebx+usb_pipe.DeviceData]
-
 
336
        mov     [edx+usb_device_data.Timer], eax
286
; if it is zero, then something has failed.
337
; 6b. If it succeeded, setup timer to configure wait timeout.
287
        lea     eax, [esi+usb_controller.SetAddressBuffer]
338
        lea     eax, [esi+usb_controller.SetAddressBuffer]
288
        stdcall usb_control_async, ebx, eax, edi, edi, usb_set_address_callback, edi, edi
339
        stdcall usb_control_async, ebx, eax, edi, edi, usb_set_address_callback, edi, edi
-
 
340
; Use the return value from usb_control_async as our return value;
-
 
341
; if it is zero, then something has failed.
289
.nothing:
342
.nothing:
290
; 6. Return.
343
; 7. Return.
291
        pop     edi ebx         ; restore used registers to be stdcall
344
        pop     edi ebx         ; restore used registers to be stdcall
292
        ret
345
        ret
293
; Handlers of failures in steps 1b, 1d, 1f.
346
; Handlers of failures in steps 2b, 2d, 2f.
294
.freememory:
347
.freememory:
295
        call    free
348
        call    free
296
        jmp     .freeaddr
349
        jmp     .freeaddr
297
.nomemory:
350
.nomemory:
298
        dbgstr 'No memory for device data'
351
        dbgstr 'No memory for device data'
299
.freeaddr:
352
.freeaddr:
300
        mov     ecx, dword [esi+usb_controller.SetAddressBuffer+2]
353
        mov     ecx, dword [esi+usb_controller.SetAddressBuffer+2]
301
        bts     [esi+usb_controller.ExistingAddresses], ecx
354
        bts     [esi+usb_controller.ExistingAddresses], ecx
302
        xor     eax, eax
355
        xor     eax, eax
303
        jmp     .nothing
356
        jmp     .nothing
304
endp
357
endp
305
 
358
 
306
; Helper procedure for usb_new_device.
359
; Helper procedure for usb_new_device.
307
; Allocates a new USB address and fills usb_controller.SetAddressBuffer
360
; Allocates a new USB address and fills usb_controller.SetAddressBuffer
308
; with data for SET_ADDRESS(allocated_address) request.
361
; with data for SET_ADDRESS(allocated_address) request.
309
; out: eax = 0 <=> failed
362
; out: eax = 0 <=> failed
310
; Destroys edi.
363
; Destroys edi.
311
proc usb_set_address_request
364
proc usb_set_address_request
312
; There are 128 bits, one for each possible address.
365
; There are 128 bits, one for each possible address.
313
; Note: only the USB thread works with usb_controller.ExistingAddresses,
366
; Note: only the USB thread works with usb_controller.ExistingAddresses,
314
; so there is no need for synchronization.
367
; so there is no need for synchronization.
315
; We must find a bit set to 1 and clear it.
368
; We must find a bit set to 1 and clear it.
316
; 1. Find the first dword which has a nonzero bit = which is nonzero.
369
; 1. Find the first dword which has a nonzero bit = which is nonzero.
317
        mov     ecx, 128/32
370
        mov     ecx, 128/32
318
        lea     edi, [esi+usb_controller.ExistingAddresses]
371
        lea     edi, [esi+usb_controller.ExistingAddresses]
319
        xor     eax, eax
372
        xor     eax, eax
320
        repz scasd
373
        repz scasd
321
; 2. If all dwords are zero, return an error.
374
; 2. If all dwords are zero, return an error.
322
        jz      .error
375
        jz      .error
323
; 3. The dword at [edi-4] is nonzero. Find the lowest nonzero bit.
376
; 3. The dword at [edi-4] is nonzero. Find the lowest nonzero bit.
324
        bsf     eax, [edi-4]
377
        bsf     eax, [edi-4]
325
; Now eax = bit number inside the dword at [edi-4].
378
; Now eax = bit number inside the dword at [edi-4].
326
; 4. Clear the bit.
379
; 4. Clear the bit.
327
        btr     [edi-4], eax
380
        btr     [edi-4], eax
328
; 5. Generate the address by edi = memory address and eax = bit inside dword.
381
; 5. Generate the address by edi = memory address and eax = bit inside dword.
329
; Address = eax + 8 * (edi-4 - (esi+usb_controller.ExistingAddress)).
382
; Address = eax + 8 * (edi-4 - (esi+usb_controller.ExistingAddress)).
330
        sub     edi, esi
383
        sub     edi, esi
331
        lea     edi, [eax+(edi-4-usb_controller.ExistingAddresses)*8]
384
        lea     edi, [eax+(edi-4-usb_controller.ExistingAddresses)*8]
332
; 6. Store the allocated address in SetAddressBuffer and fill remaining fields.
385
; 6. Store the allocated address in SetAddressBuffer and fill remaining fields.
333
; Note that usb_controller is zeroed at allocation, so only command byte needs
386
; Note that usb_controller is zeroed at allocation, so only command byte needs
334
; to be filled.
387
; to be filled.
335
        mov     byte [esi+usb_controller.SetAddressBuffer+1], USB_SET_ADDRESS
388
        mov     byte [esi+usb_controller.SetAddressBuffer+1], USB_SET_ADDRESS
336
        mov     dword [esi+usb_controller.SetAddressBuffer+2], edi
389
        mov     dword [esi+usb_controller.SetAddressBuffer+2], edi
337
; 7. Return non-zero value in eax.
390
; 7. Return non-zero value in eax.
338
        inc     eax
391
        inc     eax
339
.nothing:
392
.nothing:
340
        ret
393
        ret
341
.error:
394
.error:
342
        dbgstr 'cannot allocate USB address'
395
        dbgstr 'cannot allocate USB address'
343
        xor     eax, eax
396
        xor     eax, eax
344
        jmp     .nothing
397
        jmp     .nothing
345
endp
398
endp
346
 
399
 
347
; This procedure is called by USB stack when SET_ADDRESS request initiated by
400
; This procedure is called by USB stack when SET_ADDRESS request initiated by
348
; usb_new_device is completed, either successfully or unsuccessfully.
401
; usb_new_device is completed, either successfully or unsuccessfully.
349
; Note that USB stack uses esi = pointer to usb_controller.
402
; Note that USB stack uses esi = pointer to usb_controller.
350
proc usb_set_address_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
403
proc usb_set_address_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
351
        push    ebx     ; save ebx to be stdcall
404
        push    ebx     ; save ebx to be stdcall
352
; Load data to registers for further references.
-
 
353
        mov     ebx, [pipe]
405
        mov     ebx, [pipe]
-
 
406
; 1. In any case, cancel the timer.
-
 
407
        mov     eax, [ebx+usb_pipe.DeviceData]
-
 
408
        stdcall cancel_timer_hs, [eax+usb_device_data.Timer]
-
 
409
        mov     eax, [ebx+usb_pipe.DeviceData]
-
 
410
        mov     [eax+usb_device_data.Timer], 0
-
 
411
; Load data to registers for further references.
354
        mov     ecx, dword [esi+usb_controller.SetAddressBuffer+2]
412
        mov     ecx, dword [esi+usb_controller.SetAddressBuffer+2]
355
        mov     eax, [esi+usb_controller.HardwareFunc]
413
        mov     eax, [esi+usb_controller.HardwareFunc]
356
; 1. Check whether the device has accepted new address. If so, proceed to 2.
414
; 2. Check whether the device has accepted new address. If so, proceed to 3.
-
 
415
; Otherwise, go to 4 if killed by usb_set_address_timeout or to 5 otherwise.
-
 
416
        cmp     [status], USB_STATUS_CANCELLED
357
; Otherwise, go to 3.
417
        jz      .timeout
358
        cmp     [status], 0
418
        cmp     [status], 0
359
        jnz     .error
419
        jnz     .error
360
; 2. Address accepted.
420
; 3. Address accepted.
361
; 2a. The controller-specific structure for the control pipe still uses
421
; 3a. The controller-specific structure for the control pipe still uses
362
; zero address. Call the controller-specific function to change it to
422
; zero address. Call the controller-specific function to change it to
363
; the actual address.
423
; the actual address.
364
; Note that the hardware could cache the controller-specific structure,
424
; Note that the hardware could cache the controller-specific structure,
365
; so setting the address could take some time until the cache is evicted.
425
; so setting the address could take some time until the cache is evicted.
366
; Thus, the call is asynchronous; meet us in usb_after_set_address when it will
426
; Thus, the call is asynchronous; meet us in usb_after_set_address when it will
367
; be safe to continue.
427
; be safe to continue.
368
;        dbgstr 'address set in device'
428
;        dbgstr 'address set in device'
369
        call    [eax+usb_hardware_func.SetDeviceAddress]
429
        call    [eax+usb_hardware_func.SetDeviceAddress]
370
; 2b. If the port is in non-root hub, clear 'reset in progress' flag.
430
; 3b. If the port is in non-root hub, clear 'reset in progress' flag.
371
; In any case, proceed to 4.
431
; In any case, proceed to 6.
372
        mov     eax, [esi+usb_controller.ResettingHub]
432
        mov     eax, [esi+usb_controller.ResettingHub]
373
        test    eax, eax
433
        test    eax, eax
374
        jz      .return
434
        jz      .return
375
        and     [eax+usb_hub.Actions], not HUB_RESET_IN_PROGRESS
435
        and     [eax+usb_hub.Actions], not HUB_RESET_IN_PROGRESS
376
.return:
436
.return:
377
; 4. Address configuration done, we can proceed with other ports.
437
; 6. Address configuration done, we can proceed with other ports.
378
; Call the worker function for that.
438
; Call the worker function for that.
379
        call    usb_test_pending_port
439
        call    usb_test_pending_port
-
 
440
.wakeup:
-
 
441
        push    esi edi
-
 
442
        call    usb_wakeup
-
 
443
        pop     edi esi
380
.nothing:
444
.nothing:
381
        pop     ebx     ; restore ebx to be stdcall
445
        pop     ebx     ; restore ebx to be stdcall
382
        ret
446
        ret
-
 
447
.timeout:
-
 
448
; 4. Device continues to NAK the request. Reset it and retry.
-
 
449
        mov     edx, [ebx+usb_pipe.DeviceData]
-
 
450
        mov     ecx, [edx+usb_device_data.DeviceDescriptor]
-
 
451
        add     ecx, ecx
-
 
452
        cmp     ecx, TIMEOUT_SET_ADDRESS_LAST
-
 
453
        ja      .error
-
 
454
        mov     [edx+usb_device_data.DeviceDescriptor], ecx
-
 
455
        dbgstr 'Timeout in USB device initialization, trying to reset...'
-
 
456
        cmp     [esi+usb_controller.ResettingHub], 0
-
 
457
        jz      .reset_roothub
-
 
458
        push    esi
-
 
459
        mov     esi, [esi+usb_controller.ResettingHub]
-
 
460
        call    usb_hub_initiate_reset
-
 
461
        pop     esi
-
 
462
        jmp     .nothing
-
 
463
.reset_roothub:
-
 
464
        movzx   ecx, [esi+usb_controller.ResettingPort]
-
 
465
        call    [eax+usb_hardware_func.InitiateReset]
-
 
466
        jmp     .wakeup
383
.error:
467
.error:
384
; 3. Device error: device not responding, disconnect etc.
468
; 5. Device error: device not responding, disconnect etc.
385
        DEBUGF 1,'K : error %d in SET_ADDRESS, USB device disabled\n',[status]
469
        DEBUGF 1,'K : error %d in SET_ADDRESS, USB device disabled\n',[status]
386
; 3a. The address has not been accepted. Mark it as free.
470
; 5a. The address has not been accepted. Mark it as free.
387
        bts     dword [esi+usb_controller.ExistingAddresses], ecx
471
        bts     dword [esi+usb_controller.ExistingAddresses], ecx
388
; 3b. Disable the port with bad device.
472
; 5b. Disable the port with bad device.
389
; For the root hub, call the controller-specific function and go to 6.
473
; For the root hub, call the controller-specific function and go to 6.
390
; For non-root hubs, let the hub code do its work and return (the request
474
; For non-root hubs, let the hub code do its work and return (the request
391
; could take some time, the hub code is responsible for proceeding).
475
; could take some time, the hub code is responsible for proceeding).
392
        cmp     [esi+usb_controller.ResettingHub], 0
476
        cmp     [esi+usb_controller.ResettingHub], 0
393
        jz      .roothub
477
        jz      .roothub
394
        mov     eax, [esi+usb_controller.ResettingHub]
478
        mov     eax, [esi+usb_controller.ResettingHub]
395
        call    usb_hub_disable_resetting_port
479
        call    usb_hub_disable_resetting_port
396
        jmp     .nothing
480
        jmp     .nothing
397
.roothub:
481
.roothub:
398
        movzx   ecx, [esi+usb_controller.ResettingPort]
482
        movzx   ecx, [esi+usb_controller.ResettingPort]
399
        call    [eax+usb_hardware_func.PortDisable]
483
        call    [eax+usb_hardware_func.PortDisable]
400
        jmp     .return
484
        jmp     .return
401
endp
485
endp
402
 
486
 
403
; This procedure is called from usb_subscription_done when the hardware cache
487
; This procedure is called from usb_subscription_done when the hardware cache
404
; is cleared after request from usb_set_address_callback.
488
; is cleared after request from usb_set_address_callback.
405
; in: ebx -> usb_pipe
489
; in: ebx -> usb_pipe
406
proc usb_after_set_address
490
proc usb_after_set_address
407
;        dbgstr 'address set for controller'
491
;        dbgstr 'address set for controller'
408
; Issue control transfer GET_DESCRIPTOR(DEVICE_DESCR) for first 8 bytes.
492
; Issue control transfer GET_DESCRIPTOR(DEVICE_DESCR) for first 8 bytes.
409
; Remember, we still do not know the actual packet size;
493
; Remember, we still do not know the actual packet size;
410
; 8-bytes-request is safe.
494
; 8-bytes-request is safe.
411
; usb_new_device has allocated 8 extra bytes besides sizeof.usb_device_data;
495
; usb_new_device has allocated 8 extra bytes besides sizeof.usb_device_data;
412
; use them for both input and output.
496
; use them for both input and output.
413
        mov     eax, [ebx+usb_pipe.DeviceData]
497
        mov     eax, [ebx+usb_pipe.DeviceData]
414
        add     eax, usb_device_data.DeviceDescriptor
498
        add     eax, usb_device_data.DeviceDescriptor
415
        mov     dword [eax], \
499
        mov     dword [eax], \
416
                80h + \         ; device-to-host, standard, device-wide
500
                80h + \         ; device-to-host, standard, device-wide
417
                (USB_GET_DESCRIPTOR shl 8) + \  ; request
501
                (USB_GET_DESCRIPTOR shl 8) + \  ; request
418
                (0 shl 16) + \  ; descriptor index: there is only one
502
                (0 shl 16) + \  ; descriptor index: there is only one
419
                (USB_DEVICE_DESCR shl 24)       ; descriptor type
503
                (USB_DEVICE_DESCR shl 24)       ; descriptor type
420
        mov     dword [eax+4], 8 shl 16         ; data length
504
        mov     dword [eax+4], 8 shl 16         ; data length
421
        stdcall usb_control_async, ebx, eax, eax, 8, usb_get_descr8_callback, eax, 0
505
        stdcall usb_control_async, ebx, eax, eax, 8, usb_get_descr8_callback, eax, 0
422
        ret
506
        ret
423
endp
507
endp
424
 
508
 
425
; This procedure is called by USB stack when GET_DESCRIPTOR(DEVICE_DESCR)
509
; This procedure is called by USB stack when GET_DESCRIPTOR(DEVICE_DESCR)
426
; request initiated by usb_after_set_address is completed, either successfully
510
; request initiated by usb_after_set_address is completed, either successfully
427
; or unsuccessfully.
511
; or unsuccessfully.
428
; Note that USB stack uses esi = pointer to usb_controller.
512
; Note that USB stack uses esi = pointer to usb_controller.
429
proc usb_get_descr8_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
513
proc usb_get_descr8_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
430
;       mov     eax, [buffer]
514
;       mov     eax, [buffer]
431
;       DEBUGF 1,'K : descr8: l=%x; %x %x %x %x %x %x %x %x\n',[length],\
515
;       DEBUGF 1,'K : descr8: l=%x; %x %x %x %x %x %x %x %x\n',[length],\
432
;               [eax]:2,[eax+1]:2,[eax+2]:2,[eax+3]:2,[eax+4]:2,[eax+5]:2,[eax+6]:2,[eax+7]:2
516
;               [eax]:2,[eax+1]:2,[eax+2]:2,[eax+3]:2,[eax+4]:2,[eax+5]:2,[eax+6]:2,[eax+7]:2
433
        push    edi ebx         ; save used registers to be stdcall
517
        push    edi ebx         ; save used registers to be stdcall
434
        mov     ebx, [pipe]
518
        mov     ebx, [pipe]
435
; 1. Check whether the operation was successful.
519
; 1. Check whether the operation was successful.
436
; If not, say something to the debug board and stop the initialization.
520
; If not, say something to the debug board and stop the initialization.
437
        cmp     [status], 0
521
        cmp     [status], 0
438
        jnz     .error
522
        jnz     .error
439
; 2. Length of descriptor must be at least sizeof.usb_device_descr bytes.
523
; 2. Length of descriptor must be at least sizeof.usb_device_descr bytes.
440
; If not, say something to the debug board and stop the initialization.
524
; If not, say something to the debug board and stop the initialization.
441
        mov     eax, [ebx+usb_pipe.DeviceData]
525
        mov     eax, [ebx+usb_pipe.DeviceData]
442
        cmp     [eax+usb_device_data.DeviceDescriptor+usb_device_descr.bLength], sizeof.usb_device_descr
526
        cmp     [eax+usb_device_data.DeviceDescriptor+usb_device_descr.bLength], sizeof.usb_device_descr
443
        jb      .error
527
        jb      .error
444
; 3. Now first 8 bytes of device descriptor are known;
528
; 3. Now first 8 bytes of device descriptor are known;
445
; set DeviceDescrSize accordingly.
529
; set DeviceDescrSize accordingly.
446
        mov     [eax+usb_device_data.DeviceDescrSize], 8
530
        mov     [eax+usb_device_data.DeviceDescrSize], 8
447
; 4. The controller-specific structure for the control pipe still uses
531
; 4. The controller-specific structure for the control pipe still uses
448
; the fake "maximum packet size". Call the controller-specific function to
532
; the fake "maximum packet size". Call the controller-specific function to
449
; change it to the actual packet size from the device.
533
; change it to the actual packet size from the device.
450
; Note that the hardware could cache the controller-specific structure,
534
; Note that the hardware could cache the controller-specific structure,
451
; so changing it could take some time until the cache is evicted.
535
; so changing it could take some time until the cache is evicted.
452
; Thus, the call is asynchronous; meet us in usb_after_set_endpoint_size
536
; Thus, the call is asynchronous; meet us in usb_after_set_endpoint_size
453
; when it will be safe to continue.
537
; when it will be safe to continue.
454
        movzx   ecx, [eax+usb_device_data.DeviceDescriptor+usb_device_descr.bMaxPacketSize0]
538
        movzx   ecx, [eax+usb_device_data.DeviceDescriptor+usb_device_descr.bMaxPacketSize0]
455
        mov     eax, [esi+usb_controller.HardwareFunc]
539
        mov     eax, [esi+usb_controller.HardwareFunc]
456
        call    [eax+usb_hardware_func.SetEndpointPacketSize]
540
        call    [eax+usb_hardware_func.SetEndpointPacketSize]
457
.nothing:
541
.nothing:
458
; 5. Return.
542
; 5. Return.
459
        pop     ebx edi         ; restore used registers to be stdcall
543
        pop     ebx edi         ; restore used registers to be stdcall
460
        ret
544
        ret
461
.error:
545
.error:
462
        dbgstr 'error with USB device descriptor'
546
        dbgstr 'error with USB device descriptor'
463
        jmp     .nothing
547
        jmp     .nothing
464
endp
548
endp
465
 
549
 
466
; This procedure is called from usb_subscription_done when the hardware cache
550
; This procedure is called from usb_subscription_done when the hardware cache
467
; is cleared after request from usb_get_descr8_callback.
551
; is cleared after request from usb_get_descr8_callback.
468
; in: ebx -> usb_pipe
552
; in: ebx -> usb_pipe
469
proc usb_after_set_endpoint_size
553
proc usb_after_set_endpoint_size
470
; 1. Reallocate memory for device data:
554
; 1. Reallocate memory for device data:
471
; add memory for now-known size of device descriptor and extra 8 bytes
555
; add memory for now-known size of device descriptor and extra 8 bytes
472
; for further actions.
556
; for further actions.
473
; 1a. Allocate new memory.
557
; 1a. Allocate new memory.
474
        mov     eax, [ebx+usb_pipe.DeviceData]
558
        mov     eax, [ebx+usb_pipe.DeviceData]
475
        movzx   eax, [eax+usb_device_data.DeviceDescriptor+usb_device_descr.bLength]
559
        movzx   eax, [eax+usb_device_data.DeviceDescriptor+usb_device_descr.bLength]
476
; save length for step 2
560
; save length for step 2
477
        push    eax
561
        push    eax
478
        add     eax, sizeof.usb_device_data + 8
562
        add     eax, sizeof.usb_device_data + 8
479
        call    malloc
563
        call    malloc
480
; 1b. If failed, say something to the debug board and stop the initialization.
564
; 1b. If failed, say something to the debug board and stop the initialization.
481
        test    eax, eax
565
        test    eax, eax
482
        jz      .nomemory
566
        jz      .nomemory
483
; 1c. Copy data from old memory to new memory and switch the pointer in usb_pipe.
567
; 1c. Copy data from old memory to new memory and switch the pointer in usb_pipe.
484
        push    eax
568
        push    eax
485
        push    esi edi
569
        push    esi edi
486
        mov     esi, [ebx+usb_pipe.DeviceData]
570
        mov     esi, [ebx+usb_pipe.DeviceData]
487
        mov     [ebx+usb_pipe.DeviceData], eax
571
        mov     [ebx+usb_pipe.DeviceData], eax
488
        mov     edi, eax
572
        mov     edi, eax
489
        mov     eax, esi
573
        mov     eax, esi
490
        mov     ecx, sizeof.usb_device_data / 4
574
        mov     ecx, sizeof.usb_device_data / 4
491
        rep movsd
575
        rep movsd
492
        pop     edi esi
576
        pop     edi esi
493
        call    usb_reinit_pipe_list
577
        call    usb_reinit_pipe_list
494
; 1d. Free the old memory.
578
; 1d. Free the old memory.
495
        call    free
579
        call    free
496
        pop     eax
580
        pop     eax
497
; 2. Issue control transfer GET_DESCRIPTOR(DEVICE) for full descriptor.
581
; 2. Issue control transfer GET_DESCRIPTOR(DEVICE) for full descriptor.
498
; restore length saved in step 1a
582
; restore length saved in step 1a
499
        pop     edx
583
        pop     edx
500
        add     eax, sizeof.usb_device_data
584
        add     eax, sizeof.usb_device_data
501
        mov     dword [eax], \
585
        mov     dword [eax], \
502
                80h + \         ; device-to-host, standard, device-wide
586
                80h + \         ; device-to-host, standard, device-wide
503
                (USB_GET_DESCRIPTOR shl 8) + \  ; request
587
                (USB_GET_DESCRIPTOR shl 8) + \  ; request
504
                (0 shl 16) + \  ; descriptor index: there is only one
588
                (0 shl 16) + \  ; descriptor index: there is only one
505
                (USB_DEVICE_DESCR shl 24)       ; descriptor type
589
                (USB_DEVICE_DESCR shl 24)       ; descriptor type
506
        and     dword [eax+4], 0
590
        and     dword [eax+4], 0
507
        mov     [eax+6], dl     ; data length
591
        mov     [eax+6], dl     ; data length
508
        stdcall usb_control_async, ebx, eax, eax, edx, usb_get_descr_callback, eax, 0
592
        stdcall usb_control_async, ebx, eax, eax, edx, usb_get_descr_callback, eax, 0
509
; 3. Return.
593
; 3. Return.
510
        ret
594
        ret
511
.nomemory:
595
.nomemory:
512
        dbgstr 'No memory for device data'
596
        dbgstr 'No memory for device data'
513
        ret
597
        ret
514
endp
598
endp
515
 
599
 
516
; This procedure is called by USB stack when GET_DESCRIPTOR(DEVICE)
600
; This procedure is called by USB stack when GET_DESCRIPTOR(DEVICE)
517
; request initiated by usb_after_set_endpoint_size is completed,
601
; request initiated by usb_after_set_endpoint_size is completed,
518
; either successfully or unsuccessfully.
602
; either successfully or unsuccessfully.
519
proc usb_get_descr_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
603
proc usb_get_descr_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
520
; Note: the prolog is the same as in usb_get_descr8_callback.
604
; Note: the prolog is the same as in usb_get_descr8_callback.
521
        push    edi ebx         ; save used registers to be stdcall
605
        push    edi ebx         ; save used registers to be stdcall
522
; 1. Check whether the operation was successful.
606
; 1. Check whether the operation was successful.
523
; If not, say something to the debug board and stop the initialization.
607
; If not, say something to the debug board and stop the initialization.
524
        cmp     [status], 0
608
        cmp     [status], 0
525
        jnz     usb_get_descr8_callback.error
609
        jnz     usb_get_descr8_callback.error
526
; The full descriptor is known, dump it if specified by compile-time option.
610
; The full descriptor is known, dump it if specified by compile-time option.
527
if USB_DUMP_DESCRIPTORS
611
if USB_DUMP_DESCRIPTORS
528
        mov     eax, [buffer]
612
        mov     eax, [buffer]
529
        mov     ecx, [length]
613
        mov     ecx, [length]
530
        sub     ecx, 8
614
        sub     ecx, 8
531
        jbe     .skipdebug
615
        jbe     .skipdebug
532
        DEBUGF 1,'K : device descriptor:'
616
        DEBUGF 1,'K : device descriptor:'
533
@@:
617
@@:
534
        DEBUGF 1,' %x',[eax]:2
618
        DEBUGF 1,' %x',[eax]:2
535
        inc     eax
619
        inc     eax
536
        dec     ecx
620
        dec     ecx
537
        jnz     @b
621
        jnz     @b
538
        DEBUGF 1,'\n'
622
        DEBUGF 1,'\n'
539
.skipdebug:
623
.skipdebug:
540
end if
624
end if
541
; 2. Check that bLength is the same as was in the previous request.
625
; 2. Check that bLength is the same as was in the previous request.
542
; If not, say something to the debug board and stop the initialization.
626
; If not, say something to the debug board and stop the initialization.
543
; It is important, because usb_after_set_endpoint_size has allocated memory
627
; It is important, because usb_after_set_endpoint_size has allocated memory
544
; according to the old bLength. Note that [length] for control transfers
628
; according to the old bLength. Note that [length] for control transfers
545
; includes 8 bytes of setup packet, so data length = [length] - 8.
629
; includes 8 bytes of setup packet, so data length = [length] - 8.
546
        mov     eax, [buffer]
630
        mov     eax, [buffer]
547
        movzx   ecx, [eax+usb_device_descr.bLength]
631
        movzx   ecx, [eax+usb_device_descr.bLength]
548
        add     ecx, 8
632
        add     ecx, 8
549
        cmp     [length], ecx
633
        cmp     [length], ecx
550
        jnz     usb_get_descr8_callback.error
634
        jnz     usb_get_descr8_callback.error
551
; Amuse the user if she is watching the debug board.
635
; Amuse the user if she is watching the debug board.
552
        mov     cl, [eax+usb_device_descr.bNumConfigurations]
636
        mov     cl, [eax+usb_device_descr.bNumConfigurations]
553
        DEBUGF 1,'K : found USB device with ID %x:%x, %d configuration(s)\n',\
637
        DEBUGF 1,'K : found USB device with ID %x:%x, %d configuration(s)\n',\
554
                [eax+usb_device_descr.idVendor]:4,\
638
                [eax+usb_device_descr.idVendor]:4,\
555
                [eax+usb_device_descr.idProduct]:4,\
639
                [eax+usb_device_descr.idProduct]:4,\
556
                cl
640
                cl
557
; 3. If there are no configurations, stop the initialization.
641
; 3. If there are no configurations, stop the initialization.
558
        cmp     [eax+usb_device_descr.bNumConfigurations], 0
642
        cmp     [eax+usb_device_descr.bNumConfigurations], 0
559
        jz      .nothing
643
        jz      .nothing
560
; 4. Copy length of device descriptor to device data structure.
644
; 4. Copy length of device descriptor to device data structure.
561
        movzx   edx, [eax+usb_device_descr.bLength]
645
        movzx   edx, [eax+usb_device_descr.bLength]
562
        mov     [eax+usb_device_data.DeviceDescrSize-usb_device_data.DeviceDescriptor], dl
646
        mov     [eax+usb_device_data.DeviceDescrSize-usb_device_data.DeviceDescriptor], dl
563
; 5. Issue control transfer GET_DESCRIPTOR(CONFIGURATION). We do not know
647
; 5. Issue control transfer GET_DESCRIPTOR(CONFIGURATION). We do not know
564
; the full length of that descriptor, so start with first 8 bytes, they contain
648
; the full length of that descriptor, so start with first 8 bytes, they contain
565
; the full length.
649
; the full length.
566
; usb_after_set_endpoint_size has allocated 8 extra bytes after the
650
; usb_after_set_endpoint_size has allocated 8 extra bytes after the
567
; device descriptor, use them for both input and output.
651
; device descriptor, use them for both input and output.
568
        add     eax, edx
652
        add     eax, edx
569
        mov     dword [eax], \
653
        mov     dword [eax], \
570
                80h + \         ; device-to-host, standard, device-wide
654
                80h + \         ; device-to-host, standard, device-wide
571
                (USB_GET_DESCRIPTOR shl 8) + \  ; request
655
                (USB_GET_DESCRIPTOR shl 8) + \  ; request
572
                (0 shl 16) + \  ; descriptor index: there is only one
656
                (0 shl 16) + \  ; descriptor index: there is only one
573
                (USB_CONFIG_DESCR shl 24)       ; descriptor type
657
                (USB_CONFIG_DESCR shl 24)       ; descriptor type
574
        mov     dword [eax+4], 8 shl 16         ; data length
658
        mov     dword [eax+4], 8 shl 16         ; data length
575
        stdcall usb_control_async, [pipe], eax, eax, 8, usb_know_length_callback, eax, 0
659
        stdcall usb_control_async, [pipe], eax, eax, 8, usb_know_length_callback, eax, 0
576
.nothing:
660
.nothing:
577
; 6. Return.
661
; 6. Return.
578
        pop     ebx edi         ; restore used registers to be stdcall
662
        pop     ebx edi         ; restore used registers to be stdcall
579
        ret
663
        ret
580
endp
664
endp
581
 
665
 
582
; This procedure is called by USB stack when GET_DESCRIPTOR(CONFIGURATION)
666
; This procedure is called by USB stack when GET_DESCRIPTOR(CONFIGURATION)
583
; request initiated by usb_get_descr_callback is completed,
667
; request initiated by usb_get_descr_callback is completed,
584
; either successfully or unsuccessfully.
668
; either successfully or unsuccessfully.
585
proc usb_know_length_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
669
proc usb_know_length_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
586
        push    ebx             ; save used registers to be stdcall
670
        push    ebx             ; save used registers to be stdcall
587
; 1. Check whether the operation was successful.
671
; 1. Check whether the operation was successful.
588
; If not, say something to the debug board and stop the initialization.
672
; If not, say something to the debug board and stop the initialization.
589
        cmp     [status], 0
673
        cmp     [status], 0
590
        jnz     .error
674
        jnz     .error
591
; 2. Get the total length of data associated with config descriptor and store
675
; 2. Get the total length of data associated with config descriptor and store
592
; it in device data structure. The total length must be at least
676
; it in device data structure. The total length must be at least
593
; sizeof.usb_config_descr bytes; if not, say something to the debug board and
677
; sizeof.usb_config_descr bytes; if not, say something to the debug board and
594
; stop the initialization.
678
; stop the initialization.
595
        mov     eax, [buffer]
679
        mov     eax, [buffer]
596
        mov     edx, [pipe]
680
        mov     edx, [pipe]
597
        movzx   ecx, [eax+usb_config_descr.wTotalLength]
681
        movzx   ecx, [eax+usb_config_descr.wTotalLength]
598
        mov     eax, [edx+usb_pipe.DeviceData]
682
        mov     eax, [edx+usb_pipe.DeviceData]
599
        cmp     ecx, sizeof.usb_config_descr
683
        cmp     ecx, sizeof.usb_config_descr
600
        jb      .error
684
        jb      .error
601
        mov     [eax+usb_device_data.ConfigDataSize], ecx
685
        mov     [eax+usb_device_data.ConfigDataSize], ecx
602
; 3. Reallocate memory for device data:
686
; 3. Reallocate memory for device data:
603
; include usb_device_data structure, device descriptor,
687
; include usb_device_data structure, device descriptor,
604
; config descriptor with all associated data, and extra bytes
688
; config descriptor with all associated data, and extra bytes
605
; sufficient for 8 bytes control packet and for one usb_interface_data struc.
689
; sufficient for 8 bytes control packet and for one usb_interface_data struc.
606
; Align extra bytes to dword boundary.
690
; Align extra bytes to dword boundary.
607
if sizeof.usb_interface_data > 8
691
if sizeof.usb_interface_data > 8
608
.extra_size = sizeof.usb_interface_data
692
.extra_size = sizeof.usb_interface_data
609
else
693
else
610
.extra_size = 8
694
.extra_size = 8
611
end if
695
end if
612
; 3a. Allocate new memory.
696
; 3a. Allocate new memory.
613
        movzx   edx, [eax+usb_device_data.DeviceDescrSize]
697
        movzx   edx, [eax+usb_device_data.DeviceDescrSize]
614
        lea     eax, [ecx+edx+sizeof.usb_device_data+.extra_size+3]
698
        lea     eax, [ecx+edx+sizeof.usb_device_data+.extra_size+3]
615
        and     eax, not 3
699
        and     eax, not 3
616
        push    eax
700
        push    eax
617
        call    malloc
701
        call    malloc
618
        pop     edx
702
        pop     edx
619
; 3b. If failed, say something to the debug board and stop the initialization.
703
; 3b. If failed, say something to the debug board and stop the initialization.
620
        test    eax, eax
704
        test    eax, eax
621
        jz      .nomemory
705
        jz      .nomemory
622
; 3c. Copy data from old memory to new memory and switch the pointer in usb_pipe.
706
; 3c. Copy data from old memory to new memory and switch the pointer in usb_pipe.
623
        push    eax
707
        push    eax
624
        mov     ebx, [pipe]
708
        mov     ebx, [pipe]
625
        push    esi edi
709
        push    esi edi
626
        mov     esi, [ebx+usb_pipe.DeviceData]
710
        mov     esi, [ebx+usb_pipe.DeviceData]
627
        mov     edi, eax
711
        mov     edi, eax
628
        mov     [ebx+usb_pipe.DeviceData], eax
712
        mov     [ebx+usb_pipe.DeviceData], eax
629
        mov     eax, esi
713
        mov     eax, esi
630
        movzx   ecx, [esi+usb_device_data.DeviceDescrSize]
714
        movzx   ecx, [esi+usb_device_data.DeviceDescrSize]
631
        sub     edx, .extra_size
715
        sub     edx, .extra_size
632
        mov     [esi+usb_device_data.Interfaces], edx
716
        mov     [esi+usb_device_data.Interfaces], edx
633
        add     ecx, sizeof.usb_device_data + 8
717
        add     ecx, sizeof.usb_device_data + 8
634
        mov     edx, ecx
718
        mov     edx, ecx
635
        shr     ecx, 2
719
        shr     ecx, 2
636
        and     edx, 3
720
        and     edx, 3
637
        rep movsd
721
        rep movsd
638
        mov     ecx, edx
722
        mov     ecx, edx
639
        rep movsb
723
        rep movsb
640
        pop     edi esi
724
        pop     edi esi
641
        call    usb_reinit_pipe_list
725
        call    usb_reinit_pipe_list
642
; 3d. Free old memory.
726
; 3d. Free old memory.
643
        call    free
727
        call    free
644
        pop     eax
728
        pop     eax
645
; 4. Issue control transfer GET_DESCRIPTOR(DEVICE) for full descriptor.
729
; 4. Issue control transfer GET_DESCRIPTOR(CONFIGURATION) for full descriptor.
646
        movzx   ecx, [eax+usb_device_data.DeviceDescrSize]
730
        movzx   ecx, [eax+usb_device_data.DeviceDescrSize]
647
        mov     edx, [eax+usb_device_data.ConfigDataSize]
731
        mov     edx, [eax+usb_device_data.ConfigDataSize]
648
        lea     eax, [eax+ecx+sizeof.usb_device_data]
732
        lea     eax, [eax+ecx+sizeof.usb_device_data]
649
        mov     dword [eax], \
733
        mov     dword [eax], \
650
                80h + \         ; device-to-host, standard, device-wide
734
                80h + \         ; device-to-host, standard, device-wide
651
                (USB_GET_DESCRIPTOR shl 8) + \  ; request
735
                (USB_GET_DESCRIPTOR shl 8) + \  ; request
652
                (0 shl 16) + \  ; descriptor index: there is only one
736
                (0 shl 16) + \  ; descriptor index: there is only one
653
                (USB_CONFIG_DESCR shl 24)       ; descriptor type
737
                (USB_CONFIG_DESCR shl 24)       ; descriptor type
654
        and     dword [eax+4], 0
738
        and     dword [eax+4], 0
655
        mov     word [eax+6], dx        ; data length
739
        mov     word [eax+6], dx        ; data length
656
        stdcall usb_control_async, [pipe], eax, eax, edx, usb_set_config_callback, eax, 0
740
        stdcall usb_control_async, [pipe], eax, eax, edx, usb_set_config_callback, eax, 0
657
.nothing:
741
.nothing:
658
; 5. Return.
742
; 5. Return.
659
        pop     ebx             ; restore used registers to be stdcall
743
        pop     ebx             ; restore used registers to be stdcall
660
        ret
744
        ret
661
.error:
745
.error:
662
        dbgstr 'error with USB configuration descriptor'
746
        dbgstr 'error with USB configuration descriptor'
663
        jmp     .nothing
747
        jmp     .nothing
664
.nomemory:
748
.nomemory:
665
        dbgstr 'No memory for device data'
749
        dbgstr 'No memory for device data'
666
        jmp     .nothing
750
        jmp     .nothing
667
endp
751
endp
668
 
752
 
669
; This procedure is called by USB stack when GET_DESCRIPTOR(CONFIGURATION)
753
; This procedure is called by USB stack when GET_DESCRIPTOR(CONFIGURATION)
670
; request initiated by usb_know_length_callback is completed,
754
; request initiated by usb_know_length_callback is completed,
671
; either successfully or unsuccessfully.
755
; either successfully or unsuccessfully.
672
proc usb_set_config_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
756
proc usb_set_config_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
673
; Note that the prolog is the same as in usb_know_length_callback.
757
; Note that the prolog is the same as in usb_know_length_callback.
674
        push    ebx             ; save used registers to be stdcall
758
        push    ebx             ; save used registers to be stdcall
675
; 1. Check whether the operation was successful.
759
; 1. Check whether the operation was successful.
676
; If not, say something to the debug board and stop the initialization.
760
; If not, say something to the debug board and stop the initialization.
677
        xor     ecx, ecx
761
        xor     ecx, ecx
678
        mov     ebx, [pipe]
762
        mov     ebx, [pipe]
679
        cmp     [status], ecx
763
        cmp     [status], ecx
680
        jnz     usb_know_length_callback.error
764
        jnz     usb_know_length_callback.error
681
; The full descriptor is known, dump it if specified by compile-time option.
765
; The full descriptor is known, dump it if specified by compile-time option.
682
if USB_DUMP_DESCRIPTORS
766
if USB_DUMP_DESCRIPTORS
683
        mov     eax, [buffer]
767
        mov     eax, [buffer]
684
        mov     ecx, [length]
768
        mov     ecx, [length]
685
        sub     ecx, 8
769
        sub     ecx, 8
686
        jbe     .skip_debug
770
        jbe     .skip_debug
687
        DEBUGF 1,'K : config descriptor:'
771
        DEBUGF 1,'K : config descriptor:'
688
@@:
772
@@:
689
        DEBUGF 1,' %x',[eax]:2
773
        DEBUGF 1,' %x',[eax]:2
690
        inc     eax
774
        inc     eax
691
        dec     ecx
775
        dec     ecx
692
        jnz     @b
776
        jnz     @b
693
        DEBUGF 1,'\n'
777
        DEBUGF 1,'\n'
694
.skip_debug:
778
.skip_debug:
695
        xor     ecx, ecx
779
        xor     ecx, ecx
696
end if
780
end if
697
; 2. Issue control transfer SET_CONFIGURATION to activate this configuration.
781
; 2. Issue control transfer SET_CONFIGURATION to activate this configuration.
698
; Usually this is the only configuration.
782
; Usually this is the only configuration.
699
; Use extra bytes allocated by usb_know_length_callback;
783
; Use extra bytes allocated by usb_know_length_callback;
700
; offset from device data start is stored in Interfaces.
784
; offset from device data start is stored in Interfaces.
701
        mov     eax, [ebx+usb_pipe.DeviceData]
785
        mov     eax, [ebx+usb_pipe.DeviceData]
702
        mov     edx, [buffer]
786
        mov     edx, [buffer]
703
        add     eax, [eax+usb_device_data.Interfaces]
787
        add     eax, [eax+usb_device_data.Interfaces]
704
        mov     dl, [edx+usb_config_descr.bConfigurationValue]
788
        mov     dl, [edx+usb_config_descr.bConfigurationValue]
705
        mov     dword [eax], USB_SET_CONFIGURATION shl 8
789
        mov     dword [eax], USB_SET_CONFIGURATION shl 8
706
        mov     dword [eax+4], ecx
790
        mov     dword [eax+4], ecx
707
        mov     byte [eax+2], dl
791
        mov     byte [eax+2], dl
708
        stdcall usb_control_async, [pipe], eax, ecx, ecx, usb_got_config_callback, [buffer], ecx
792
        stdcall usb_control_async, [pipe], eax, ecx, ecx, usb_got_config_callback, [buffer], ecx
709
        pop     ebx             ; restore used registers to be stdcall
793
        pop     ebx             ; restore used registers to be stdcall
710
        ret
794
        ret
711
endp
795
endp
712
 
796
 
713
; This procedure is called by USB stack when SET_CONFIGURATION
797
; This procedure is called by USB stack when SET_CONFIGURATION
714
; request initiated by usb_set_config_callback is completed,
798
; request initiated by usb_set_config_callback is completed,
715
; either successfully or unsuccessfully.
799
; either successfully or unsuccessfully.
716
; If successfully, the device is configured and ready to work,
800
; If successfully, the device is configured and ready to work,
717
; pass the device to the corresponding driver(s).
801
; pass the device to the corresponding driver(s).
718
proc usb_got_config_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
802
proc usb_got_config_callback stdcall, pipe:dword, status:dword, buffer:dword, length:dword, calldata:dword
719
locals
803
locals
720
InterfacesData  dd      ?
804
InterfacesData  dd      ?
721
NumInterfaces   dd      ?
805
NumInterfaces   dd      ?
722
driver          dd      ?
806
driver          dd      ?
723
endl
807
endl
724
; 1. If there was an error, say something to the debug board and stop the
808
; 1. If there was an error, say something to the debug board and stop the
725
; initialization.
809
; initialization.
726
        cmp     [status], 0
810
        cmp     [status], 0
727
        jz      @f
811
        jz      @f
728
        dbgstr 'USB error in SET_CONFIGURATION'
812
        dbgstr 'USB error in SET_CONFIGURATION'
729
        ret
813
        ret
730
@@:
814
@@:
731
        push    ebx edi         ; save used registers to be stdcall
815
        push    ebx edi         ; save used registers to be stdcall
732
; 2. Sanity checks: the total length must be the same as before (because we
816
; 2. Sanity checks: the total length must be the same as before (because we
733
; have allocated memory assuming the old value), length of config descriptor
817
; have allocated memory assuming the old value), length of config descriptor
734
; must be at least sizeof.usb_config_descr (we use fields from it),
818
; must be at least sizeof.usb_config_descr (we use fields from it),
735
; there must be at least one interface.
819
; there must be at least one interface.
736
        mov     ebx, [pipe]
820
        mov     ebx, [pipe]
737
        mov     ebx, [ebx+usb_pipe.DeviceData]
821
        mov     ebx, [ebx+usb_pipe.DeviceData]
738
        mov     eax, [calldata]
822
        mov     eax, [calldata]
739
        mov     edx, [ebx+usb_device_data.ConfigDataSize]
823
        mov     edx, [ebx+usb_device_data.ConfigDataSize]
740
        cmp     [eax+usb_config_descr.wTotalLength], dx
824
        cmp     [eax+usb_config_descr.wTotalLength], dx
741
        jnz     .invalid
825
        jnz     .invalid
742
        cmp     [eax+usb_config_descr.bLength], 9
826
        cmp     [eax+usb_config_descr.bLength], 9
743
        jb      .invalid
827
        jb      .invalid
744
        movzx   edx, [eax+usb_config_descr.bNumInterfaces]
828
        movzx   edx, [eax+usb_config_descr.bNumInterfaces]
745
        test    edx, edx
829
        test    edx, edx
746
        jnz     @f
830
        jnz     @f
747
.invalid:
831
.invalid:
748
        dbgstr 'error: invalid configuration descriptor'
832
        dbgstr 'error: invalid configuration descriptor'
749
        jmp     .nothing
833
        jmp     .nothing
750
@@:
834
@@:
751
; 3. Store the number of interfaces in device data structure.
835
; 3. Store the number of interfaces in device data structure.
752
        mov     [ebx+usb_device_data.NumInterfaces], edx
836
        mov     [ebx+usb_device_data.NumInterfaces], edx
753
; 4. If there is only one interface (which happens quite often),
837
; 4. If there is only one interface (which happens quite often),
754
; the memory allocated in usb_know_length_callback is sufficient.
838
; the memory allocated in usb_know_length_callback is sufficient.
755
; Otherwise (which also happens quite often), reallocate device data.
839
; Otherwise (which also happens quite often), reallocate device data.
756
; 4a. Check whether there is only one interface. If so, skip this step.
840
; 4a. Check whether there is only one interface. If so, skip this step.
757
        cmp     edx, 1
841
        cmp     edx, 1
758
        jz      .has_memory
842
        jz      .has_memory
759
; 4b. Allocate new memory.
843
; 4b. Allocate new memory.
760
        mov     eax, [ebx+usb_device_data.Interfaces]
844
        mov     eax, [ebx+usb_device_data.Interfaces]
761
        lea     eax, [eax+edx*sizeof.usb_interface_data]
845
        lea     eax, [eax+edx*sizeof.usb_interface_data]
762
        call    malloc
846
        call    malloc
763
; 4c. If failed, say something to the debug board and
847
; 4c. If failed, say something to the debug board and
764
; stop the initialization.
848
; stop the initialization.
765
        test    eax, eax
849
        test    eax, eax
766
        jnz     @f
850
        jnz     @f
767
        dbgstr 'No memory for device data'
851
        dbgstr 'No memory for device data'
768
        jmp     .nothing
852
        jmp     .nothing
769
@@:
853
@@:
770
; 4d. Copy data from old memory to new memory and switch the pointer in usb_pipe.
854
; 4d. Copy data from old memory to new memory and switch the pointer in usb_pipe.
771
        push    eax
855
        push    eax
772
        push    esi
856
        push    esi
773
        mov     ebx, [pipe]
857
        mov     ebx, [pipe]
774
        mov     edi, eax
858
        mov     edi, eax
775
        mov     esi, [ebx+usb_pipe.DeviceData]
859
        mov     esi, [ebx+usb_pipe.DeviceData]
776
        mov     [ebx+usb_pipe.DeviceData], eax
860
        mov     [ebx+usb_pipe.DeviceData], eax
777
        mov     eax, esi
861
        mov     eax, esi
778
        mov     ecx, [esi+usb_device_data.Interfaces]
862
        mov     ecx, [esi+usb_device_data.Interfaces]
779
        shr     ecx, 2
863
        shr     ecx, 2
780
        rep movsd
864
        rep movsd
781
        pop     esi
865
        pop     esi
782
        call    usb_reinit_pipe_list
866
        call    usb_reinit_pipe_list
783
; 4e. Free old memory.
867
; 4e. Free old memory.
784
        call    free
868
        call    free
785
        pop     ebx
869
        pop     ebx
786
.has_memory:
870
.has_memory:
787
; 5. Initialize interfaces table: zero all contents.
871
; 5. Initialize interfaces table: zero all contents.
788
        mov     edi, [ebx+usb_device_data.Interfaces]
872
        mov     edi, [ebx+usb_device_data.Interfaces]
789
        add     edi, ebx
873
        add     edi, ebx
790
        mov     [InterfacesData], edi
874
        mov     [InterfacesData], edi
791
        mov     ecx, [ebx+usb_device_data.NumInterfaces]
875
        mov     ecx, [ebx+usb_device_data.NumInterfaces]
792
if sizeof.usb_interface_data <> 8
876
if sizeof.usb_interface_data <> 8
793
You have changed sizeof.usb_interface_data? Modify this place too.
877
You have changed sizeof.usb_interface_data? Modify this place too.
794
end if
878
end if
795
        add     ecx, ecx
879
        add     ecx, ecx
796
        xor     eax, eax
880
        xor     eax, eax
797
        rep stosd
881
        rep stosd
798
; No interfaces are found yet.
882
; No interfaces are found yet.
799
        mov     [NumInterfaces], eax
883
        mov     [NumInterfaces], eax
800
; 6. Get the pointer to config descriptor data.
884
; 6. Get the pointer to config descriptor data.
801
; Note: if there was reallocation, [buffer] is not valid anymore,
885
; Note: if there was reallocation, [buffer] is not valid anymore,
802
; so calculate value based on usb_device_data.
886
; so calculate value based on usb_device_data.
803
        movzx   eax, [ebx+usb_device_data.DeviceDescrSize]
887
        movzx   eax, [ebx+usb_device_data.DeviceDescrSize]
804
        lea     eax, [eax+ebx+sizeof.usb_device_data]
888
        lea     eax, [eax+ebx+sizeof.usb_device_data]
805
        mov     [calldata], eax
889
        mov     [calldata], eax
806
        mov     ecx, [ebx+usb_device_data.ConfigDataSize]
890
        mov     ecx, [ebx+usb_device_data.ConfigDataSize]
807
; 7. Loop over all descriptors,
891
; 7. Loop over all descriptors,
808
; scan for interface descriptors with bAlternateSetting = 0,
892
; scan for interface descriptors with bAlternateSetting = 0,
809
; load the corresponding driver, call its AddDevice function.
893
; load the corresponding driver, call its AddDevice function.
810
.descriptor_loop:
894
.descriptor_loop:
811
; While in loop: eax points to the current descriptor,
895
; While in loop: eax points to the current descriptor,
812
; ecx = number of bytes left, the iteration starts only if ecx is nonzero,
896
; ecx = number of bytes left, the iteration starts only if ecx is nonzero,
813
; edx = size of the current descriptor.
897
; edx = size of the current descriptor.
814
; 7a. The first byte is always accessible; it contains the length of
898
; 7a. The first byte is always accessible; it contains the length of
815
; the current descriptor. Validate that the length is at least 2 bytes,
899
; the current descriptor. Validate that the length is at least 2 bytes,
816
; and the entire descriptor is readable (the length is at most number of
900
; and the entire descriptor is readable (the length is at most number of
817
; bytes left).
901
; bytes left).
818
        movzx   edx, [eax+usb_descr.bLength]
902
        movzx   edx, [eax+usb_descr.bLength]
819
        cmp     edx, sizeof.usb_descr
903
        cmp     edx, sizeof.usb_descr
820
        jb      .invalid
904
        jb      .invalid
821
        cmp     ecx, edx
905
        cmp     ecx, edx
822
        jb      .invalid
906
        jb      .invalid
823
; 7b. Check descriptor type. Ignore all non-INTERFACE descriptor.
907
; 7b. Check descriptor type. Ignore all non-INTERFACE descriptor.
824
        cmp     byte [eax+usb_descr.bDescriptorType], USB_INTERFACE_DESCR
908
        cmp     byte [eax+usb_descr.bDescriptorType], USB_INTERFACE_DESCR
825
        jz      .interface
909
        jz      .interface
826
.next_descriptor:
910
.next_descriptor:
827
; 7c. Advance pointer, decrease length left, if there is still something left,
911
; 7c. Advance pointer, decrease length left, if there is still something left,
828
; continue the loop.
912
; continue the loop.
829
        add     eax, edx
913
        add     eax, edx
830
        sub     ecx, edx
914
        sub     ecx, edx
831
        jnz     .descriptor_loop
915
        jnz     .descriptor_loop
832
.done:
916
.done:
833
.nothing:
917
.nothing:
834
        pop     edi ebx         ; restore used registers to be stdcall
918
        pop     edi ebx         ; restore used registers to be stdcall
835
        ret
919
        ret
836
.interface:
920
.interface:
837
; 7d. Validate the descriptor length.
921
; 7d. Validate the descriptor length.
838
        cmp     edx, sizeof.usb_interface_descr
922
        cmp     edx, sizeof.usb_interface_descr
839
        jb      .next_descriptor
923
        jb      .next_descriptor
840
; 7e. If bAlternateSetting is nonzero, this descriptor actually describes
924
; 7e. If bAlternateSetting is nonzero, this descriptor actually describes
841
; another mode of already known interface and belongs to the already loaded
925
; another mode of already known interface and belongs to the already loaded
842
; driver; amuse the user and continue to 7c.
926
; driver; amuse the user and continue to 7c.
843
        cmp     byte [eax+usb_interface_descr.bAlternateSetting], 0
927
        cmp     byte [eax+usb_interface_descr.bAlternateSetting], 0
844
        jz      @f
928
        jz      @f
845
        DEBUGF 1,'K : note: alternate setting with %x/%x/%x\n',\
929
        DEBUGF 1,'K : note: alternate setting with %x/%x/%x\n',\
846
                [eax+usb_interface_descr.bInterfaceClass]:2,\
930
                [eax+usb_interface_descr.bInterfaceClass]:2,\
847
                [eax+usb_interface_descr.bInterfaceSubClass]:2,\
931
                [eax+usb_interface_descr.bInterfaceSubClass]:2,\
848
                [eax+usb_interface_descr.bInterfaceProtocol]:2
932
                [eax+usb_interface_descr.bInterfaceProtocol]:2
849
        jmp     .next_descriptor
933
        jmp     .next_descriptor
850
@@:
934
@@:
851
; 7f. Check that the new interface does not overflow allocated table.
935
; 7f. Check that the new interface does not overflow allocated table.
852
        mov     edx, [NumInterfaces]
936
        mov     edx, [NumInterfaces]
853
        inc     edx
937
        inc     edx
854
        cmp     edx, [ebx+usb_device_data.NumInterfaces]
938
        cmp     edx, [ebx+usb_device_data.NumInterfaces]
855
        ja      .invalid
939
        ja      .invalid
856
; 7g. We have found a new interface. Advance bookkeeping vars.
940
; 7g. We have found a new interface. Advance bookkeeping vars.
857
        mov     [NumInterfaces], edx
941
        mov     [NumInterfaces], edx
858
        add     [InterfacesData], sizeof.usb_interface_data
942
        add     [InterfacesData], sizeof.usb_interface_data
859
; 7h. Save length left and pointer to the current interface descriptor.
943
; 7h. Save length left and pointer to the current interface descriptor.
860
        push    ecx eax
944
        push    ecx eax
861
; Amuse the user if she is watching the debug board.
945
; Amuse the user if she is watching the debug board.
862
        DEBUGF 1,'K : USB interface class/subclass/protocol = %x/%x/%x\n',\
946
        DEBUGF 1,'K : USB interface class/subclass/protocol = %x/%x/%x\n',\
863
                [eax+usb_interface_descr.bInterfaceClass]:2,\
947
                [eax+usb_interface_descr.bInterfaceClass]:2,\
864
                [eax+usb_interface_descr.bInterfaceSubClass]:2,\
948
                [eax+usb_interface_descr.bInterfaceSubClass]:2,\
865
                [eax+usb_interface_descr.bInterfaceProtocol]:2
949
                [eax+usb_interface_descr.bInterfaceProtocol]:2
866
; 7i. Select the correct driver based on interface class.
950
; 7i. Select the correct driver based on interface class.
867
; For hubs, go to 7j. Otherwise, go to 7k.
951
; For hubs, go to 7j. Otherwise, go to 7k.
868
; Note: this should be rewritten as table-based lookup when more drivers will
952
; Note: this should be rewritten as table-based lookup when more drivers will
869
; be available.
953
; be available.
870
        cmp     byte [eax+usb_interface_descr.bInterfaceClass], 9
954
        cmp     byte [eax+usb_interface_descr.bInterfaceClass], 9
871
        jz      .found_hub
955
        jz      .found_hub
872
        mov     edx, usb_hid_name
956
        mov     edx, usb_hid_name
873
        cmp     byte [eax+usb_interface_descr.bInterfaceClass], 3
957
        cmp     byte [eax+usb_interface_descr.bInterfaceClass], 3
874
        jz      .load_driver
958
        jz      .load_driver
875
        mov     edx, usb_print_name
959
        mov     edx, usb_print_name
876
        cmp     byte [eax+usb_interface_descr.bInterfaceClass], 7
960
        cmp     byte [eax+usb_interface_descr.bInterfaceClass], 7
877
        jz      .load_driver
961
        jz      .load_driver
878
        mov     edx, usb_stor_name
962
        mov     edx, usb_stor_name
879
        cmp     byte [eax+usb_interface_descr.bInterfaceClass], 8
963
        cmp     byte [eax+usb_interface_descr.bInterfaceClass], 8
880
        jz      .load_driver
964
        jz      .load_driver
881
        mov     edx, usb_other_name
965
        mov     edx, usb_other_name
882
        jmp     .load_driver
966
        jmp     .load_driver
883
.found_hub:
967
.found_hub:
884
; 7j. Hubs are a part of USB stack, thus, integrated into the kernel.
968
; 7j. Hubs are a part of USB stack, thus, integrated into the kernel.
885
; Use the pointer to hub callbacks and go to 7m.
969
; Use the pointer to hub callbacks and go to 7m.
886
        mov     eax, usb_hub_pseudosrv - USBSRV.usb_func
970
        mov     eax, usb_hub_pseudosrv - USBSRV.usb_func
887
        jmp     .driver_loaded
971
        jmp     .driver_loaded
888
.load_driver:
972
.load_driver:
889
; 7k. Load the corresponding driver.
973
; 7k. Load the corresponding driver.
890
        push    ebx esi edi
974
        push    ebx esi edi
891
        stdcall get_service, edx
975
        stdcall get_service, edx
892
        pop     edi esi ebx
976
        pop     edi esi ebx
893
; 7l. If failed, say something to the debug board and go to 7p.
977
; 7l. If failed, say something to the debug board and go to 7p.
894
        test    eax, eax
978
        test    eax, eax
895
        jnz     .driver_loaded
979
        jnz     .driver_loaded
896
        dbgstr 'failed to load class driver'
980
        dbgstr 'failed to load class driver'
897
        jmp     .next_descriptor2
981
        jmp     .next_descriptor2
898
.driver_loaded:
982
.driver_loaded:
899
; 7m. Call AddDevice function of the driver.
983
; 7m. Call AddDevice function of the driver.
900
; Note that top of stack contains a pointer to the current interface,
984
; Note that top of stack contains a pointer to the current interface,
901
; saved by step 7h.
985
; saved by step 7h.
902
        mov     [driver], eax
986
        mov     [driver], eax
903
        mov     eax, [eax+USBSRV.usb_func]
987
        mov     eax, [eax+USBSRV.usb_func]
904
        pop     edx
988
        pop     edx
905
        push    edx
989
        push    edx
906
; Note: usb_hub_init assumes that edx points to usb_interface_descr,
990
; Note: usb_hub_init assumes that edx points to usb_interface_descr,
907
; ecx = length rest; if you change the code, modify usb_hub_init also.
991
; ecx = length rest; if you change the code, modify usb_hub_init also.
908
        stdcall [eax+USBFUNC.add_device], [pipe], [calldata], edx
992
        stdcall [eax+USBFUNC.add_device], [pipe], [calldata], edx
909
; 7n. If failed, say something to the debug board and go to 7p.
993
; 7n. If failed, say something to the debug board and go to 7p.
910
        test    eax, eax
994
        test    eax, eax
911
        jnz     .store_data
995
        jnz     .store_data
912
        dbgstr 'USB device initialization failed'
996
        dbgstr 'USB device initialization failed'
913
        jmp     .next_descriptor2
997
        jmp     .next_descriptor2
914
.store_data:
998
.store_data:
915
; 7o. Store the returned value and the driver handle to InterfacesData.
999
; 7o. Store the returned value and the driver handle to InterfacesData.
916
; Note that step 7g has already advanced InterfacesData.
1000
; Note that step 7g has already advanced InterfacesData.
917
        mov     edx, [InterfacesData]
1001
        mov     edx, [InterfacesData]
918
        mov     [edx+usb_interface_data.DriverData-sizeof.usb_interface_data], eax
1002
        mov     [edx+usb_interface_data.DriverData-sizeof.usb_interface_data], eax
919
        mov     eax, [driver]
1003
        mov     eax, [driver]
920
        mov     [edx+usb_interface_data.DriverFunc-sizeof.usb_interface_data], eax
1004
        mov     [edx+usb_interface_data.DriverFunc-sizeof.usb_interface_data], eax
921
.next_descriptor2:
1005
.next_descriptor2:
922
; 7p. Restore registers saved in step 7h, get the descriptor length and
1006
; 7p. Restore registers saved in step 7h, get the descriptor length and
923
; continue to 7c.
1007
; continue to 7c.
924
        pop     eax ecx
1008
        pop     eax ecx
925
        movzx   edx, byte [eax+usb_descr.bLength]
1009
        movzx   edx, byte [eax+usb_descr.bLength]
926
        jmp     .next_descriptor
1010
        jmp     .next_descriptor
927
endp
1011
endp
928
 
1012
 
929
; Driver names, see step 7i of usb_got_config_callback.
1013
; Driver names, see step 7i of usb_got_config_callback.
930
iglobal
1014
iglobal
931
usb_hid_name    db      'usbhid',0
1015
usb_hid_name    db      'usbhid',0
932
usb_stor_name   db      'usbstor',0
1016
usb_stor_name   db      'usbstor',0
933
usb_print_name  db      'usbprint',0
1017
usb_print_name  db      'usbprint',0
934
usb_other_name  db      'usbother',0
1018
usb_other_name  db      'usbother',0
935
endg
1019
endg