Subversion Repositories Kolibri OS

Rev

Rev 5363 | Details | Compare with Previous | Last modification | View Log | RSS feed

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