Subversion Repositories Kolibri OS

Rev

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

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