Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2013-2024. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8.  
  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.  
  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.  
  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
  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:
  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.
  225. ; 2a. Allocate a bus address.
  226.         push    ecx
  227.         call    usb_set_address_request
  228.         pop     ecx
  229. ; 2b. If failed, just return zero.
  230.         test    eax, eax
  231.         jz      .nothing
  232. ; 2c. Allocate memory for device data.
  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.
  236.         movi    eax, sizeof.usb_device_data + 8
  237.         push    ecx
  238.         call    malloc
  239.         pop     ecx
  240. ; 2d. If failed, free the bus address and return zero.
  241.         test    eax, eax
  242.         jz      .nomemory
  243. ; 2e. Open pipe for endpoint zero.
  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
  266. ; 2f. If failed, free the memory, the bus address and return zero.
  267.         test    ebx, ebx
  268.         jz      .freememory
  269. ; 3. Store pointer to device data in the pipe structure.
  270.         mov     [ebx+usb_pipe.DeviceData], eax
  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
  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
  280.         mov     [eax+usb_device_data.NumPipes], 1
  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
  303.         mov     [eax+usb_device_data.ConfigDataSize], edi
  304.         mov     [eax+usb_device_data.Interfaces], edi
  305.         movzx   ecx, [esi+usb_controller.ResettingPort]
  306.         mov     [eax+usb_device_data.Port], cl
  307.         mov     edx, [esi+usb_controller.ResettingHub]
  308.         mov     [eax+usb_device_data.Hub], edx
  309. ; 5. Store pointer to the config pipe in the hub data.
  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
  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
  338. ; Use the return value from usb_control_async as our return value;
  339. ; if it is zero, then something has failed.
  340. .nothing:
  341. ; 7. Return.
  342.         pop     edi ebx         ; restore used registers to be stdcall
  343.         ret
  344. ; Handlers of failures in steps 2b, 2d, 2f.
  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
  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
  409. ; Load data to registers for further references.
  410.         mov     ecx, dword [esi+usb_controller.SetAddressBuffer+2]
  411.         mov     eax, [esi+usb_controller.HardwareFunc]
  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
  416.         cmp     [status], 0
  417.         jnz     .error
  418. ; 3. Address accepted.
  419. ; 3a. The controller-specific structure for the control pipe still uses
  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.
  426. ;        dbgstr 'address set in device'
  427.         call    [eax+usb_hardware_func.SetDeviceAddress]
  428. ; 3b. If the port is in non-root hub, clear 'reset in progress' flag.
  429. ; In any case, proceed to 6.
  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:
  435. ; 6. Address configuration done, we can proceed with other ports.
  436. ; Call the worker function for that.
  437.         call    usb_test_pending_port
  438. .wakeup:
  439.         push    esi edi
  440.         call    usb_wakeup
  441.         pop     edi esi
  442. .nothing:
  443.         pop     ebx     ; restore ebx to be stdcall
  444.         ret
  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
  465. .error:
  466. ; 5. Device error: device not responding, disconnect etc.
  467.         DEBUGF 1,'K : error %d in SET_ADDRESS, USB device disabled\n',[status]
  468. ; 5a. The address has not been accepted. Mark it as free.
  469.         bts     dword [esi+usb_controller.ExistingAddresses], ecx
  470. ; 5b. Disable the port with bad device.
  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
  489. ;        dbgstr 'address set for controller'
  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
  572.         mov     ecx, sizeof.usb_device_data / 4
  573.         rep movsd
  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
  727. ; 4. Issue control transfer GET_DESCRIPTOR(CONFIGURATION) for full descriptor.
  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.
  834.         mov     [ebx+usb_device_data.NumInterfaces], edx
  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
  873.         mov     ecx, [ebx+usb_device_data.NumInterfaces]
  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]
  935.         inc     edx
  936.         cmp     edx, [ebx+usb_device_data.NumInterfaces]
  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
  1018.