Rev 4227 | Rev 4305 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4227 | Rev 4302 | ||
---|---|---|---|
Line 217... | Line 217... | ||
217 | dd ? ; return address |
217 | dd ? ; return address |
218 | .pipe dd ? ; handle of the config pipe |
218 | .pipe dd ? ; handle of the config pipe |
219 | .config dd ? ; pointer to usb_config_descr |
219 | .config dd ? ; pointer to usb_config_descr |
220 | .interface dd ? ; pointer to usb_interface_descr |
220 | .interface dd ? ; pointer to usb_interface_descr |
221 | end virtual |
221 | end virtual |
- | 222 | ; 1. Check that the maximal nesting is not exceeded: |
|
- | 223 | ; 5 non-root hubs is the maximum according to the spec. |
|
- | 224 | mov ebx, [.pipe] |
|
- | 225 | movi ecx, 5 |
|
- | 226 | mov eax, ebx |
|
- | 227 | .count_parents: |
|
- | 228 | mov eax, [eax+usb_pipe.DeviceData] |
|
- | 229 | mov eax, [eax+usb_device_data.Hub] |
|
- | 230 | test eax, eax |
|
- | 231 | jz .depth_ok |
|
- | 232 | mov eax, [eax+usb_hub.ConfigPipe] |
|
- | 233 | dec ecx |
|
- | 234 | jnz .count_parents |
|
- | 235 | dbgstr 'Hub chain is too long' |
|
- | 236 | jmp .return0 |
|
- | 237 | .depth_ok: |
|
222 | ; Hubs use one IN interrupt endpoint for polling the device |
238 | ; Hubs use one IN interrupt endpoint for polling the device |
223 | ; 1. Locate the descriptor of the interrupt endpoint. |
239 | ; 2. Locate the descriptor of the interrupt endpoint. |
224 | ; Loop over all descriptors owned by this interface. |
240 | ; Loop over all descriptors owned by this interface. |
225 | .lookep: |
241 | .lookep: |
226 | ; 1a. Skip the current descriptor. |
242 | ; 2a. Skip the current descriptor. |
227 | movzx eax, [edx+usb_descr.bLength] |
243 | movzx eax, [edx+usb_descr.bLength] |
228 | add edx, eax |
244 | add edx, eax |
229 | sub ecx, eax |
245 | sub ecx, eax |
230 | jb .errorep |
246 | jb .errorep |
231 | ; 1b. Length of data left must be at least sizeof.usb_endpoint_descr. |
247 | ; 2b. Length of data left must be at least sizeof.usb_endpoint_descr. |
232 | cmp ecx, sizeof.usb_endpoint_descr |
248 | cmp ecx, sizeof.usb_endpoint_descr |
233 | jb .errorep |
249 | jb .errorep |
234 | ; 1c. If we have found another interface descriptor but not found our endpoint, |
250 | ; 2c. If we have found another interface descriptor but not found our endpoint, |
235 | ; this is an error: all subsequent descriptors belong to that interface |
251 | ; this is an error: all subsequent descriptors belong to that interface |
236 | ; (or further interfaces). |
252 | ; (or further interfaces). |
237 | cmp [edx+usb_endpoint_descr.bDescriptorType], USB_INTERFACE_DESCR |
253 | cmp [edx+usb_endpoint_descr.bDescriptorType], USB_INTERFACE_DESCR |
238 | jz .errorep |
254 | jz .errorep |
239 | ; 1d. Ignore all interface-related descriptors except endpoint descriptor. |
255 | ; 2d. Ignore all interface-related descriptors except endpoint descriptor. |
240 | cmp [edx+usb_endpoint_descr.bDescriptorType], USB_ENDPOINT_DESCR |
256 | cmp [edx+usb_endpoint_descr.bDescriptorType], USB_ENDPOINT_DESCR |
241 | jnz .lookep |
257 | jnz .lookep |
242 | ; 1e. Length of endpoint descriptor must be at least sizeof.usb_endpoint_descr. |
258 | ; 2e. Length of endpoint descriptor must be at least sizeof.usb_endpoint_descr. |
243 | cmp [edx+usb_endpoint_descr.bLength], sizeof.usb_endpoint_descr |
259 | cmp [edx+usb_endpoint_descr.bLength], sizeof.usb_endpoint_descr |
244 | jb .errorep |
260 | jb .errorep |
245 | ; 1f. Ignore all endpoints except for INTERRUPT IN. |
261 | ; 2f. Ignore all endpoints except for INTERRUPT IN. |
246 | cmp [edx+usb_endpoint_descr.bEndpointAddress], 0 |
262 | cmp [edx+usb_endpoint_descr.bEndpointAddress], 0 |
247 | jge .lookep |
263 | jge .lookep |
248 | mov al, [edx+usb_endpoint_descr.bmAttributes] |
264 | mov al, [edx+usb_endpoint_descr.bmAttributes] |
249 | and al, 3 |
265 | and al, 3 |
250 | cmp al, INTERRUPT_PIPE |
266 | cmp al, INTERRUPT_PIPE |
251 | jnz .lookep |
267 | jnz .lookep |
252 | ; We have located the descriptor for INTERRUPT IN endpoint, |
268 | ; We have located the descriptor for INTERRUPT IN endpoint, |
253 | ; the pointer is in edx. |
269 | ; the pointer is in edx. |
254 | ; 2. Allocate memory for the hub descriptor. |
270 | ; 3. Allocate memory for the hub descriptor. |
255 | ; Maximum length (assuming 255 downstream ports) is 40 bytes. |
271 | ; Maximum length (assuming 255 downstream ports) is 40 bytes. |
256 | ; Allocate 4 extra bytes to keep wMaxPacketSize. |
272 | ; Allocate 4 extra bytes to keep wMaxPacketSize. |
257 | ; 2a. Save registers. |
273 | ; 3a. Save registers. |
258 | push edx |
274 | push edx |
259 | ; 2b. Call the allocator. |
275 | ; 3b. Call the allocator. |
260 | movi eax, 44 |
276 | movi eax, 44 |
261 | call malloc |
277 | call malloc |
262 | ; 2c. Restore registers. |
278 | ; 3c. Restore registers. |
263 | pop ecx |
279 | pop ecx |
264 | ; 2d. If failed, say something to the debug board and return error. |
280 | ; 3d. If failed, say something to the debug board and return error. |
265 | test eax, eax |
281 | test eax, eax |
266 | jz .nomemory |
282 | jz .nomemory |
267 | ; 2e. Store the pointer in esi. xchg eax,r32 is one byte shorter than mov. |
283 | ; 3e. Store the pointer in esi. xchg eax,r32 is one byte shorter than mov. |
268 | xchg esi, eax |
284 | xchg esi, eax |
269 | ; 3. Open a pipe for the status endpoint with descriptor found in step 1. |
285 | ; 4. Open a pipe for the status endpoint with descriptor found in step 1. |
270 | mov ebx, [.pipe] |
- | |
271 | movzx eax, [ecx+usb_endpoint_descr.bEndpointAddress] |
286 | movzx eax, [ecx+usb_endpoint_descr.bEndpointAddress] |
272 | movzx edx, [ecx+usb_endpoint_descr.bInterval] |
287 | movzx edx, [ecx+usb_endpoint_descr.bInterval] |
273 | movzx ecx, [ecx+usb_endpoint_descr.wMaxPacketSize] |
288 | movzx ecx, [ecx+usb_endpoint_descr.wMaxPacketSize] |
274 | test ecx, (1 shl 11) - 1 |
289 | test ecx, (1 shl 11) - 1 |
275 | jz .free |
290 | jz .free |
276 | push ecx |
291 | push ecx |
277 | stdcall usb_open_pipe, ebx, eax, ecx, INTERRUPT_PIPE, edx |
292 | stdcall usb_open_pipe, ebx, eax, ecx, INTERRUPT_PIPE, edx |
278 | pop ecx |
293 | pop ecx |
279 | ; If failed, free the memory allocated in step 2, |
294 | ; If failed, free the memory allocated in step 3, |
280 | ; say something to the debug board and return error. |
295 | ; say something to the debug board and return error. |
281 | test eax, eax |
296 | test eax, eax |
282 | jz .free |
297 | jz .free |
283 | ; 4. Send control query for the hub descriptor, |
298 | ; 5. Send control query for the hub descriptor, |
284 | ; pass status pipe as a callback parameter, |
299 | ; pass status pipe as a callback parameter, |
285 | ; allow short packets. |
300 | ; allow short packets. |
286 | and ecx, (1 shl 11) - 1 |
301 | and ecx, (1 shl 11) - 1 |
287 | mov [esi+40], ecx |
302 | mov [esi+40], ecx |
288 | mov dword [esi], 0xA0 + \ ; class-specific request |
303 | mov dword [esi], 0xA0 + \ ; class-specific request |
289 | (USB_GET_DESCRIPTOR shl 8) + \ |
304 | (USB_GET_DESCRIPTOR shl 8) + \ |
290 | (0 shl 16) + \ ; descriptor index 0 |
305 | (0 shl 16) + \ ; descriptor index 0 |
291 | (USB_HUB_DESCRIPTOR shl 24) |
306 | (USB_HUB_DESCRIPTOR shl 24) |
292 | mov dword [esi+4], 40 shl 16 |
307 | mov dword [esi+4], 40 shl 16 |
293 | stdcall usb_control_async, ebx, esi, esi, 40, usb_hub_got_config, eax, 1 |
308 | stdcall usb_control_async, ebx, esi, esi, 40, usb_hub_got_config, eax, 1 |
294 | ; 5. If failed, free the memory allocated in step 2, |
309 | ; 6. If failed, free the memory allocated in step 3, |
295 | ; say something to the debug board and return error. |
310 | ; say something to the debug board and return error. |
296 | test eax, eax |
311 | test eax, eax |
297 | jz .free |
312 | jz .free |
298 | ; Otherwise, return 1. usb_hub_got_config will overwrite it later. |
313 | ; Otherwise, return 1. usb_hub_got_config will overwrite it later. |
299 | xor eax, eax |
314 | xor eax, eax |