2 * hub.c - USB driver stack project for Windows NT 4.0
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * this program (in the main directory of the distribution, the file
18 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "usbdriver.h"
24 //----------------------------------------------------------
26 #define crash_machine() \
27 { ( ( PUSB_DEV ) 0 )->flags = 0x12345; }
29 #define hub_if_from_dev( pdEV, pIF ) \
32 for( i = 0; i < pdEV->usb_config->if_count; i ++ )\
34 if( pdEV->usb_config->interf[ i ].pusb_if_desc->bInterfaceClass\
41 if( i < pdEV->usb_config->if_count )\
42 pIF = &pdev->usb_config->interf[ i ];\
48 extern ULONG cpu_clock_freq
;
50 BOOLEAN
hub_check_reset_port_status(PUSB_DEV pdev
, LONG port_idx
);
52 VOID
hub_reexamine_port_status_queue(PUSB_DEV hub_dev
, ULONG port_idx
, BOOLEAN from_dpc
);
54 void hub_int_completion(PURB purb
, PVOID pcontext
);
56 VOID
hub_get_port_status_completion(PURB purb
, PVOID context
);
58 VOID
hub_clear_port_feature_completion(PURB purb
, PVOID context
);
60 VOID
hub_event_examine_status_que(PUSB_DEV pdev
, ULONG event
, ULONG context
, //hub_ext
61 ULONG param
//port_idx
64 VOID
hub_timer_wait_dev_stable(PUSB_DEV pdev
,
65 PVOID context
//port-index
68 VOID
hub_event_dev_stable(PUSB_DEV pdev
,
70 ULONG context
, //hub_ext
71 ULONG param
//port_idx
74 VOID
hub_post_esq_event(PUSB_DEV pdev
, BYTE port_idx
, PROCESS_EVENT pe
);
76 void hub_set_cfg_completion(PURB purb
, PVOID pcontext
);
78 void hub_get_hub_desc_completion(PURB purb
, PVOID pcontext
);
80 NTSTATUS
hub_start_int_request(PUSB_DEV pdev
);
82 BOOLEAN
hub_connect(PDEV_CONNECT_DATA init_param
, DEV_HANDLE dev_handle
);
84 BOOLEAN
hub_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
);
86 BOOLEAN
hub_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
);
88 NTSTATUS
hub_disable_port_request(PUSB_DEV pdev
, UCHAR port_idx
);
90 VOID
hub_start_reset_port_completion(PURB purb
, PVOID context
);
93 init_event_pool(PUSB_EVENT_POOL pool
)
100 if ((pool
->event_array
= usb_alloc_mem(NonPagedPool
, sizeof(USB_EVENT
) * MAX_EVENTS
)) == NULL
)
103 InitializeListHead(&pool
->free_que
);
104 KeInitializeSpinLock(&pool
->pool_lock
);
105 pool
->total_count
= MAX_EVENTS
;
106 pool
->free_count
= 0;
108 for(i
= 0; i
< MAX_EVENTS
; i
++)
110 free_event(pool
, &pool
->event_array
[i
]);
117 free_event(PUSB_EVENT_POOL pool
, PUSB_EVENT pevent
)
119 if (pool
== NULL
|| pevent
== NULL
)
124 RtlZeroMemory(pevent
, sizeof(USB_EVENT
));
125 InsertTailList(&pool
->free_que
, (PLIST_ENTRY
) pevent
);
127 usb_dbg_print(DBGLVL_MAXIMUM
+ 1,
128 ("free_event(): alloced=0x%x, addr=0x%x\n", MAX_EVENTS
- pool
->free_count
, pevent
));
135 alloc_event(PUSB_EVENT_POOL pool
, LONG count
)
138 if (pool
== NULL
|| count
!= 1)
141 if (pool
->free_count
== 0)
144 NewEvent
= (PUSB_EVENT
) RemoveHeadList(&pool
->free_que
);
147 usb_dbg_print(DBGLVL_MAXIMUM
+ 1,
148 ("alloc_event(): alloced=0x%x, addr=0x%x\n", MAX_EVENTS
- pool
->free_count
, NewEvent
));
153 destroy_event_pool(PUSB_EVENT_POOL pool
)
158 InitializeListHead(&pool
->free_que
);
159 pool
->free_count
= pool
->total_count
= 0;
160 usb_free_mem(pool
->event_array
);
161 pool
->event_array
= NULL
;
167 event_list_default_process_event(PUSB_DEV pdev
, ULONG event
, ULONG context
, ULONG param
)
169 UNREFERENCED_PARAMETER(param
);
170 UNREFERENCED_PARAMETER(context
);
171 UNREFERENCED_PARAMETER(event
);
172 UNREFERENCED_PARAMETER(pdev
);
175 //----------------------------------------------------------
176 //timer_svc pool routines
179 init_timer_svc_pool(PTIMER_SVC_POOL pool
)
186 pool
->timer_svc_array
= usb_alloc_mem(NonPagedPool
, sizeof(TIMER_SVC
) * MAX_TIMER_SVCS
);
187 InitializeListHead(&pool
->free_que
);
188 pool
->free_count
= 0;
189 pool
->total_count
= MAX_TIMER_SVCS
;
190 KeInitializeSpinLock(&pool
->pool_lock
);
192 for(i
= 0; i
< MAX_TIMER_SVCS
; i
++)
194 free_timer_svc(pool
, &pool
->timer_svc_array
[i
]);
201 free_timer_svc(PTIMER_SVC_POOL pool
, PTIMER_SVC ptimer
)
203 if (pool
== NULL
|| ptimer
== NULL
)
206 RtlZeroMemory(ptimer
, sizeof(TIMER_SVC
));
207 InsertTailList(&pool
->free_que
, (PLIST_ENTRY
) & ptimer
->timer_svc_link
);
215 alloc_timer_svc(PTIMER_SVC_POOL pool
, LONG count
)
219 if (pool
== NULL
|| count
!= 1)
222 if (pool
->free_count
<= 0)
225 NewTimer
= (PTIMER_SVC
) RemoveHeadList(&pool
->free_que
);
232 destroy_timer_svc_pool(PTIMER_SVC_POOL pool
)
237 usb_free_mem(pool
->timer_svc_array
);
238 pool
->timer_svc_array
= NULL
;
239 InitializeListHead(&pool
->free_que
);
240 pool
->free_count
= 0;
241 pool
->total_count
= 0;
247 event_list_default_process_queue(PLIST_HEAD event_list
,
248 PUSB_EVENT_POOL event_pool
, PUSB_EVENT usb_event
, PUSB_EVENT out_event
)
250 //remove the first event from the event list, and copy it to
253 if (event_list
== NULL
|| event_pool
== NULL
|| usb_event
== NULL
|| out_event
== NULL
)
256 RemoveEntryList(&usb_event
->event_link
);
257 RtlCopyMemory(out_event
, usb_event
, sizeof(USB_EVENT
));
258 free_event(event_pool
, usb_event
);
263 psq_enqueue(PPORT_STATUS_QUEUE psq
, ULONG status
)
268 if (psq_is_full(psq
))
271 psq
->port_status
[psq
->status_count
].wPortChange
= HIWORD(status
);
272 psq
->port_status
[psq
->status_count
].wPortStatus
= LOWORD(status
);
276 usb_dbg_print(DBGLVL_MAXIMUM
, ("psq_enqueue(): last status=0x%x, status count=0x%x, port_flag=0x%x\n",
277 status
, psq
->status_count
, psq
->port_flags
));
283 psq_init(PPORT_STATUS_QUEUE psq
)
285 RtlZeroMemory(psq
, sizeof(PORT_STATUS_QUEUE
));
286 psq
->port_flags
= STATE_IDLE
| USB_PORT_FLAG_DISABLE
;
289 //return 0xffffffff if no element
291 psq_outqueue(PPORT_STATUS_QUEUE psq
)
298 if (psq_is_empty(psq
))
301 status
= ((PULONG
) & psq
->port_status
)[0];
302 psq
->port_status
[0] = psq
->port_status
[1];
303 psq
->port_status
[1] = psq
->port_status
[2];
304 psq
->port_status
[2] = psq
->port_status
[3];
311 psq_push(PPORT_STATUS_QUEUE psq
, ULONG status
)
316 status
= ((PULONG
) & psq
->port_status
)[0];
317 psq
->port_status
[3] = psq
->port_status
[2];
318 psq
->port_status
[2] = psq
->port_status
[1];
319 psq
->port_status
[1] = psq
->port_status
[0];
321 ((PULONG
) & psq
->port_status
)[0] = status
;
324 psq
->status_count
= ((4 > psq
->status_count
) ? psq
->status_count
: 4);
330 hub_driver_init(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
332 UNREFERENCED_PARAMETER(dev_mgr
);
334 //init driver structure, no PNP table functions
335 pdriver
->driver_desc
.flags
= USB_DRIVER_FLAG_DEV_CAPABLE
;
336 pdriver
->driver_desc
.vendor_id
= 0xffff; // USB Vendor ID
337 pdriver
->driver_desc
.product_id
= 0xffff; // USB Product ID.
338 pdriver
->driver_desc
.release_num
= 0xffff; // Release Number of Device
340 pdriver
->driver_desc
.config_val
= 0; // Configuration Value
341 pdriver
->driver_desc
.if_num
= 0; // Interface Number
342 pdriver
->driver_desc
.if_class
= USB_CLASS_HUB
; // Interface Class
343 pdriver
->driver_desc
.if_sub_class
= 0; // Interface SubClass
344 pdriver
->driver_desc
.if_protocol
= 0; // Interface Protocol
346 pdriver
->driver_desc
.driver_name
= "USB hub"; // Driver name for Name Registry
347 pdriver
->driver_desc
.dev_class
= USB_CLASS_HUB
;
348 pdriver
->driver_desc
.dev_sub_class
= 0; // Device Subclass
349 pdriver
->driver_desc
.dev_protocol
= 0; // Protocol Info.
351 //pdriver->driver_init = hub_driver_init; // initialized in dev_mgr_init_driver
352 //pdriver->driver_destroy = hub_driver_destroy;
354 pdriver
->driver_ext
= 0;
355 pdriver
->driver_ext_size
= 0;
357 pdriver
->disp_tbl
.version
= 1;
358 pdriver
->disp_tbl
.dev_connect
= hub_connect
;
359 pdriver
->disp_tbl
.dev_disconnect
= hub_disconnect
;
360 pdriver
->disp_tbl
.dev_stop
= hub_stop
;
361 pdriver
->disp_tbl
.dev_reserved
= NULL
;
367 hub_driver_destroy(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
369 UNREFERENCED_PARAMETER(dev_mgr
);
371 pdriver
->driver_ext
= NULL
;
376 hub_reset_pipe_completion(PURB purb
, //only for reference, can not be released
382 USE_BASIC_NON_PENDING_IRQL
;
384 UNREFERENCED_PARAMETER(context
);
394 lock_dev(pdev
, TRUE
);
395 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
397 unlock_dev(pdev
, TRUE
);
401 if (usb_error(purb
->status
))
404 unlock_dev(pdev
, TRUE
);
405 //usb_free_mem( purb );
408 unlock_dev(pdev
, TRUE
);
411 hub_start_int_request(pdev
);
416 hub_start_int_request(PUSB_DEV pdev
)
420 PHUB2_EXTENSION hub_ext
;
423 USE_BASIC_NON_PENDING_IRQL
;
426 return STATUS_INVALID_PARAMETER
;
428 lock_dev(pdev
, FALSE
);
429 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
431 unlock_dev(pdev
, FALSE
);
432 return STATUS_DEVICE_DOES_NOT_EXIST
;
434 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
435 RtlZeroMemory(purb
, sizeof(URB
));
439 unlock_dev(pdev
, FALSE
);
440 return STATUS_NO_MEMORY
;
444 purb
->status
= STATUS_SUCCESS
;
445 hub_ext
= hub_ext_from_dev(pdev
);
446 purb
->data_buffer
= hub_ext
->int_data_buf
;
447 purb
->data_length
= (hub_ext
->port_count
+ 7) / 8;
449 hub_if_from_dev(pdev
, pif
);
450 usb_dbg_print(DBGLVL_ULTRA
, ("hub_start_int_request(): pdev=0x%x, pif=0x%x\n", pdev
, pif
));
451 purb
->pendp
= &pif
->endp
[0];
454 purb
->completion
= hub_int_completion
;
455 purb
->context
= hub_ext
;
460 unlock_dev(pdev
, FALSE
);
462 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
463 if (status
!= STATUS_PENDING
)
473 hub_int_completion(PURB purb
, PVOID pcontext
)
477 PHUB2_EXTENSION hub_ext
;
479 PUSB_CTRL_SETUP_PACKET psetup
;
484 USE_BASIC_NON_PENDING_IRQL
;
489 if (pcontext
== NULL
)
495 usb_dbg_print(DBGLVL_ULTRA
, ("hub_int_completion(): entering...\n"));
500 lock_dev(pdev
, TRUE
);
501 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
503 unlock_dev(pdev
, TRUE
);
510 if (purb
->status
== STATUS_SUCCESS
)
513 for(i
= 1; i
<= hub_ext
->port_count
; i
++)
515 if (hub_ext
->int_data_buf
[i
>> 3] & (1 << i
))
520 if (i
> hub_ext
->port_count
)
522 //no status change, re-initialize the int request
523 unlock_dev(pdev
, TRUE
);
525 hub_start_int_request(pdev
);
531 //re-use the urb to get port status
532 purb
->pendp
= &pdev
->default_endp
;
533 purb
->data_buffer
= (PUCHAR
) & hub_ext
->port_status
;
535 purb
->data_length
= sizeof(USB_PORT_STATUS
);
538 purb
->context
= hub_ext
;
540 purb
->completion
= hub_get_port_status_completion
;
541 purb
->reference
= port_idx
;
543 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
545 psetup
->bmRequestType
= 0xa3; //host-device class other recepient
546 psetup
->bRequest
= USB_REQ_GET_STATUS
;
548 psetup
->wIndex
= (USHORT
) port_idx
;
552 unlock_dev(pdev
, TRUE
);
554 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
555 if (usb_error(status
))
560 else if (status
== STATUS_SUCCESS
)
562 // this is for root hub
563 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
569 unlock_dev(pdev
, TRUE
);
570 if (usb_halted(purb
->status
))
573 usb_reset_pipe(pdev
, purb
->pendp
, hub_reset_pipe_completion
, NULL
);
583 hub_get_port_status_completion(PURB purb
, PVOID context
)
588 PHUB2_EXTENSION hub_ext
;
589 PUSB_CTRL_SETUP_PACKET psetup
;
593 USE_BASIC_NON_PENDING_IRQL
;
595 if (purb
== NULL
|| context
== NULL
)
598 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_get_port_feature_completion(): entering...\n"));
603 lock_dev(pdev
, TRUE
);
604 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
606 unlock_dev(pdev
, TRUE
);
612 if (usb_error(purb
->status
))
614 unlock_dev(pdev
, TRUE
);
617 //simply retry the request refer to item 55 in document
618 status
= hcd
->hcd_submit_urb(hcd
, pdev
, pendp
, purb
);
619 if (status
!= STATUS_PENDING
)
621 if (status
== STATUS_SUCCESS
)
623 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
629 // must be fatal error
630 // FIXME: better to pass it to the completion for further
639 hub_ext
= hub_ext_from_dev(pdev
);
640 port_idx
= (BYTE
) purb
->reference
;
642 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_get_port_stataus_completion(): port_idx=0x%x, hcd =0x%x, \
643 pdev=0x%x, purb=0x%x, hub_ext=0x%x, portsc=0x%x \n", port_idx
, pdev
->hcd
, pdev
,
644 purb
, hub_ext
, *((PULONG
) purb
->data_buffer
)));
646 psq_enqueue(&hub_ext
->port_status_queue
[port_idx
], *((PULONG
) purb
->data_buffer
));
648 //reuse the urb to clear the feature
649 RtlZeroMemory(purb
, sizeof(URB
));
651 purb
->data_buffer
= NULL
;
652 purb
->data_length
= 0;
653 purb
->pendp
= &pdev
->default_endp
;
656 purb
->context
= (PVOID
) & hub_ext
->port_status
;
658 purb
->completion
= hub_clear_port_feature_completion
;
659 purb
->reference
= port_idx
;
661 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
663 psetup
->bmRequestType
= 0x23; //host-device class port recepient
664 psetup
->bRequest
= USB_REQ_CLEAR_FEATURE
;
665 psetup
->wIndex
= port_idx
;
669 if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_CONNECTION
)
671 psetup
->wValue
= USB_PORT_FEAT_C_CONNECTION
;
673 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_ENABLE
)
675 psetup
->wValue
= USB_PORT_FEAT_C_ENABLE
;
677 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_SUSPEND
)
679 psetup
->wValue
= USB_PORT_FEAT_C_SUSPEND
;
681 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_OVERCURRENT
)
683 psetup
->wValue
= USB_PORT_FEAT_C_OVER_CURRENT
;
685 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_RESET
)
687 psetup
->wValue
= USB_PORT_FEAT_C_RESET
;
689 unlock_dev(pdev
, TRUE
);
691 status
= hcd
->hcd_submit_urb(hcd
, pdev
, pendp
, purb
);
693 // if( status != STATUS_SUCCESS )
694 if (status
!= STATUS_PENDING
)
696 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
698 /*else if( usb_error( status ) )
700 usb_free_mem( purb );
708 hub_clear_port_feature_completion(PURB purb
, PVOID context
)
712 BOOLEAN event_post
, brh
;
717 PHUB2_EXTENSION hub_ext
= NULL
;
718 PUSB_DEV_MANAGER dev_mgr
;
720 PUSB_CTRL_SETUP_PACKET psetup
;
722 USE_BASIC_NON_PENDING_IRQL
;
733 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_clear_port_feature_completion(): entering...\n"));
736 port_idx
= (BYTE
) purb
->reference
;
738 lock_dev(pdev
, TRUE
);
739 dev_mgr
= dev_mgr_from_dev(pdev
);
741 brh
= (BOOLEAN
) (dev_class(pdev
) == USB_DEV_CLASS_ROOT_HUB
);
743 if (usb_error(purb
->status
))
745 unlock_dev(pdev
, TRUE
);
750 status
= hcd
->hcd_submit_urb(hcd
, purb
->pdev
, purb
->pendp
, purb
);
751 if (status
!= STATUS_PENDING
)
753 if (status
== STATUS_SUCCESS
)
755 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
760 // FIXME: should we pass the error to the completion directly
761 // instead of forstall it here?
763 // do not think the device is workable, no requests to it any more.
764 // including the int polling
766 // usb_free_mem( purb );
768 goto LBL_SCAN_PORT_STAT
;
774 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
776 unlock_dev(pdev
, TRUE
);
781 pc
= ((PUSB_PORT_STATUS
) context
)->wPortChange
;
785 // the bits are tested in ascending order
786 if (pc
& USB_PORT_STAT_C_CONNECTION
)
788 pc
&= ~USB_PORT_STAT_C_CONNECTION
;
790 else if (pc
& USB_PORT_STAT_C_ENABLE
)
792 pc
&= ~USB_PORT_STAT_C_ENABLE
;
794 else if (pc
& USB_PORT_STAT_C_SUSPEND
)
796 pc
&= ~USB_PORT_STAT_C_SUSPEND
;
798 else if (pc
& USB_PORT_STAT_C_OVERCURRENT
)
800 pc
&= ~USB_PORT_STAT_C_OVERCURRENT
;
802 else if (pc
& USB_PORT_STAT_C_RESET
)
804 pc
&= ~USB_PORT_STAT_C_RESET
;
807 ((PUSB_PORT_STATUS
) context
)->wPortChange
= (USHORT
) pc
;
809 hub_ext
= hub_ext_from_dev(pdev
);
813 //some other status change on the port still active
814 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
816 if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_CONNECTION
)
818 psetup
->wValue
= USB_PORT_FEAT_C_CONNECTION
;
820 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_ENABLE
)
822 psetup
->wValue
= USB_PORT_FEAT_C_ENABLE
;
824 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_SUSPEND
)
826 psetup
->wValue
= USB_PORT_FEAT_C_SUSPEND
;
828 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_OVERCURRENT
)
830 psetup
->wValue
= USB_PORT_FEAT_C_OVER_CURRENT
;
832 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_RESET
)
834 psetup
->wValue
= USB_PORT_FEAT_C_RESET
;
836 unlock_dev(pdev
, TRUE
);
838 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
839 if (status
!= STATUS_PENDING
)
841 if (status
== STATUS_SUCCESS
)
843 usb_dbg_print(DBGLVL_MAXIMUM
,
844 ("hub_clear_port_status_completion(): port_idx=0x%x, hcd=0x%x, \
845 pdev=0x%x, purb=0x%x, hub_ext=0x%x, wPortChange=0x%x \n",
846 port_idx
, pdev
->hcd
, pdev
, purb
, hub_ext
, pc
));
848 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
852 usb_dbg_print(DBGLVL_MAXIMUM
, (" hub_clear_port_feature_completion(): \
853 error=0x%x\n", status
));
855 // usb_free_mem( purb );
856 goto LBL_SCAN_PORT_STAT
;
862 for(i
= 1; i
<= hub_ext
->port_count
; i
++)
864 if (hub_ext
->int_data_buf
[i
>> 3] & (1 << i
))
870 //clear the port-change map, we have get port i's status.
871 hub_ext
->int_data_buf
[i
>> 3] &= ~(1 << i
);
873 //rescan to find some other port that has status change
874 for(i
= 1; i
<= hub_ext
->port_count
; i
++)
876 if (hub_ext
->int_data_buf
[i
>> 3] & (1 << i
))
882 if (i
<= hub_ext
->port_count
)
884 //still has port-change pending, get the port status change
885 port_idx
= (UCHAR
) i
;
888 purb
->data_buffer
= (PUCHAR
) & hub_ext
->port_status
;
889 purb
->data_length
= sizeof(USB_PORT_STATUS
);
890 purb
->pendp
= &pdev
->default_endp
;
893 purb
->context
= hub_ext
;
895 purb
->completion
= hub_get_port_status_completion
;
896 purb
->reference
= port_idx
;
898 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
900 psetup
->bmRequestType
= 0xa3; //host-device class other recepient
901 psetup
->bRequest
= USB_REQ_GET_STATUS
;
903 psetup
->wIndex
= port_idx
;
908 unlock_dev(pdev
, TRUE
);
910 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
911 if (status
!= STATUS_PENDING
)
913 if (status
== STATUS_SUCCESS
)
915 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
918 { //must be fatal error
919 // usb_free_mem( purb );
920 goto LBL_SCAN_PORT_STAT
;
926 unlock_dev(pdev
, TRUE
);
930 //all status changes are cleared
936 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
937 lock_dev(pdev
, TRUE
);
939 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
942 // if reset is in process, the dev_mgr_disconnect_dev will continue
943 // the following resets
945 unlock_dev(pdev
, TRUE
);
946 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
950 //at last we wake up thread if some port have status change to process
952 for(i
= 1, event_post
= FALSE
; i
<= hub_ext
->port_count
; i
++)
954 if (psq_is_empty(&hub_ext
->port_status_queue
[i
]) == FALSE
)
956 if (port_state(hub_ext
->port_status_queue
[i
].port_flags
) == STATE_IDLE
||
957 port_state(hub_ext
->port_status_queue
[i
].port_flags
) == STATE_WAIT_ADDRESSED
)
959 // have status in the queue pending
960 // STATE_WAIT_ADDRESSED is added to avoid some bad mannered
961 // hub to disturb the reset process
962 hub_post_esq_event(pdev
, (BYTE
) i
, hub_event_examine_status_que
);
964 else if (port_state(hub_ext
->port_status_queue
[i
].port_flags
) == STATE_WAIT_RESET_COMPLETE
)
966 //there is only one reset at one time
972 unlock_dev(pdev
, TRUE
);
973 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
977 hub_check_reset_port_status(pdev
, port_idx
);
979 //reinitialize the int request, here to reduce some uncertainty of concurrency
980 hub_start_int_request(pdev
);
986 hub_event_examine_status_que(PUSB_DEV pdev
,
988 ULONG context
, //hub_ext
989 ULONG param
//port_idx
992 PHUB2_EXTENSION hub_ext
;
996 PUSB_DEV_MANAGER dev_mgr
;
998 USE_NON_PENDING_IRQL
;
1000 UNREFERENCED_PARAMETER(event
);
1002 if (pdev
== NULL
|| context
== 0 || param
== 0)
1007 lock_dev(pdev
, FALSE
);
1008 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1010 unlock_dev(pdev
, FALSE
);
1014 dev_mgr
= dev_mgr_from_dev(pdev
);
1015 hub_ext
= hub_ext_from_dev(pdev
);
1017 if (psq_is_empty(&hub_ext
->port_status_queue
[param
]))
1019 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_IDLE
);
1020 unlock_dev(pdev
, FALSE
);
1024 *((ULONG
*) & ps
) = psq_outqueue(&hub_ext
->port_status_queue
[param
]);
1027 pchild_dev
= hub_ext
->child_dev
[param
];
1028 hub_ext
->child_dev
[param
] = 0;
1030 usb_dbg_print(DBGLVL_MAXIMUM
,
1031 ("hub_event_examine_status_queue(): dev_addr=0x%x, port=0x%x, wPortChange=0x%x, wPortStatus=0x%x\n",
1032 pdev
->dev_addr
, param
, ps
.wPortChange
, ps
.wPortStatus
));
1034 unlock_dev(pdev
, FALSE
);
1036 if (pchild_dev
!= NULL
)
1037 dev_mgr_disconnect_dev(pchild_dev
);
1039 if (((ps
.wPortChange
& USB_PORT_STAT_C_ENABLE
) &&
1040 ((pdev
->flags
& USB_DEV_CLASS_MASK
) != USB_DEV_CLASS_ROOT_HUB
))
1041 || (ps
.wPortChange
& USB_PORT_STAT_C_OVERCURRENT
)
1042 || (ps
.wPortChange
& USB_PORT_STAT_C_RESET
)
1043 || ((ps
.wPortChange
& USB_PORT_STAT_C_CONNECTION
) &&
1044 !(ps
.wPortStatus
& USB_PORT_STAT_CONNECTION
)))
1046 usb_dbg_print(DBGLVL_MAXIMUM
,
1047 ("hub_event_examine_status_queue(): error occured, portc=0x%x, ports=0x%x\n",
1048 ps
.wPortChange
, ps
.wPortStatus
));
1050 lock_dev(pdev
, FALSE
);
1051 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1053 unlock_dev(pdev
, FALSE
);
1056 if (psq_is_empty(&hub_ext
->port_status_queue
[param
]))
1058 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_IDLE
);
1062 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_EXAMINE_STATUS_QUE
);
1064 unlock_dev(pdev
, FALSE
);
1068 else if ((ps
.wPortChange
& USB_PORT_STAT_C_CONNECTION
)
1069 && (ps
.wPortStatus
& USB_PORT_STAT_CONNECTION
)
1070 && psq_is_empty(&hub_ext
->port_status_queue
[param
]))
1072 KeAcquireSpinLock(&dev_mgr
->timer_svc_list_lock
, &old_irql
);
1073 lock_dev(pdev
, TRUE
);
1074 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1076 unlock_dev(pdev
, TRUE
);
1077 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
1078 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_event_examine_status_queue(): dev lost\n"));
1081 ptimer
= alloc_timer_svc(&dev_mgr
->timer_svc_pool
, 1);
1084 unlock_dev(pdev
, TRUE
);
1085 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
1086 usb_dbg_print(DBGLVL_MAXIMUM
,
1087 ("hub_event_examine_status_queue(): timer can not allocated\n"));
1092 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_event_examine_status_queue(): new connection comes\n"));
1094 ptimer
->counter
= 0;
1095 ptimer
->threshold
= 21; //100 ms
1097 if (ps
.wPortStatus
& USB_PORT_STAT_LOW_SPEED
)
1098 ptimer
->threshold
= 51; //500 ms
1100 ptimer
->context
= param
;
1101 ptimer
->pdev
= pdev
;
1102 ptimer
->func
= hub_timer_wait_dev_stable
;
1103 InsertTailList(&dev_mgr
->timer_svc_list
, &ptimer
->timer_svc_link
);
1105 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_WAIT_STABLE
);
1106 unlock_dev(pdev
, TRUE
);
1107 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
1113 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_event_examine_status_queue(): unknown error\n"));
1121 hub_timer_wait_dev_stable(PUSB_DEV pdev
,
1122 PVOID context
//port-index
1126 PHUB2_EXTENSION hub_ext
;
1128 PUSB_DEV_MANAGER dev_mgr
;
1130 USE_BASIC_NON_PENDING_IRQL
;
1132 if (pdev
== NULL
|| context
== 0)
1135 dev_mgr
= dev_mgr_from_dev(pdev
);
1136 param
= (ULONG
) context
;
1137 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
1138 lock_dev(pdev
, TRUE
);
1142 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1147 hub_ext
= hub_ext_from_dev(pdev
);
1149 if (!psq_is_empty(&hub_ext
->port_status_queue
[param
]))
1151 //error occured, normally we should not receive event here
1152 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_EXAMINE_STATUS_QUE
);
1154 hub_post_esq_event(pdev
, (BYTE
) param
, hub_event_examine_status_que
);
1158 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_WAIT_RESET
);
1160 hub_post_esq_event(pdev
, (BYTE
) param
, hub_event_dev_stable
);
1165 unlock_dev(pdev
, TRUE
);
1166 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1171 hub_event_dev_stable(PUSB_DEV pdev
,
1173 ULONG context
, //hub_ext
1174 ULONG param
//port_idx
1178 PHUB2_EXTENSION hub_ext
;
1179 PUSB_EVENT pevent
, pevent1
;
1180 PLIST_ENTRY pthis
, pnext
;
1183 PUSB_DEV_MANAGER dev_mgr
;
1186 PUSB_CTRL_SETUP_PACKET psetup
;
1188 USE_NON_PENDING_IRQL
;
1190 UNREFERENCED_PARAMETER(event
);
1192 if (pdev
== NULL
|| context
== 0 || param
== 0)
1195 dev_mgr
= dev_mgr_from_dev(pdev
);
1196 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
1197 lock_dev(pdev
, TRUE
);
1199 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1202 hub_ext
= hub_ext_from_dev(pdev
);
1205 pevent
= alloc_event(&dev_mgr
->event_pool
, 1);
1209 pevent
->event
= USB_EVENT_WAIT_RESET_PORT
;
1210 pevent
->pdev
= pdev
;
1211 pevent
->context
= (ULONG
) hub_ext
;
1212 pevent
->param
= param
;
1213 pevent
->flags
= USB_EVENT_FLAG_QUE_RESET
;
1214 pevent
->process_event
= NULL
; //hub_event_reset_port_complete;
1215 pevent
->process_queue
= NULL
; //hub_event_reset_process_queue;
1216 pevent
->pnext
= NULL
;
1218 ListFirst(&dev_mgr
->event_list
, pthis
);
1223 //insert the event in to the wait-queue
1224 pevent1
= (PUSB_EVENT
) pthis
;
1225 if (pevent1
->event
== USB_EVENT_WAIT_RESET_PORT
)
1227 while (pevent1
->pnext
)
1228 pevent1
= pevent1
->pnext
;
1230 pevent1
->pnext
= pevent
;
1234 ListNext(&dev_mgr
->event_list
, pthis
, pnext
);
1240 //Let's start a reset port request
1241 InsertHeadList(&dev_mgr
->event_list
, &pevent
->event_link
);
1242 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1243 RtlZeroMemory(purb
, sizeof(URB
));
1245 purb
->data_buffer
= NULL
;
1246 purb
->data_length
= 0;
1247 purb
->pendp
= &pdev
->default_endp
;
1249 purb
->context
= hub_ext
;
1251 purb
->completion
= hub_start_reset_port_completion
; //hub_int_completion;
1252 purb
->reference
= param
;
1254 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1256 psetup
->bmRequestType
= 0x23; //host-device other recepient
1257 psetup
->bRequest
= USB_REQ_SET_FEATURE
;
1258 psetup
->wValue
= USB_PORT_FEAT_RESET
;
1259 psetup
->wIndex
= (USHORT
) param
;
1260 psetup
->wLength
= 0;
1263 //enter another state
1264 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_WAIT_RESET_COMPLETE
);
1266 unlock_dev(pdev
, TRUE
);
1267 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1269 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
1270 if (status
!= STATUS_PENDING
)
1272 //must be fatal error
1274 hub_reexamine_port_status_queue(pdev
, param
, FALSE
);
1275 if (hub_remove_reset_event(pdev
, param
, FALSE
))
1276 hub_start_next_reset_port(dev_mgr
, FALSE
);
1282 unlock_dev(pdev
, TRUE
);
1283 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1288 hub_start_reset_port_completion(PURB purb
, PVOID context
)
1291 PUSB_ENDPOINT pendp
;
1292 PUSB_DEV_MANAGER dev_mgr
= NULL
;
1293 NTSTATUS status
= STATUS_SUCCESS
;
1297 USE_BASIC_NON_PENDING_IRQL
;;
1301 if (context
== NULL
)
1303 //fatal error no retry.
1309 pendp
= purb
->pendp
;
1310 port_idx
= purb
->reference
;
1312 lock_dev(pdev
, TRUE
);
1314 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1316 unlock_dev(pdev
, TRUE
);
1318 goto LBL_FREE_EVENT
;
1322 dev_mgr
= dev_mgr_from_dev(pdev
);
1323 unlock_dev(pdev
, TRUE
);
1325 status
= purb
->status
;
1328 if (!usb_error(status
))
1334 //since we have no patient to retry the dev, we should remove the event of
1335 //wait_reset_port on the port from the event list. and if possible, start
1336 //another reset process. note other port on the dev still have chance to be
1337 //reset if necessary.
1338 hub_reexamine_port_status_queue(pdev
, port_idx
, TRUE
);
1339 if (hub_remove_reset_event(pdev
, port_idx
, TRUE
))
1340 hub_start_next_reset_port(dev_mgr
, TRUE
);
1346 hub_set_address_completion(PURB purb
, PVOID context
)
1348 PUSB_DEV pdev
, hub_dev
;
1349 PUSB_ENDPOINT pendp
;
1350 PUSB_DEV_MANAGER dev_mgr
;
1354 USE_BASIC_NON_PENDING_IRQL
;
1356 hcd_dbg_print(DBGLVL_MAXIMUM
, ("hub_set_address_completion: purb=%p context=%p\n", purb
, context
));
1361 if (context
== NULL
)
1363 //fatal error no retry.
1369 pendp
= purb
->pendp
;
1370 port_idx
= purb
->reference
;
1372 lock_dev(pdev
, TRUE
);
1375 dev_mgr
= dev_mgr_from_dev(pdev
);
1376 hub_dev
= pdev
->parent_dev
;
1377 port_idx
= pdev
->port_idx
;
1379 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1381 unlock_dev(pdev
, TRUE
);
1383 //some error occured, let's start the next reset event
1384 goto LBL_RESET_NEXT
;
1387 pdev
->flags
&= ~USB_DEV_STATE_MASK
;
1388 pdev
->flags
|= USB_DEV_STATE_ADDRESSED
;
1390 unlock_dev(pdev
, TRUE
);
1391 status
= purb
->status
;
1393 if (usb_error(status
))
1397 hcd_dbg_print(DBGLVL_MAXIMUM
, ("hub_set_address_completion: can not set address\n"));
1398 status
= hcd
->hcd_submit_urb(hcd
, pdev
, pendp
, purb
);
1399 //some error occured, disable the port
1400 if (status
!= STATUS_PENDING
)
1403 status
= hub_disable_port_request(hub_dev
, (UCHAR
) port_idx
);
1409 //let address settle
1410 usb_wait_ms_dpc(10);
1412 //let's config the dev
1413 dev_mgr_start_config_dev(pdev
);
1416 //second, remove the event in the queue
1417 hub_reexamine_port_status_queue(hub_dev
, port_idx
, TRUE
);
1418 if (hub_remove_reset_event(hub_dev
, port_idx
, TRUE
))
1419 hub_start_next_reset_port(dev_mgr
, TRUE
);
1424 hub_disable_port_completion(PURB purb
, PVOID pcontext
)
1427 PUSB_DEV_MANAGER dev_mgr
;
1429 PUSB_ENDPOINT pendp
;
1430 PUSB_CTRL_SETUP_PACKET psetup
;
1432 UNREFERENCED_PARAMETER(pcontext
);
1438 pendp
= purb
->pendp
;
1439 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1440 port_idx
= (UCHAR
) psetup
->wIndex
;
1442 dev_mgr
= dev_mgr_from_dev(pdev
);
1446 hub_reexamine_port_status_queue(pdev
, port_idx
, TRUE
);
1447 if (hub_remove_reset_event(pdev
, port_idx
, TRUE
))
1448 hub_start_next_reset_port(dev_mgr
, TRUE
);
1453 //caller should guarantee the validity of the dev
1455 hub_disable_port_request(PUSB_DEV pdev
, UCHAR port_idx
)
1458 PUSB_ENDPOINT pendp
;
1459 PHUB2_EXTENSION hub_ext
;
1460 PUSB_CTRL_SETUP_PACKET psetup
;
1463 USE_BASIC_NON_PENDING_IRQL
;;
1465 if (pdev
== NULL
|| port_idx
== 0)
1466 return STATUS_INVALID_PARAMETER
;
1468 lock_dev(pdev
, FALSE
);
1469 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1471 unlock_dev(pdev
, FALSE
);
1472 return STATUS_DEVICE_DOES_NOT_EXIST
;
1475 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1478 unlock_dev(pdev
, FALSE
);
1479 return STATUS_NO_MEMORY
;
1482 RtlZeroMemory(purb
, sizeof(URB
));
1485 purb
->status
= STATUS_SUCCESS
;
1487 hub_ext
= hub_ext_from_dev(pdev
);
1489 purb
->data_buffer
= NULL
;
1490 purb
->data_length
= 0;
1492 pendp
= purb
->pendp
= &pdev
->default_endp
;
1495 purb
->completion
= hub_disable_port_completion
;
1496 purb
->context
= hub_ext
;
1499 purb
->reference
= 0;
1501 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1503 psetup
->bmRequestType
= 0x23; //host-device other recepient
1504 psetup
->bRequest
= USB_REQ_CLEAR_FEATURE
; //clear_feature
1505 psetup
->wValue
= USB_PORT_FEAT_ENABLE
;
1506 psetup
->wIndex
= (USHORT
) port_idx
;
1507 psetup
->wLength
= 0;
1510 //enter another state
1512 unlock_dev(pdev
, FALSE
);
1514 status
= hcd
->hcd_submit_urb(hcd
, pdev
, pendp
, purb
);
1515 if (status
== STATUS_PENDING
)
1524 hub_remove_reset_event(PUSB_DEV pdev
, ULONG port_idx
, BOOLEAN from_dpc
)
1526 PUSB_DEV_MANAGER dev_mgr
;
1527 PLIST_ENTRY pthis
, pnext
;
1528 PUSB_EVENT pevent
, pnext_event
;
1539 dev_mgr
= dev_mgr_from_dev(pdev
);
1543 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
1545 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
1547 ListFirst(&dev_mgr
->event_list
, pthis
);
1550 pevent
= (PUSB_EVENT
) pthis
;
1551 if (pevent
->event
== USB_EVENT_WAIT_RESET_PORT
&&
1552 (pevent
->flags
& USB_EVENT_FLAG_QUE_TYPE
) == USB_EVENT_FLAG_QUE_RESET
)
1554 if (pevent
->pdev
== pdev
&& pevent
->param
== port_idx
)
1557 RemoveEntryList(&pevent
->event_link
);
1558 pnext_event
= pevent
->pnext
;
1559 free_event(&dev_mgr
->event_pool
, pevent
);
1562 InsertHeadList(&dev_mgr
->event_list
, &pnext_event
->event_link
);
1568 ListNext(&dev_mgr
->event_list
, pthis
, pnext
);
1573 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1575 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1580 hub_start_next_reset_port(PUSB_DEV_MANAGER dev_mgr
, BOOLEAN from_dpc
)
1582 PLIST_ENTRY pthis
, pnext
;
1583 PUSB_EVENT pevent
, pnext_event
;
1584 PUSB_DEV pdev
= NULL
;
1585 PHUB2_EXTENSION hub_ext
;
1589 PUSB_CTRL_SETUP_PACKET psetup
;
1592 USE_NON_PENDING_IRQL
;;
1594 if (dev_mgr
== NULL
)
1601 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
1603 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
1605 ListFirst(&dev_mgr
->event_list
, pthis
);
1607 while ((pevent
= (PUSB_EVENT
) pthis
))
1609 while (pevent
->event
== USB_EVENT_WAIT_RESET_PORT
&&
1610 (pevent
->flags
& USB_EVENT_FLAG_QUE_TYPE
) == USB_EVENT_FLAG_QUE_RESET
)
1615 pdev
= pevent
->pdev
;
1616 lock_dev(pdev
, TRUE
);
1618 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1620 unlock_dev(pdev
, TRUE
);
1621 pnext_event
= pevent
->pnext
;
1622 free_event(&dev_mgr
->event_pool
, pevent
);
1623 pevent
= pnext_event
;
1632 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1633 RtlZeroMemory(purb
, sizeof(URB
));
1635 purb
->data_buffer
= NULL
;
1636 purb
->data_length
= 0;
1637 purb
->pendp
= &pdev
->default_endp
;
1639 hub_ext
= hub_ext_from_dev(pdev
);
1640 purb
->context
= hub_ext
;
1642 purb
->completion
= hub_start_reset_port_completion
;
1643 purb
->reference
= pevent
->param
;
1645 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1647 psetup
->bmRequestType
= 0x23; //host-device other recepient
1648 psetup
->bRequest
= 3; //set_feature
1649 psetup
->wValue
= USB_PORT_FEAT_RESET
;
1650 psetup
->wIndex
= (USHORT
) pevent
->param
;
1651 psetup
->wLength
= 0;
1655 set_port_state(hub_ext
->port_status_queue
[pevent
->param
].port_flags
, STATE_WAIT_RESET_COMPLETE
);
1656 unlock_dev(pdev
, TRUE
);
1664 ListNext(&dev_mgr
->event_list
, pthis
, pnext
);
1672 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1674 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1676 if (processed
&& bret
)
1678 if (hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
) != STATUS_PENDING
)
1683 //do not know what to do
1694 //must have event-list-lock and dev-lock acquired
1697 hub_post_esq_event(PUSB_DEV pdev
, BYTE port_idx
, PROCESS_EVENT pe
)
1699 PUSB_DEV_MANAGER dev_mgr
;
1702 if (pdev
== NULL
|| port_idx
== 0 || pe
== NULL
)
1705 dev_mgr
= dev_mgr_from_dev(pdev
);
1707 pevent
= alloc_event(&dev_mgr
->event_pool
, 1);
1708 pevent
->event
= USB_EVENT_DEFAULT
;
1709 pevent
->process_queue
= event_list_default_process_queue
;
1710 pevent
->process_event
= pe
;
1711 pevent
->context
= (ULONG
) hub_ext_from_dev(pdev
);
1712 pevent
->param
= port_idx
;
1713 pevent
->flags
= USB_EVENT_FLAG_ACTIVE
;
1714 pevent
->pdev
= pdev
;
1715 pevent
->pnext
= NULL
;
1717 InsertTailList(&dev_mgr
->event_list
, &pevent
->event_link
);
1718 KeSetEvent(&dev_mgr
->wake_up_event
, 0, FALSE
);
1719 // usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_post_esq_event(): current element in event list is 0x%x\n",
1720 // dbg_count_list( &dev_mgr->event_list ) ) );
1724 // called only in hub_clear_port_feature_completion
1726 hub_check_reset_port_status(PUSB_DEV pdev
, LONG port_idx
)
1728 PUSB_DEV_MANAGER dev_mgr
;
1729 PHUB2_EXTENSION hub_ext
;
1731 USB_PORT_STATUS port_status
;
1736 PUSB_CTRL_SETUP_PACKET psetup
;
1739 USE_BASIC_NON_PENDING_IRQL
;;
1741 //let's check whether the status change is a reset complete
1742 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_check_reset_port_status(): entering...\n"));
1743 dev_mgr
= dev_mgr_from_dev(pdev
);
1744 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->dev_list_lock
);
1745 lock_dev(pdev
, TRUE
);
1747 dev_mgr
= dev_mgr_from_dev(pdev
);
1750 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1752 unlock_dev(pdev
, TRUE
);
1753 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->dev_list_lock
);
1757 hub_ext
= hub_ext_from_dev(pdev
);
1758 port_status
= psq_peek(&hub_ext
->port_status_queue
[port_idx
], 0);
1761 if (port_status
.wPortChange
& USB_PORT_STAT_C_RESET
)
1768 && (port_state(hub_ext
->port_status_queue
[port_idx
].port_flags
) == STATE_WAIT_RESET_COMPLETE
)
1769 && (psq_count(&hub_ext
->port_status_queue
[port_idx
]) == 1))
1771 // a port-reset complete, empty the queue, keep the state
1772 psq_outqueue(&hub_ext
->port_status_queue
[port_idx
]);
1773 set_port_state(hub_ext
->port_status_queue
[port_idx
].port_flags
, STATE_WAIT_ADDRESSED
);
1775 //let's new a dev, and start the set-addr request
1776 if (hub_ext
->child_dev
[port_idx
] == 0)
1778 pdev2
= hub_ext
->child_dev
[port_idx
] = dev_mgr_alloc_device(dev_mgr
, hcd
);
1781 purb2
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1784 dev_mgr_free_device(dev_mgr
, pdev2
);
1785 pdev2
= hub_ext
->child_dev
[port_idx
] = NULL
;
1789 if (port_status
.wPortStatus
& USB_PORT_STAT_LOW_SPEED
)
1791 pdev2
->flags
|= USB_DEV_FLAG_LOW_SPEED
;
1793 else if (port_status
.wPortStatus
& USB_PORT_STAT_HIGH_SPEED
)
1794 pdev2
->flags
|= USB_DEV_FLAG_HIGH_SPEED
;
1796 pdev2
->parent_dev
= pdev
;
1797 pdev2
->port_idx
= (UCHAR
) port_idx
;
1800 RtlZeroMemory(purb2
, sizeof(URB
));
1802 purb2
->pdev
= pdev2
;
1803 purb2
->pendp
= &pdev2
->default_endp
;
1804 purb2
->context
= hub_ext
;
1805 purb2
->completion
= hub_set_address_completion
;
1807 InitializeListHead(&purb2
->trasac_list
);
1808 purb2
->reference
= port_idx
;
1811 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb2
->setup_packet
;
1812 psetup
->bmRequestType
= 0;
1813 psetup
->bRequest
= USB_REQ_SET_ADDRESS
;
1814 psetup
->wValue
= pdev2
->dev_addr
;
1821 //creation success, emit the urb
1823 InsertTailList(&dev_mgr
->dev_list
, &pdev2
->dev_link
);
1825 unlock_dev(pdev
, TRUE
);
1826 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->dev_list_lock
);
1828 status
= hcd
->hcd_submit_urb(hcd
, pdev2
, purb2
->pendp
, purb2
);
1830 lock_dev(pdev2
, TRUE
);
1832 usb_dbg_print(DBGLVL_MAXIMUM
,
1833 ("hub_check_reset_port_status(): new dev ref_count=0x%x\n", pdev2
->ref_count
));
1834 unlock_dev(pdev2
, TRUE
);
1836 if (status
!= STATUS_PENDING
)
1838 usb_free_mem(purb2
);
1839 //??? do we need to lock it for SMP?
1840 //dev_mgr_free_device( dev_mgr, pdev2 ), let dev_mgr_thread to clean it;
1842 if (hub_disable_port_request(pdev
, (UCHAR
) port_idx
) != STATUS_PENDING
)
1843 goto LBL_RESET_FAIL
;
1851 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_check_reset_port_status(): not a correct reset status\n"));
1853 unlock_dev(pdev
, TRUE
);
1854 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->dev_list_lock
);
1857 //Any event other than reset cause the reset process stall and another
1858 //pending reset-port requeset is serviced
1859 hub_reexamine_port_status_queue(pdev
, port_idx
, TRUE
);
1860 if (hub_remove_reset_event(pdev
, port_idx
, TRUE
))
1861 hub_start_next_reset_port(dev_mgr
, TRUE
);
1867 hub_reexamine_port_status_queue(PUSB_DEV hub_dev
, ULONG port_idx
, BOOLEAN from_dpc
)
1870 PHUB2_EXTENSION hub_ext
;
1871 PUSB_DEV_MANAGER dev_mgr
;
1873 USE_NON_PENDING_IRQL
;;
1875 if (hub_dev
== NULL
|| port_idx
== 0)
1878 dev_mgr
= dev_mgr_from_dev(hub_dev
);
1880 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
1882 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
1884 lock_dev(hub_dev
, TRUE
);
1885 if (dev_state(hub_dev
) != USB_DEV_STATE_ZOMB
)
1888 hub_ext
= hub_ext_from_dev(hub_dev
);
1889 if (psq_is_empty(&hub_ext
->port_status_queue
[port_idx
]))
1891 set_port_state(hub_ext
->port_status_queue
[port_idx
].port_flags
, STATE_IDLE
);
1896 set_port_state(hub_ext
->port_status_queue
[port_idx
].port_flags
, STATE_EXAMINE_STATUS_QUE
);
1898 hub_post_esq_event(hub_dev
, (UCHAR
) port_idx
, hub_event_examine_status_que
);
1901 unlock_dev(hub_dev
, TRUE
);
1904 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1906 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1911 hub_connect(PDEV_CONNECT_DATA param
, DEV_HANDLE dev_handle
)
1915 DEV_HANDLE endp_handle
;
1916 USB_DEVICE_DESC dev_desc
;
1917 PUSB_CONFIGURATION_DESC pcfg_desc
;
1918 PUSB_INTERFACE_DESC pif_desc
;
1919 PUSB_CTRL_SETUP_PACKET psetup
;
1921 LONG i
, j
, found
, cfg_val
= 0;
1922 PUSB_DEV_MANAGER dev_mgr
;
1926 if (param
== NULL
|| dev_handle
== 0)
1929 dev_mgr
= param
->dev_mgr
;
1931 pcfg_desc
= (PUSB_CONFIGURATION_DESC
) buf
;
1932 endp_handle
= dev_handle
| 0xffff;
1933 UsbBuildGetDescriptorRequest(&urb
,
1935 USB_DT_DEVICE
, 0, 0, (&dev_desc
), (sizeof(USB_DEVICE_DESC
)), NULL
, 0, 0);
1937 status
= usb_submit_urb(dev_mgr
, &urb
);
1938 if (status
!= STATUS_SUCCESS
)
1942 for(i
= 0; i
< dev_desc
.bNumConfigurations
; i
++)
1944 UsbBuildGetDescriptorRequest(&urb
, endp_handle
, USB_DT_CONFIG
, (USHORT
) i
, 0, buf
, 512, NULL
, 0, 0);
1946 status
= usb_submit_urb(dev_mgr
, &urb
);
1947 if (status
!= STATUS_SUCCESS
)
1952 status
= usb_query_and_lock_dev(dev_mgr
, dev_handle
, &pdev
);
1953 if (status
!= STATUS_SUCCESS
)
1956 pif_desc
= (PUSB_INTERFACE_DESC
) & buf
[sizeof(USB_CONFIGURATION_DESC
)];
1957 for(j
= 0; j
< pcfg_desc
->bNumInterfaces
; j
++)
1959 if (pif_desc
->bInterfaceClass
== USB_CLASS_HUB
1960 && pif_desc
->bInterfaceSubClass
== 0 && pif_desc
->bNumEndpoints
== 1)
1962 if ((pif_desc
->bInterfaceProtocol
> 0 && pif_desc
->bInterfaceProtocol
< 3)
1963 || (pif_desc
->bInterfaceProtocol
== 0 && pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
)
1964 || (pif_desc
->bInterfaceProtocol
== 0 && !usb2(pdev
->hcd
)))
1967 cfg_val
= pcfg_desc
->bConfigurationValue
;
1971 if (usb_skip_if_and_altif((PBYTE
*) & pif_desc
) == FALSE
)
1976 usb_unlock_dev(pdev
);
1981 if (usb_skip_one_config((PBYTE
*) & pcfg_desc
) == FALSE
)
1989 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1993 psetup
= (PUSB_CTRL_SETUP_PACKET
) (purb
)->setup_packet
;
1996 purb
->endp_handle
= endp_handle
;
1997 purb
->data_buffer
= NULL
;
1998 purb
->data_length
= 0;
1999 purb
->completion
= hub_set_cfg_completion
;
2000 purb
->context
= dev_mgr
;
2001 purb
->reference
= (LONG
) param
->pdriver
;
2002 psetup
->bmRequestType
= 0;
2003 psetup
->bRequest
= USB_REQ_SET_CONFIGURATION
;
2004 psetup
->wValue
= (USHORT
) cfg_val
;
2006 psetup
->wLength
= 0;
2008 status
= usb_submit_urb(dev_mgr
, purb
);
2009 if (status
!= STATUS_PENDING
)
2020 VOID
hub_set_interface_completion(PURB purb
, PVOID pcontext
);
2023 hub_set_cfg_completion(PURB purb
, PVOID pcontext
)
2025 PUSB_DEV_MANAGER dev_mgr
;
2026 PUSB_DRIVER pdriver
;
2027 ULONG endp_handle
, dev_handle
;
2028 PUSB_CTRL_SETUP_PACKET psetup
;
2032 BOOLEAN high_speed
, multiple_tt
;
2034 USE_BASIC_NON_PENDING_IRQL
;;
2036 if (purb
== NULL
|| pcontext
== NULL
)
2040 dev_mgr
= (PUSB_DEV_MANAGER
) pcontext
;
2041 endp_handle
= purb
->endp_handle
;
2042 dev_handle
= endp_handle
& 0xffff0000;
2043 pdriver
= (PUSB_DRIVER
) purb
->reference
;
2045 multiple_tt
= FALSE
;
2047 if (purb
->status
!= STATUS_SUCCESS
)
2052 status
= usb_query_and_lock_dev(dev_mgr
, purb
->endp_handle
, &pdev
);
2053 if (status
!= STATUS_SUCCESS
)
2055 usb_unlock_dev(pdev
);
2058 lock_dev(pdev
, TRUE
);
2059 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2061 unlock_dev(pdev
, TRUE
);
2062 usb_unlock_dev(pdev
);
2065 if (pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
)
2068 hub_if_from_dev(pdev
, pif
);
2069 if (pif
->altif_count
)
2072 if_idx
= pif
- &pdev
->usb_config
->interf
[0];
2075 unlock_dev(pdev
, TRUE
);
2076 usb_unlock_dev(pdev
);
2078 if (!high_speed
|| !multiple_tt
)
2080 hub_set_interface_completion(purb
, pcontext
);
2084 psetup
= (PUSB_CTRL_SETUP_PACKET
) (purb
)->setup_packet
;
2087 // set the mult-tt if exist
2088 purb
->endp_handle
= endp_handle
;
2089 purb
->data_buffer
= NULL
;
2090 purb
->data_length
= 0;
2091 purb
->completion
= hub_set_interface_completion
;
2092 purb
->context
= dev_mgr
;
2093 purb
->reference
= (LONG
) pdriver
;
2094 psetup
->bmRequestType
= 0;
2095 psetup
->bRequest
= USB_REQ_SET_INTERFACE
;
2096 psetup
->wValue
= (USHORT
) 1; // alternate tt
2097 psetup
->wIndex
= if_idx
; // if index
2098 psetup
->wLength
= 0;
2100 status
= usb_submit_urb(dev_mgr
, purb
);
2101 if (status
== STATUS_PENDING
)
2111 hub_set_interface_completion(PURB purb
, PVOID pcontext
)
2114 PUSB_CTRL_SETUP_PACKET psetup
;
2115 PUSB_DEV_MANAGER dev_mgr
;
2117 DEV_HANDLE endp_handle
;
2118 PUSB_DRIVER pdriver
;
2120 if (purb
== NULL
|| pcontext
== NULL
)
2124 dev_mgr
= (PUSB_DEV_MANAGER
) pcontext
;
2125 endp_handle
= purb
->endp_handle
;
2126 pdriver
= (PUSB_DRIVER
) purb
->reference
;
2128 if (purb
->status
!= STATUS_SUCCESS
)
2134 dev_ext
= usb_alloc_mem(NonPagedPool
, sizeof(HUB2_EXTENSION
));
2135 if (dev_ext
== NULL
)
2141 //acquire hub descriptor
2143 RtlZeroMemory(dev_ext
, sizeof(HUB2_EXTENSION
));
2146 purb
->data_buffer
= (PUCHAR
) & ((HUB2_EXTENSION
*) dev_ext
)->hub_desc
;
2147 purb
->endp_handle
= endp_handle
;
2148 purb
->data_length
= sizeof(USB_HUB_DESCRIPTOR
);
2149 purb
->completion
= hub_get_hub_desc_completion
;
2150 purb
->context
= (PVOID
) dev_mgr
;
2151 purb
->reference
= (ULONG
) dev_ext
;
2152 purb
->pirp
= (PIRP
) pdriver
;
2154 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2155 psetup
->bmRequestType
= 0xa0;
2156 psetup
->bRequest
= USB_REQ_GET_DESCRIPTOR
;
2157 psetup
->wValue
= (0x29 << 8);
2158 psetup
->wLength
= sizeof(USB_HUB_DESCRIPTOR
);
2159 status
= usb_submit_urb(dev_mgr
, purb
);
2161 if (status
!= STATUS_PENDING
)
2163 usb_free_mem(dev_ext
);
2169 //clear the dev_driver fields in the dev.
2176 hub_power_on_port_completion(PURB purb
, PVOID pcontext
)
2178 PUSB_DEV_MANAGER dev_mgr
;
2182 if (pcontext
== NULL
)
2185 dev_mgr
= (PUSB_DEV_MANAGER
) pcontext
;
2187 if (purb
->status
!= STATUS_SUCCESS
)
2189 usb_dbg_print(DBGLVL_MAXIMUM
,
2190 ("hub_power_on_port_completion(): port%d power on failed\n", purb
->reference
));
2194 usb_dbg_print(DBGLVL_MAXIMUM
,
2195 ("hub_power_on_port_completion(): port%d power on succeed\n", purb
->reference
));
2204 hub_power_on_port(PUSB_DEV pdev
, UCHAR port_idx
)
2207 PUSB_CTRL_SETUP_PACKET psetup
;
2208 PUSB_DEV_MANAGER dev_mgr
;
2212 USE_BASIC_NON_PENDING_IRQL
;;
2213 if (pdev
== NULL
|| port_idx
== 0)
2214 return STATUS_INVALID_PARAMETER
;
2216 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
2218 return STATUS_NO_MEMORY
;
2222 lock_dev(pdev
, FALSE
);
2223 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2225 unlock_dev(pdev
, FALSE
);
2226 status
= STATUS_DEVICE_DOES_NOT_EXIST
;
2229 dev_mgr
= dev_mgr_from_dev(pdev
);
2232 purb
->completion
= hub_power_on_port_completion
;
2233 purb
->context
= (PVOID
) dev_mgr
;
2234 purb
->reference
= (ULONG
) port_idx
;
2236 purb
->pendp
= &pdev
->default_endp
;
2238 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2239 psetup
->bmRequestType
= 0x23;
2240 psetup
->bRequest
= USB_REQ_SET_FEATURE
;
2241 psetup
->wValue
= USB_PORT_FEAT_POWER
;
2242 psetup
->wIndex
= (WORD
) port_idx
;
2243 psetup
->wLength
= 0;
2245 unlock_dev(pdev
, FALSE
);
2247 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
2249 if (status
!= STATUS_PENDING
)
2253 return STATUS_PENDING
;
2261 hub_get_hub_desc_completion(PURB purb
, PVOID pcontext
)
2263 PUSB_DEV_MANAGER dev_mgr
;
2264 PHUB2_EXTENSION hub_ext
;
2267 PUSB_INTERFACE pif
= NULL
;
2270 PUSB_DRIVER pdriver
;
2271 DEV_HANDLE dev_handle
;
2273 USE_BASIC_NON_PENDING_IRQL
;;
2280 dev_mgr
= (PUSB_DEV_MANAGER
) pcontext
;
2281 hub_ext
= (PHUB2_EXTENSION
) purb
->reference
;
2282 pdriver
= (PUSB_DRIVER
) purb
->pirp
;
2283 dev_handle
= purb
->endp_handle
& 0xffff0000;
2285 if (pcontext
== NULL
|| purb
->reference
== 0)
2288 if (purb
->status
!= STATUS_SUCCESS
)
2293 // obtain the pointer to the dev
2294 status
= usb_query_and_lock_dev(dev_mgr
, purb
->endp_handle
, &pdev
);
2295 if (status
!= STATUS_SUCCESS
)
2297 usb_unlock_dev(pdev
);
2300 // safe to release the pdev ref since we are in urb completion
2301 usb_unlock_dev(pdev
);
2303 lock_dev(pdev
, TRUE
);
2304 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
||
2305 dev_mgr_set_driver(dev_mgr
, dev_handle
, pdriver
, pdev
) == FALSE
)
2307 unlock_dev(pdev
, TRUE
);
2311 //transit the state to configured
2312 pdev
->flags
&= ~USB_DEV_STATE_MASK
;
2313 pdev
->flags
|= USB_DEV_STATE_CONFIGURED
;
2315 pdev
->dev_ext
= (PBYTE
) hub_ext
;
2316 pdev
->dev_ext_size
= sizeof(HUB2_EXTENSION
);
2318 port_count
= hub_ext
->port_count
= hub_ext
->hub_desc
.bNbrPorts
;
2319 hub_ext
->pdev
= pdev
;
2320 for(i
= 0; i
< pdev
->usb_config
->if_count
; i
++)
2322 pif
= &pdev
->usb_config
->interf
[i
];
2323 if (pif
->pusb_if_desc
->bInterfaceClass
== USB_CLASS_HUB
2324 && pif
->pusb_if_desc
->bInterfaceSubClass
== 0
2325 && pif
->pusb_if_desc
->bInterfaceProtocol
< 3 && pif
->pusb_if_desc
->bNumEndpoints
== 1)
2331 for(i
= 0; i
< MAX_HUB_PORTS
+ 1; i
++)
2333 psq_init((PPORT_STATUS_QUEUE
) hub_ext
->port_status_queue
);
2336 hub_ext
->multiple_tt
= (pif
->pusb_if_desc
->bInterfaceProtocol
== 2);
2338 unlock_dev(pdev
, TRUE
);
2341 hub_start_int_request(pdev
);
2343 for(i
= 0; i
< port_count
; i
++)
2345 hub_power_on_port(pdev
, (UCHAR
) (i
+ 1));
2354 usb_free_mem(hub_ext
);
2359 hub_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
2361 UNREFERENCED_PARAMETER(dev_mgr
);
2362 UNREFERENCED_PARAMETER(dev_handle
);
2367 hub_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
2370 //special use of usb_query and lock dev
2371 if (usb_query_and_lock_dev(dev_mgr
, dev_handle
, &pdev
) != STATUS_SUCCESS
)
2373 //will never be success, since the dev is already in zomb state
2374 //at this point, the dev is valid, ref_count is of none use,
2375 //no need to lock it
2378 usb_free_mem(pdev
->dev_ext
);
2386 hub_lock_unlock_tt(PUSB_DEV pdev
, UCHAR port_idx
, UCHAR type
, BOOLEAN lock
)
2388 PHUB2_EXTENSION dev_ext
;
2391 USE_BASIC_NON_PENDING_IRQL
;;
2393 if (pdev
== NULL
|| port_idx
> 127)
2396 lock_dev(pdev
, FALSE
);
2397 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2399 unlock_dev(pdev
, FALSE
);
2403 dev_ext
= hub_ext_from_dev(pdev
);
2404 if (dev_ext
== NULL
)
2406 unlock_dev(pdev
, FALSE
);
2409 if (type
== USB_ENDPOINT_XFER_INT
|| type
== USB_ENDPOINT_XFER_ISOC
)
2411 pmap
= dev_ext
->tt_status_map
;
2413 else if (type
== USB_ENDPOINT_XFER_BULK
|| type
== USB_ENDPOINT_XFER_CONTROL
)
2415 pmap
= dev_ext
->tt_bulk_map
;
2420 if (pmap
[port_idx
>> 5] & (1 << port_idx
))
2422 unlock_dev(pdev
, FALSE
);
2425 pmap
[port_idx
>> 5] |= (1 << port_idx
);
2429 pmap
[port_idx
>> 5] &= ~(1 << port_idx
);
2432 unlock_dev(pdev
, FALSE
);
2437 hub_lock_tt(PUSB_DEV pdev
,
2439 UCHAR type
// transfer type
2442 return hub_lock_unlock_tt(pdev
, port_idx
, type
, TRUE
);
2446 hub_unlock_tt(PUSB_DEV pdev
, UCHAR port_idx
, UCHAR type
)
2448 return hub_lock_unlock_tt(pdev
, port_idx
, type
, FALSE
);
2452 hub_clear_tt_buffer_completion(PURB purb
, PVOID context
)
2454 PUSB_CTRL_SETUP_PACKET psetup
;
2455 PURB_HS_PIPE_CONTENT pipe_content
;
2456 PHUB2_EXTENSION hub_ext
;
2459 if (purb
== NULL
|| context
== NULL
)
2462 hub_ext
= (PHUB2_EXTENSION
) context
;
2463 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2464 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->reference
;
2465 hub_unlock_tt(purb
->pdev
, (UCHAR
) psetup
->wIndex
, (UCHAR
) pipe_content
->trans_type
);
2468 hcd
= hub_ext
->pdev
->hcd
;
2470 // let those blocked urbs ( sharing the same tt )have chance to be scheduled
2471 if (hcd
&& usb2(hcd
))
2472 hcd
->hcd_submit_urb(hcd
, NULL
, NULL
, NULL
);
2477 // send CLEAR_TT_BUFFER to the hub
2479 hub_clear_tt_buffer(PUSB_DEV pdev
, URB_HS_PIPE_CONTENT pipe_content
, UCHAR port_idx
)
2482 PUSB_CTRL_SETUP_PACKET psetup
;
2483 PHUB2_EXTENSION hub_ext
;
2486 USE_BASIC_NON_PENDING_IRQL
;;
2491 if (pipe_content
.speed_high
)
2494 lock_dev(pdev
, FALSE
);
2495 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2497 unlock_dev(pdev
, FALSE
);
2501 hub_ext
= hub_ext_from_dev(pdev
);
2502 if (hub_ext
== NULL
)
2504 unlock_dev(pdev
, FALSE
);
2507 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
2508 RtlZeroMemory(purb
, sizeof(URB
));
2512 unlock_dev(pdev
, FALSE
);
2517 purb
->status
= STATUS_SUCCESS
;
2518 purb
->data_buffer
= NULL
;
2519 purb
->data_length
= 0; // ( hub_ext->port_count + 7 ) / 8;
2521 // hub_if_from_dev( pdev, pif );
2522 purb
->pendp
= &pdev
->default_endp
;
2525 purb
->completion
= hub_clear_tt_buffer_completion
;
2526 purb
->context
= hub_ext
;
2527 purb
->reference
= *((PLONG
) & pipe_content
);
2532 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2533 psetup
->bmRequestType
= 0x23; //host-device class other recepient
2534 psetup
->bRequest
= HUB_REQ_CLEAR_TT_BUFFER
;
2535 psetup
->wValue
= (USHORT
) ((pipe_content
.endp_addr
) | (pipe_content
.dev_addr
<< 4) |
2536 (pipe_content
.trans_type
<< 10) | (pipe_content
.trans_dir
<< 15));
2538 if (hub_ext
->multiple_tt
)
2540 psetup
->wIndex
= (USHORT
) port_idx
;
2545 psetup
->wLength
= 0;
2546 unlock_dev(pdev
, FALSE
);
2548 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
2549 if (status
!= STATUS_PENDING
)
2559 hub_event_clear_tt_buffer(PUSB_DEV pdev
, //always null. we do not use this param
2564 UNREFERENCED_PARAMETER(event
);
2565 hub_clear_tt_buffer(pdev
, *((PURB_HS_PIPE_CONTENT
) & context
), (UCHAR
) param
);
2570 hub_post_clear_tt_event(PUSB_DEV pdev
, BYTE port_idx
, ULONG pipe
)
2572 PUSB_DEV_MANAGER dev_mgr
;
2574 USE_NON_PENDING_IRQL
;;
2576 dev_mgr
= dev_mgr_from_dev(pdev
);
2578 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
2579 lock_dev(pdev
, TRUE
);
2580 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2582 unlock_dev(pdev
, TRUE
);
2583 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
2586 pevent
= alloc_event(&dev_mgr
->event_pool
, 1);
2589 unlock_dev(pdev
, TRUE
);
2590 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
2595 pevent
->event
= USB_EVENT_WAIT_RESET_PORT
;
2596 pevent
->pdev
= pdev
;
2597 pevent
->context
= pipe
;
2598 pevent
->param
= port_idx
;
2599 pevent
->flags
= USB_EVENT_FLAG_ACTIVE
;
2600 pevent
->process_queue
= event_list_default_process_queue
;
2601 pevent
->process_event
= hub_event_clear_tt_buffer
;
2602 pevent
->pnext
= NULL
;
2603 InsertTailList(&dev_mgr
->event_list
, &pevent
->event_link
);
2605 unlock_dev(pdev
, TRUE
);
2606 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
2608 KeSetEvent(&dev_mgr
->wake_up_event
, 0, FALSE
);
2613 init_irp_list(PIRP_LIST irp_list
)
2616 KeInitializeSpinLock(&irp_list
->irp_list_lock
);
2617 InitializeListHead(&irp_list
->irp_busy_list
);
2618 InitializeListHead(&irp_list
->irp_free_list
);
2619 irp_list
->irp_list_element_array
=
2620 usb_alloc_mem(NonPagedPool
, sizeof(IRP_LIST_ELEMENT
) * MAX_IRP_LIST_SIZE
);
2622 if (irp_list
->irp_list_element_array
== NULL
)
2625 RtlZeroMemory(irp_list
->irp_list_element_array
, sizeof(IRP_LIST_ELEMENT
) * MAX_IRP_LIST_SIZE
);
2626 for(i
= 0; i
< MAX_IRP_LIST_SIZE
; i
++)
2628 InsertTailList(&irp_list
->irp_free_list
, &irp_list
->irp_list_element_array
[i
].irp_link
);
2630 irp_list
->irp_free_list_count
= MAX_IRP_LIST_SIZE
;
2635 destroy_irp_list(PIRP_LIST irp_list
)
2637 InitializeListHead(&irp_list
->irp_busy_list
);
2638 InitializeListHead(&irp_list
->irp_free_list
);
2639 usb_free_mem(irp_list
->irp_list_element_array
);
2640 irp_list
->irp_list_element_array
= NULL
;
2641 irp_list
->irp_free_list_count
= 0;
2646 add_irp_to_list(PIRP_LIST irp_list
, PIRP pirp
, PURB purb
)
2649 PIRP_LIST_ELEMENT pile
;
2651 if (irp_list
== NULL
|| pirp
== NULL
|| purb
== NULL
)
2654 IoAcquireCancelSpinLock(&old_irql
);
2655 KeAcquireSpinLockAtDpcLevel(&irp_list
->irp_list_lock
);
2657 if (irp_list
->irp_free_list_count
== 0)
2659 KeReleaseSpinLockFromDpcLevel(&irp_list
->irp_list_lock
);
2660 IoReleaseCancelSpinLock(old_irql
);
2663 pile
= (PIRP_LIST_ELEMENT
) RemoveHeadList(&irp_list
->irp_free_list
);
2668 irp_list
->irp_free_list_count
--;
2669 InsertTailList(&irp_list
->irp_busy_list
, &pile
->irp_link
);
2670 (void)IoSetCancelRoutine(pirp
, dev_mgr_cancel_irp
);
2672 KeReleaseSpinLockFromDpcLevel(&irp_list
->irp_list_lock
);
2673 IoReleaseCancelSpinLock(old_irql
);
2678 remove_irp_from_list(PIRP_LIST irp_list
,
2680 PUSB_DEV_MANAGER dev_mgr
//if dev_mgr is not NULL, the urb needs to be canceled
2683 PIRP_LIST_ELEMENT pile
;
2684 PLIST_ENTRY pthis
, pnext
;
2686 DEV_HANDLE endp_handle
;
2688 PUSB_ENDPOINT pendp
;
2691 USE_NON_PENDING_IRQL
;;
2693 if (irp_list
== NULL
|| pirp
== NULL
)
2696 KeAcquireSpinLock(&irp_list
->irp_list_lock
, &old_irql
);
2698 if (irp_list
->irp_free_list_count
== MAX_IRP_LIST_SIZE
)
2700 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);
2705 ListFirst(&irp_list
->irp_busy_list
, pthis
);
2708 pile
= struct_ptr(pthis
, IRP_LIST_ELEMENT
, irp_link
);
2709 if (pile
->pirp
== pirp
)
2714 RemoveEntryList(pthis
);
2715 InsertTailList(&irp_list
->irp_free_list
, pthis
);
2716 irp_list
->irp_free_list_count
++;
2719 ListNext(&irp_list
->irp_busy_list
, pthis
, pnext
);
2726 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);
2730 endp_handle
= purb
->endp_handle
;
2731 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);
2735 // indicate we needs to cancel the urb, this condition happens only in cancel routine
2736 // we should notice that even the hcd_cancel_urb is called, the irp may not be canceled
2737 // if the urb does not exist in any queue of the host controller driver, indicating
2738 // it is being processed by dpc. Thus, the dpc will certainly prevent the irp in
2739 // completion from being canceled at the same time. On the other hand, if the
2740 // hcd_cancel_urb succeeds, it either directly complete the irp or queue the dpc for
2741 // irp completion. So, there won't be two simutaneous threads processing the same
2744 if (usb_query_and_lock_dev(dev_mgr
, endp_handle
, &pdev
) != STATUS_SUCCESS
)
2747 lock_dev(pdev
, TRUE
);
2748 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2750 unlock_dev(pdev
, FALSE
);
2751 usb_unlock_dev(pdev
);
2756 endp_from_handle(pdev
, endp_handle
, pendp
);
2757 unlock_dev(pdev
, TRUE
);
2758 hcd
->hcd_cancel_urb(hcd
, pdev
, pendp
, purb
);
2759 usb_unlock_dev(pdev
);
2766 irp_list_empty(PIRP_LIST irp_list
)
2770 KeAcquireSpinLock(&irp_list
->irp_list_lock
, &old_irql
);
2771 ret
= (BOOLEAN
) (irp_list
->irp_free_list_count
== MAX_IRP_LIST_SIZE
);
2772 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);
2777 irp_list_full(PIRP_LIST irp_list
)
2781 KeAcquireSpinLock(&irp_list
->irp_list_lock
, &old_irql
);
2782 ret
= (BOOLEAN
) (irp_list
->irp_free_list_count
== 0);
2783 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);