diff --git a/kernel/trunk/bus/usb/hub.inc b/kernel/trunk/bus/usb/hub.inc index aea5acd125..b5a4fdab49 100644 --- a/kernel/trunk/bus/usb/hub.inc +++ b/kernel/trunk/bus/usb/hub.inc @@ -219,30 +219,46 @@ virtual at esp .config dd ? ; pointer to usb_config_descr .interface dd ? ; pointer to usb_interface_descr end virtual +; 1. Check that the maximal nesting is not exceeded: +; 5 non-root hubs is the maximum according to the spec. + mov ebx, [.pipe] + movi ecx, 5 + mov eax, ebx +.count_parents: + mov eax, [eax+usb_pipe.DeviceData] + mov eax, [eax+usb_device_data.Hub] + test eax, eax + jz .depth_ok + mov eax, [eax+usb_hub.ConfigPipe] + dec ecx + jnz .count_parents + dbgstr 'Hub chain is too long' + jmp .return0 +.depth_ok: ; Hubs use one IN interrupt endpoint for polling the device -; 1. Locate the descriptor of the interrupt endpoint. +; 2. Locate the descriptor of the interrupt endpoint. ; Loop over all descriptors owned by this interface. .lookep: -; 1a. Skip the current descriptor. +; 2a. Skip the current descriptor. movzx eax, [edx+usb_descr.bLength] add edx, eax sub ecx, eax jb .errorep -; 1b. Length of data left must be at least sizeof.usb_endpoint_descr. +; 2b. Length of data left must be at least sizeof.usb_endpoint_descr. cmp ecx, sizeof.usb_endpoint_descr jb .errorep -; 1c. If we have found another interface descriptor but not found our endpoint, +; 2c. If we have found another interface descriptor but not found our endpoint, ; this is an error: all subsequent descriptors belong to that interface ; (or further interfaces). cmp [edx+usb_endpoint_descr.bDescriptorType], USB_INTERFACE_DESCR jz .errorep -; 1d. Ignore all interface-related descriptors except endpoint descriptor. +; 2d. Ignore all interface-related descriptors except endpoint descriptor. cmp [edx+usb_endpoint_descr.bDescriptorType], USB_ENDPOINT_DESCR jnz .lookep -; 1e. Length of endpoint descriptor must be at least sizeof.usb_endpoint_descr. +; 2e. Length of endpoint descriptor must be at least sizeof.usb_endpoint_descr. cmp [edx+usb_endpoint_descr.bLength], sizeof.usb_endpoint_descr jb .errorep -; 1f. Ignore all endpoints except for INTERRUPT IN. +; 2f. Ignore all endpoints except for INTERRUPT IN. cmp [edx+usb_endpoint_descr.bEndpointAddress], 0 jge .lookep mov al, [edx+usb_endpoint_descr.bmAttributes] @@ -251,23 +267,22 @@ end virtual jnz .lookep ; We have located the descriptor for INTERRUPT IN endpoint, ; the pointer is in edx. -; 2. Allocate memory for the hub descriptor. +; 3. Allocate memory for the hub descriptor. ; Maximum length (assuming 255 downstream ports) is 40 bytes. ; Allocate 4 extra bytes to keep wMaxPacketSize. -; 2a. Save registers. +; 3a. Save registers. push edx -; 2b. Call the allocator. +; 3b. Call the allocator. movi eax, 44 call malloc -; 2c. Restore registers. +; 3c. Restore registers. pop ecx -; 2d. If failed, say something to the debug board and return error. +; 3d. If failed, say something to the debug board and return error. test eax, eax jz .nomemory -; 2e. Store the pointer in esi. xchg eax,r32 is one byte shorter than mov. +; 3e. Store the pointer in esi. xchg eax,r32 is one byte shorter than mov. xchg esi, eax -; 3. Open a pipe for the status endpoint with descriptor found in step 1. - mov ebx, [.pipe] +; 4. Open a pipe for the status endpoint with descriptor found in step 1. movzx eax, [ecx+usb_endpoint_descr.bEndpointAddress] movzx edx, [ecx+usb_endpoint_descr.bInterval] movzx ecx, [ecx+usb_endpoint_descr.wMaxPacketSize] @@ -276,11 +291,11 @@ end virtual push ecx stdcall usb_open_pipe, ebx, eax, ecx, INTERRUPT_PIPE, edx pop ecx -; If failed, free the memory allocated in step 2, +; If failed, free the memory allocated in step 3, ; say something to the debug board and return error. test eax, eax jz .free -; 4. Send control query for the hub descriptor, +; 5. Send control query for the hub descriptor, ; pass status pipe as a callback parameter, ; allow short packets. and ecx, (1 shl 11) - 1 @@ -291,7 +306,7 @@ end virtual (USB_HUB_DESCRIPTOR shl 24) mov dword [esi+4], 40 shl 16 stdcall usb_control_async, ebx, esi, esi, 40, usb_hub_got_config, eax, 1 -; 5. If failed, free the memory allocated in step 2, +; 6. If failed, free the memory allocated in step 3, ; say something to the debug board and return error. test eax, eax jz .free