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
, &pevent
->event_link
);
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
, &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
));
438 unlock_dev(pdev
, FALSE
);
439 return STATUS_NO_MEMORY
;
442 RtlZeroMemory(purb
, sizeof(URB
));
445 purb
->status
= STATUS_SUCCESS
;
446 hub_ext
= hub_ext_from_dev(pdev
);
447 purb
->data_buffer
= hub_ext
->int_data_buf
;
448 purb
->data_length
= (hub_ext
->port_count
+ 7) / 8;
450 hub_if_from_dev(pdev
, pif
);
451 usb_dbg_print(DBGLVL_ULTRA
, ("hub_start_int_request(): pdev=0x%x, pif=0x%x\n", pdev
, pif
));
452 purb
->pendp
= &pif
->endp
[0];
455 purb
->completion
= hub_int_completion
;
456 purb
->context
= hub_ext
;
461 unlock_dev(pdev
, FALSE
);
463 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
464 if (status
!= STATUS_PENDING
)
474 hub_int_completion(PURB purb
, PVOID pcontext
)
478 PHUB2_EXTENSION hub_ext
;
480 PUSB_CTRL_SETUP_PACKET psetup
;
485 USE_BASIC_NON_PENDING_IRQL
;
490 if (pcontext
== NULL
)
496 usb_dbg_print(DBGLVL_ULTRA
, ("hub_int_completion(): entering...\n"));
501 lock_dev(pdev
, TRUE
);
502 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
504 unlock_dev(pdev
, TRUE
);
511 if (purb
->status
== STATUS_SUCCESS
)
514 for(i
= 1; i
<= hub_ext
->port_count
; i
++)
516 if (hub_ext
->int_data_buf
[i
>> 3] & (1 << i
))
521 if (i
> hub_ext
->port_count
)
523 //no status change, re-initialize the int request
524 unlock_dev(pdev
, TRUE
);
526 hub_start_int_request(pdev
);
532 //re-use the urb to get port status
533 purb
->pendp
= &pdev
->default_endp
;
534 purb
->data_buffer
= (PUCHAR
) & hub_ext
->port_status
;
536 purb
->data_length
= sizeof(USB_PORT_STATUS
);
539 purb
->context
= hub_ext
;
541 purb
->completion
= hub_get_port_status_completion
;
542 purb
->reference
= port_idx
;
544 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
546 psetup
->bmRequestType
= 0xa3; //host-device class other recepient
547 psetup
->bRequest
= USB_REQ_GET_STATUS
;
549 psetup
->wIndex
= (USHORT
) port_idx
;
553 unlock_dev(pdev
, TRUE
);
555 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
556 if (usb_error(status
))
561 else if (status
== STATUS_SUCCESS
)
563 // this is for root hub
564 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
570 unlock_dev(pdev
, TRUE
);
571 if (usb_halted(purb
->status
))
574 usb_reset_pipe(pdev
, purb
->pendp
, hub_reset_pipe_completion
, NULL
);
584 hub_get_port_status_completion(PURB purb
, PVOID context
)
589 PHUB2_EXTENSION hub_ext
;
590 PUSB_CTRL_SETUP_PACKET psetup
;
594 USE_BASIC_NON_PENDING_IRQL
;
596 if (purb
== NULL
|| context
== NULL
)
599 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_get_port_feature_completion(): entering...\n"));
604 lock_dev(pdev
, TRUE
);
605 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
607 unlock_dev(pdev
, TRUE
);
613 if (usb_error(purb
->status
))
615 unlock_dev(pdev
, TRUE
);
618 //simply retry the request refer to item 55 in document
619 status
= hcd
->hcd_submit_urb(hcd
, pdev
, pendp
, purb
);
620 if (status
!= STATUS_PENDING
)
622 if (status
== STATUS_SUCCESS
)
624 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
630 // must be fatal error
631 // FIXME: better to pass it to the completion for further
640 hub_ext
= hub_ext_from_dev(pdev
);
641 port_idx
= (BYTE
) purb
->reference
;
643 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_get_port_stataus_completion(): port_idx=0x%x, hcd =0x%x, \
644 pdev=0x%x, purb=0x%x, hub_ext=0x%x, portsc=0x%x \n", port_idx
, pdev
->hcd
, pdev
,
645 purb
, hub_ext
, *((PULONG
) purb
->data_buffer
)));
647 psq_enqueue(&hub_ext
->port_status_queue
[port_idx
], *((PULONG
) purb
->data_buffer
));
649 //reuse the urb to clear the feature
650 RtlZeroMemory(purb
, sizeof(URB
));
652 purb
->data_buffer
= NULL
;
653 purb
->data_length
= 0;
654 purb
->pendp
= &pdev
->default_endp
;
657 purb
->context
= (PVOID
) & hub_ext
->port_status
;
659 purb
->completion
= hub_clear_port_feature_completion
;
660 purb
->reference
= port_idx
;
662 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
664 psetup
->bmRequestType
= 0x23; //host-device class port recepient
665 psetup
->bRequest
= USB_REQ_CLEAR_FEATURE
;
666 psetup
->wIndex
= port_idx
;
670 if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_CONNECTION
)
672 psetup
->wValue
= USB_PORT_FEAT_C_CONNECTION
;
674 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_ENABLE
)
676 psetup
->wValue
= USB_PORT_FEAT_C_ENABLE
;
678 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_SUSPEND
)
680 psetup
->wValue
= USB_PORT_FEAT_C_SUSPEND
;
682 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_OVERCURRENT
)
684 psetup
->wValue
= USB_PORT_FEAT_C_OVER_CURRENT
;
686 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_RESET
)
688 psetup
->wValue
= USB_PORT_FEAT_C_RESET
;
690 unlock_dev(pdev
, TRUE
);
692 status
= hcd
->hcd_submit_urb(hcd
, pdev
, pendp
, purb
);
694 // if( status != STATUS_SUCCESS )
695 if (status
!= STATUS_PENDING
)
697 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
699 /*else if( usb_error( status ) )
701 usb_free_mem( purb );
709 hub_clear_port_feature_completion(PURB purb
, PVOID context
)
713 BOOLEAN event_post
, brh
;
718 PHUB2_EXTENSION hub_ext
= NULL
;
719 PUSB_DEV_MANAGER dev_mgr
;
721 PUSB_CTRL_SETUP_PACKET psetup
;
723 USE_BASIC_NON_PENDING_IRQL
;
734 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_clear_port_feature_completion(): entering...\n"));
737 port_idx
= (BYTE
) purb
->reference
;
739 lock_dev(pdev
, TRUE
);
740 dev_mgr
= dev_mgr_from_dev(pdev
);
742 brh
= (BOOLEAN
) (dev_class(pdev
) == USB_DEV_CLASS_ROOT_HUB
);
744 if (usb_error(purb
->status
))
746 unlock_dev(pdev
, TRUE
);
751 status
= hcd
->hcd_submit_urb(hcd
, purb
->pdev
, purb
->pendp
, purb
);
752 if (status
!= STATUS_PENDING
)
754 if (status
== STATUS_SUCCESS
)
756 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
761 // FIXME: should we pass the error to the completion directly
762 // instead of forstall it here?
764 // do not think the device is workable, no requests to it any more.
765 // including the int polling
771 hub_check_reset_port_status(pdev
, port_idx
);
777 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
779 unlock_dev(pdev
, TRUE
);
784 pc
= ((PUSB_PORT_STATUS
) context
)->wPortChange
;
788 // the bits are tested in ascending order
789 if (pc
& USB_PORT_STAT_C_CONNECTION
)
791 pc
&= ~USB_PORT_STAT_C_CONNECTION
;
793 else if (pc
& USB_PORT_STAT_C_ENABLE
)
795 pc
&= ~USB_PORT_STAT_C_ENABLE
;
797 else if (pc
& USB_PORT_STAT_C_SUSPEND
)
799 pc
&= ~USB_PORT_STAT_C_SUSPEND
;
801 else if (pc
& USB_PORT_STAT_C_OVERCURRENT
)
803 pc
&= ~USB_PORT_STAT_C_OVERCURRENT
;
805 else if (pc
& USB_PORT_STAT_C_RESET
)
807 pc
&= ~USB_PORT_STAT_C_RESET
;
810 ((PUSB_PORT_STATUS
) context
)->wPortChange
= (USHORT
) pc
;
812 hub_ext
= hub_ext_from_dev(pdev
);
816 //some other status change on the port still active
817 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
819 if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_CONNECTION
)
821 psetup
->wValue
= USB_PORT_FEAT_C_CONNECTION
;
823 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_ENABLE
)
825 psetup
->wValue
= USB_PORT_FEAT_C_ENABLE
;
827 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_SUSPEND
)
829 psetup
->wValue
= USB_PORT_FEAT_C_SUSPEND
;
831 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_OVERCURRENT
)
833 psetup
->wValue
= USB_PORT_FEAT_C_OVER_CURRENT
;
835 else if (hub_ext
->port_status
.wPortChange
& USB_PORT_STAT_C_RESET
)
837 psetup
->wValue
= USB_PORT_FEAT_C_RESET
;
839 unlock_dev(pdev
, TRUE
);
841 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
842 if (status
!= STATUS_PENDING
)
844 if (status
== STATUS_SUCCESS
)
846 usb_dbg_print(DBGLVL_MAXIMUM
,
847 ("hub_clear_port_status_completion(): port_idx=0x%x, hcd=0x%x, \
848 pdev=0x%x, purb=0x%x, hub_ext=0x%x, wPortChange=0x%x \n",
849 port_idx
, pdev
->hcd
, pdev
, purb
, hub_ext
, pc
));
851 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
855 usb_dbg_print(DBGLVL_MAXIMUM
, (" hub_clear_port_feature_completion(): \
856 error=0x%x\n", status
));
858 // usb_free_mem( purb );
859 goto LBL_SCAN_PORT_STAT
;
865 for(i
= 1; i
<= hub_ext
->port_count
; i
++)
867 if (hub_ext
->int_data_buf
[i
>> 3] & (1 << i
))
873 //clear the port-change map, we have get port i's status.
874 hub_ext
->int_data_buf
[i
>> 3] &= ~(1 << i
);
876 //rescan to find some other port that has status change
877 for(i
= 1; i
<= hub_ext
->port_count
; i
++)
879 if (hub_ext
->int_data_buf
[i
>> 3] & (1 << i
))
885 if (i
<= hub_ext
->port_count
)
887 //still has port-change pending, get the port status change
888 port_idx
= (UCHAR
) i
;
891 purb
->data_buffer
= (PUCHAR
) & hub_ext
->port_status
;
892 purb
->data_length
= sizeof(USB_PORT_STATUS
);
893 purb
->pendp
= &pdev
->default_endp
;
896 purb
->context
= hub_ext
;
898 purb
->completion
= hub_get_port_status_completion
;
899 purb
->reference
= port_idx
;
901 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
903 psetup
->bmRequestType
= 0xa3; //host-device class other recepient
904 psetup
->bRequest
= USB_REQ_GET_STATUS
;
906 psetup
->wIndex
= port_idx
;
911 unlock_dev(pdev
, TRUE
);
913 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
914 if (status
!= STATUS_PENDING
)
916 if (status
== STATUS_SUCCESS
)
918 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
921 { //must be fatal error
922 // usb_free_mem( purb );
923 goto LBL_SCAN_PORT_STAT
;
929 unlock_dev(pdev
, TRUE
);
933 //all status changes are cleared
939 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
940 lock_dev(pdev
, TRUE
);
942 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
945 // if reset is in process, the dev_mgr_disconnect_dev will continue
946 // the following resets
948 unlock_dev(pdev
, TRUE
);
949 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
953 //at last we wake up thread if some port have status change to process
955 for(i
= 1, event_post
= FALSE
; i
<= hub_ext
->port_count
; i
++)
957 if (psq_is_empty(&hub_ext
->port_status_queue
[i
]) == FALSE
)
959 if (port_state(hub_ext
->port_status_queue
[i
].port_flags
) == STATE_IDLE
||
960 port_state(hub_ext
->port_status_queue
[i
].port_flags
) == STATE_WAIT_ADDRESSED
)
962 // have status in the queue pending
963 // STATE_WAIT_ADDRESSED is added to avoid some bad mannered
964 // hub to disturb the reset process
965 hub_post_esq_event(pdev
, (BYTE
) i
, hub_event_examine_status_que
);
967 else if (port_state(hub_ext
->port_status_queue
[i
].port_flags
) == STATE_WAIT_RESET_COMPLETE
)
969 //there is only one reset at one time
975 unlock_dev(pdev
, TRUE
);
976 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
980 hub_check_reset_port_status(pdev
, port_idx
);
982 //reinitialize the int request, here to reduce some uncertainty of concurrency
983 hub_start_int_request(pdev
);
989 hub_event_examine_status_que(PUSB_DEV pdev
,
991 ULONG context
, //hub_ext
992 ULONG param
//port_idx
995 PHUB2_EXTENSION hub_ext
;
999 PUSB_DEV_MANAGER dev_mgr
;
1001 USE_NON_PENDING_IRQL
;
1003 UNREFERENCED_PARAMETER(event
);
1005 if (pdev
== NULL
|| context
== 0 || param
== 0)
1010 lock_dev(pdev
, FALSE
);
1011 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1013 unlock_dev(pdev
, FALSE
);
1017 dev_mgr
= dev_mgr_from_dev(pdev
);
1018 hub_ext
= hub_ext_from_dev(pdev
);
1020 if (psq_is_empty(&hub_ext
->port_status_queue
[param
]))
1022 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_IDLE
);
1023 unlock_dev(pdev
, FALSE
);
1027 *((ULONG
*) & ps
) = psq_outqueue(&hub_ext
->port_status_queue
[param
]);
1030 pchild_dev
= hub_ext
->child_dev
[param
];
1031 hub_ext
->child_dev
[param
] = 0;
1033 usb_dbg_print(DBGLVL_MAXIMUM
,
1034 ("hub_event_examine_status_queue(): dev_addr=0x%x, port=0x%x, wPortChange=0x%x, wPortStatus=0x%x\n",
1035 pdev
->dev_addr
, param
, ps
.wPortChange
, ps
.wPortStatus
));
1037 unlock_dev(pdev
, FALSE
);
1039 if (pchild_dev
!= NULL
)
1040 dev_mgr_disconnect_dev(pchild_dev
);
1042 if (((ps
.wPortChange
& USB_PORT_STAT_C_ENABLE
) &&
1043 ((pdev
->flags
& USB_DEV_CLASS_MASK
) != USB_DEV_CLASS_ROOT_HUB
))
1044 || (ps
.wPortChange
& USB_PORT_STAT_C_OVERCURRENT
)
1045 || (ps
.wPortChange
& USB_PORT_STAT_C_RESET
)
1046 || ((ps
.wPortChange
& USB_PORT_STAT_C_CONNECTION
) &&
1047 !(ps
.wPortStatus
& USB_PORT_STAT_CONNECTION
)))
1049 usb_dbg_print(DBGLVL_MAXIMUM
,
1050 ("hub_event_examine_status_queue(): error occured, portc=0x%x, ports=0x%x\n",
1051 ps
.wPortChange
, ps
.wPortStatus
));
1053 lock_dev(pdev
, FALSE
);
1054 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1056 unlock_dev(pdev
, FALSE
);
1059 if (psq_is_empty(&hub_ext
->port_status_queue
[param
]))
1061 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_IDLE
);
1065 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_EXAMINE_STATUS_QUE
);
1067 unlock_dev(pdev
, FALSE
);
1071 else if ((ps
.wPortChange
& USB_PORT_STAT_C_CONNECTION
)
1072 && (ps
.wPortStatus
& USB_PORT_STAT_CONNECTION
)
1073 && psq_is_empty(&hub_ext
->port_status_queue
[param
]))
1075 KeAcquireSpinLock(&dev_mgr
->timer_svc_list_lock
, &old_irql
);
1076 lock_dev(pdev
, TRUE
);
1077 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1079 unlock_dev(pdev
, TRUE
);
1080 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
1081 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_event_examine_status_queue(): dev lost\n"));
1084 ptimer
= alloc_timer_svc(&dev_mgr
->timer_svc_pool
, 1);
1087 unlock_dev(pdev
, TRUE
);
1088 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
1089 usb_dbg_print(DBGLVL_MAXIMUM
,
1090 ("hub_event_examine_status_queue(): timer can not allocated\n"));
1095 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_event_examine_status_queue(): new connection comes\n"));
1097 ptimer
->counter
= 0;
1098 ptimer
->threshold
= 21; //100 ms
1100 if (ps
.wPortStatus
& USB_PORT_STAT_LOW_SPEED
)
1101 ptimer
->threshold
= 51; //500 ms
1103 ptimer
->context
= param
;
1104 ptimer
->pdev
= pdev
;
1105 ptimer
->func
= hub_timer_wait_dev_stable
;
1106 InsertTailList(&dev_mgr
->timer_svc_list
, &ptimer
->timer_svc_link
);
1108 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_WAIT_STABLE
);
1109 unlock_dev(pdev
, TRUE
);
1110 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
1116 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_event_examine_status_queue(): unknown error\n"));
1124 hub_timer_wait_dev_stable(PUSB_DEV pdev
,
1125 PVOID context
//port-index
1129 PHUB2_EXTENSION hub_ext
;
1131 PUSB_DEV_MANAGER dev_mgr
;
1133 USE_BASIC_NON_PENDING_IRQL
;
1135 if (pdev
== NULL
|| context
== 0)
1138 dev_mgr
= dev_mgr_from_dev(pdev
);
1139 param
= (ULONG
) context
;
1140 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
1141 lock_dev(pdev
, TRUE
);
1145 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1150 hub_ext
= hub_ext_from_dev(pdev
);
1152 if (!psq_is_empty(&hub_ext
->port_status_queue
[param
]))
1154 //error occured, normally we should not receive event here
1155 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_EXAMINE_STATUS_QUE
);
1157 hub_post_esq_event(pdev
, (BYTE
) param
, hub_event_examine_status_que
);
1161 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_WAIT_RESET
);
1163 hub_post_esq_event(pdev
, (BYTE
) param
, hub_event_dev_stable
);
1168 unlock_dev(pdev
, TRUE
);
1169 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1174 hub_event_dev_stable(PUSB_DEV pdev
,
1176 ULONG context
, //hub_ext
1177 ULONG param
//port_idx
1181 PHUB2_EXTENSION hub_ext
;
1182 PUSB_EVENT pevent
, pevent1
;
1183 PLIST_ENTRY pthis
, pnext
;
1186 PUSB_DEV_MANAGER dev_mgr
;
1189 PUSB_CTRL_SETUP_PACKET psetup
;
1191 USE_NON_PENDING_IRQL
;
1193 UNREFERENCED_PARAMETER(event
);
1195 if (pdev
== NULL
|| context
== 0 || param
== 0)
1198 dev_mgr
= dev_mgr_from_dev(pdev
);
1199 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
1200 lock_dev(pdev
, TRUE
);
1202 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1205 hub_ext
= hub_ext_from_dev(pdev
);
1208 pevent
= alloc_event(&dev_mgr
->event_pool
, 1);
1212 pevent
->event
= USB_EVENT_WAIT_RESET_PORT
;
1213 pevent
->pdev
= pdev
;
1214 pevent
->context
= (ULONG
) hub_ext
;
1215 pevent
->param
= param
;
1216 pevent
->flags
= USB_EVENT_FLAG_QUE_RESET
;
1217 pevent
->process_event
= NULL
; //hub_event_reset_port_complete;
1218 pevent
->process_queue
= NULL
; //hub_event_reset_process_queue;
1219 pevent
->pnext
= NULL
;
1221 ListFirst(&dev_mgr
->event_list
, pthis
);
1226 //insert the event in to the wait-queue
1227 pevent1
= (PUSB_EVENT
) pthis
;
1228 if (pevent1
->event
== USB_EVENT_WAIT_RESET_PORT
)
1230 while (pevent1
->pnext
)
1231 pevent1
= pevent1
->pnext
;
1233 pevent1
->pnext
= pevent
;
1237 ListNext(&dev_mgr
->event_list
, pthis
, pnext
);
1243 //Let's start a reset port request
1244 InsertHeadList(&dev_mgr
->event_list
, &pevent
->event_link
);
1245 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1246 if (!purb
) goto LBL_OUT
;
1247 RtlZeroMemory(purb
, sizeof(URB
));
1249 purb
->data_buffer
= NULL
;
1250 purb
->data_length
= 0;
1251 purb
->pendp
= &pdev
->default_endp
;
1253 purb
->context
= hub_ext
;
1255 purb
->completion
= hub_start_reset_port_completion
; //hub_int_completion;
1256 purb
->reference
= param
;
1258 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1260 psetup
->bmRequestType
= 0x23; //host-device other recepient
1261 psetup
->bRequest
= USB_REQ_SET_FEATURE
;
1262 psetup
->wValue
= USB_PORT_FEAT_RESET
;
1263 psetup
->wIndex
= (USHORT
) param
;
1264 psetup
->wLength
= 0;
1267 //enter another state
1268 set_port_state(hub_ext
->port_status_queue
[param
].port_flags
, STATE_WAIT_RESET_COMPLETE
);
1270 unlock_dev(pdev
, TRUE
);
1271 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1273 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
1274 if (status
!= STATUS_PENDING
)
1276 //must be fatal error
1278 hub_reexamine_port_status_queue(pdev
, param
, FALSE
);
1279 if (hub_remove_reset_event(pdev
, param
, FALSE
))
1280 hub_start_next_reset_port(dev_mgr
, FALSE
);
1286 unlock_dev(pdev
, TRUE
);
1287 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1292 hub_start_reset_port_completion(PURB purb
, PVOID context
)
1295 PUSB_ENDPOINT pendp
;
1296 PUSB_DEV_MANAGER dev_mgr
= NULL
;
1297 NTSTATUS status
= STATUS_SUCCESS
;
1301 USE_BASIC_NON_PENDING_IRQL
;
1305 if (context
== NULL
)
1307 //fatal error no retry.
1313 pendp
= purb
->pendp
;
1314 port_idx
= purb
->reference
;
1316 lock_dev(pdev
, TRUE
);
1318 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1320 unlock_dev(pdev
, TRUE
);
1322 goto LBL_FREE_EVENT
;
1326 dev_mgr
= dev_mgr_from_dev(pdev
);
1327 unlock_dev(pdev
, TRUE
);
1329 status
= purb
->status
;
1332 if (!usb_error(status
))
1338 //since we have no patient to retry the dev, we should remove the event of
1339 //wait_reset_port on the port from the event list. and if possible, start
1340 //another reset process. note other port on the dev still have chance to be
1341 //reset if necessary.
1342 hub_reexamine_port_status_queue(pdev
, port_idx
, TRUE
);
1343 if (hub_remove_reset_event(pdev
, port_idx
, TRUE
))
1344 hub_start_next_reset_port(dev_mgr
, TRUE
);
1350 hub_set_address_completion(PURB purb
, PVOID context
)
1352 PUSB_DEV pdev
, hub_dev
;
1353 PUSB_ENDPOINT pendp
;
1354 PUSB_DEV_MANAGER dev_mgr
;
1358 USE_BASIC_NON_PENDING_IRQL
;
1360 hcd_dbg_print(DBGLVL_MAXIMUM
, ("hub_set_address_completion: purb=%p context=%p\n", purb
, context
));
1365 if (context
== NULL
)
1367 //fatal error no retry.
1373 pendp
= purb
->pendp
;
1374 port_idx
= purb
->reference
;
1376 lock_dev(pdev
, TRUE
);
1379 dev_mgr
= dev_mgr_from_dev(pdev
);
1380 hub_dev
= pdev
->parent_dev
;
1381 port_idx
= pdev
->port_idx
;
1383 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1385 unlock_dev(pdev
, TRUE
);
1387 //some error occured, let's start the next reset event
1388 goto LBL_RESET_NEXT
;
1391 pdev
->flags
&= ~USB_DEV_STATE_MASK
;
1392 pdev
->flags
|= USB_DEV_STATE_ADDRESSED
;
1394 unlock_dev(pdev
, TRUE
);
1395 status
= purb
->status
;
1397 if (usb_error(status
))
1401 hcd_dbg_print(DBGLVL_MAXIMUM
, ("hub_set_address_completion: can not set address\n"));
1402 status
= hcd
->hcd_submit_urb(hcd
, pdev
, pendp
, purb
);
1403 //some error occured, disable the port
1404 if (status
!= STATUS_PENDING
)
1407 status
= hub_disable_port_request(hub_dev
, (UCHAR
) port_idx
);
1413 //let address settle
1414 usb_wait_ms_dpc(10);
1416 //let's config the dev
1417 dev_mgr_start_config_dev(pdev
);
1420 //second, remove the event in the queue
1421 hub_reexamine_port_status_queue(hub_dev
, port_idx
, TRUE
);
1422 if (hub_remove_reset_event(hub_dev
, port_idx
, TRUE
))
1423 hub_start_next_reset_port(dev_mgr
, TRUE
);
1428 hub_disable_port_completion(PURB purb
, PVOID pcontext
)
1431 PUSB_DEV_MANAGER dev_mgr
;
1433 PUSB_ENDPOINT pendp
;
1434 PUSB_CTRL_SETUP_PACKET psetup
;
1436 UNREFERENCED_PARAMETER(pcontext
);
1442 pendp
= purb
->pendp
;
1443 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1444 port_idx
= (UCHAR
) psetup
->wIndex
;
1446 dev_mgr
= dev_mgr_from_dev(pdev
);
1450 hub_reexamine_port_status_queue(pdev
, port_idx
, TRUE
);
1451 if (hub_remove_reset_event(pdev
, port_idx
, TRUE
))
1452 hub_start_next_reset_port(dev_mgr
, TRUE
);
1457 //caller should guarantee the validity of the dev
1459 hub_disable_port_request(PUSB_DEV pdev
, UCHAR port_idx
)
1462 PUSB_ENDPOINT pendp
;
1463 PHUB2_EXTENSION hub_ext
;
1464 PUSB_CTRL_SETUP_PACKET psetup
;
1467 USE_BASIC_NON_PENDING_IRQL
;
1469 if (pdev
== NULL
|| port_idx
== 0)
1470 return STATUS_INVALID_PARAMETER
;
1472 lock_dev(pdev
, FALSE
);
1473 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1475 unlock_dev(pdev
, FALSE
);
1476 return STATUS_DEVICE_DOES_NOT_EXIST
;
1479 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1482 unlock_dev(pdev
, FALSE
);
1483 return STATUS_NO_MEMORY
;
1486 RtlZeroMemory(purb
, sizeof(URB
));
1489 purb
->status
= STATUS_SUCCESS
;
1491 hub_ext
= hub_ext_from_dev(pdev
);
1493 purb
->data_buffer
= NULL
;
1494 purb
->data_length
= 0;
1496 pendp
= purb
->pendp
= &pdev
->default_endp
;
1499 purb
->completion
= hub_disable_port_completion
;
1500 purb
->context
= hub_ext
;
1503 purb
->reference
= 0;
1505 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1507 psetup
->bmRequestType
= 0x23; //host-device other recepient
1508 psetup
->bRequest
= USB_REQ_CLEAR_FEATURE
; //clear_feature
1509 psetup
->wValue
= USB_PORT_FEAT_ENABLE
;
1510 psetup
->wIndex
= (USHORT
) port_idx
;
1511 psetup
->wLength
= 0;
1514 //enter another state
1516 unlock_dev(pdev
, FALSE
);
1518 status
= hcd
->hcd_submit_urb(hcd
, pdev
, pendp
, purb
);
1519 if (status
== STATUS_PENDING
)
1528 hub_remove_reset_event(PUSB_DEV pdev
, ULONG port_idx
, BOOLEAN from_dpc
)
1530 PUSB_DEV_MANAGER dev_mgr
;
1531 PLIST_ENTRY pthis
, pnext
;
1532 PUSB_EVENT pevent
, pnext_event
;
1543 dev_mgr
= dev_mgr_from_dev(pdev
);
1547 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
1549 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
1551 ListFirst(&dev_mgr
->event_list
, pthis
);
1554 pevent
= (PUSB_EVENT
) pthis
;
1555 if (pevent
->event
== USB_EVENT_WAIT_RESET_PORT
&&
1556 (pevent
->flags
& USB_EVENT_FLAG_QUE_TYPE
) == USB_EVENT_FLAG_QUE_RESET
)
1558 if (pevent
->pdev
== pdev
&& pevent
->param
== port_idx
)
1561 RemoveEntryList(&pevent
->event_link
);
1562 pnext_event
= pevent
->pnext
;
1563 free_event(&dev_mgr
->event_pool
, pevent
);
1566 InsertHeadList(&dev_mgr
->event_list
, &pnext_event
->event_link
);
1572 ListNext(&dev_mgr
->event_list
, pthis
, pnext
);
1577 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1579 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1584 hub_start_next_reset_port(PUSB_DEV_MANAGER dev_mgr
, BOOLEAN from_dpc
)
1586 PLIST_ENTRY pthis
, pnext
;
1587 PUSB_EVENT pevent
, pnext_event
;
1588 PUSB_DEV pdev
= NULL
;
1589 PHUB2_EXTENSION hub_ext
;
1593 PUSB_CTRL_SETUP_PACKET psetup
;
1596 USE_NON_PENDING_IRQL
;
1598 if (dev_mgr
== NULL
)
1605 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
1607 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
1609 ListFirst(&dev_mgr
->event_list
, pthis
);
1611 while ((pevent
= (PUSB_EVENT
) pthis
))
1613 while (pevent
->event
== USB_EVENT_WAIT_RESET_PORT
&&
1614 (pevent
->flags
& USB_EVENT_FLAG_QUE_TYPE
) == USB_EVENT_FLAG_QUE_RESET
)
1619 pdev
= pevent
->pdev
;
1620 lock_dev(pdev
, TRUE
);
1622 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1624 unlock_dev(pdev
, TRUE
);
1625 pnext_event
= pevent
->pnext
;
1626 free_event(&dev_mgr
->event_pool
, pevent
);
1627 pevent
= pnext_event
;
1636 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1640 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1642 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1646 RtlZeroMemory(purb
, sizeof(URB
));
1648 purb
->data_buffer
= NULL
;
1649 purb
->data_length
= 0;
1650 purb
->pendp
= &pdev
->default_endp
;
1652 hub_ext
= hub_ext_from_dev(pdev
);
1653 purb
->context
= hub_ext
;
1655 purb
->completion
= hub_start_reset_port_completion
;
1656 purb
->reference
= pevent
->param
;
1658 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1660 psetup
->bmRequestType
= 0x23; //host-device other recepient
1661 psetup
->bRequest
= 3; //set_feature
1662 psetup
->wValue
= USB_PORT_FEAT_RESET
;
1663 psetup
->wIndex
= (USHORT
) pevent
->param
;
1664 psetup
->wLength
= 0;
1668 set_port_state(hub_ext
->port_status_queue
[pevent
->param
].port_flags
, STATE_WAIT_RESET_COMPLETE
);
1669 unlock_dev(pdev
, TRUE
);
1677 ListNext(&dev_mgr
->event_list
, pthis
, pnext
);
1685 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1687 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1689 if (processed
&& bret
)
1691 if (hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
) != STATUS_PENDING
)
1696 //do not know what to do
1707 //must have event-list-lock and dev-lock acquired
1710 hub_post_esq_event(PUSB_DEV pdev
, BYTE port_idx
, PROCESS_EVENT pe
)
1712 PUSB_DEV_MANAGER dev_mgr
;
1715 if (pdev
== NULL
|| port_idx
== 0 || pe
== NULL
)
1718 dev_mgr
= dev_mgr_from_dev(pdev
);
1720 pevent
= alloc_event(&dev_mgr
->event_pool
, 1);
1721 if (!pevent
) return;
1722 pevent
->event
= USB_EVENT_DEFAULT
;
1723 pevent
->process_queue
= event_list_default_process_queue
;
1724 pevent
->process_event
= pe
;
1725 pevent
->context
= (ULONG
) hub_ext_from_dev(pdev
);
1726 pevent
->param
= port_idx
;
1727 pevent
->flags
= USB_EVENT_FLAG_ACTIVE
;
1728 pevent
->pdev
= pdev
;
1729 pevent
->pnext
= NULL
;
1731 InsertTailList(&dev_mgr
->event_list
, &pevent
->event_link
);
1732 KeSetEvent(&dev_mgr
->wake_up_event
, 0, FALSE
);
1733 // usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_post_esq_event(): current element in event list is 0x%x\n",
1734 // dbg_count_list( &dev_mgr->event_list ) ) );
1738 // called only in hub_clear_port_feature_completion
1740 hub_check_reset_port_status(PUSB_DEV pdev
, LONG port_idx
)
1742 PUSB_DEV_MANAGER dev_mgr
;
1743 PHUB2_EXTENSION hub_ext
;
1745 USB_PORT_STATUS port_status
;
1750 PUSB_CTRL_SETUP_PACKET psetup
;
1753 USE_BASIC_NON_PENDING_IRQL
;
1755 //let's check whether the status change is a reset complete
1756 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_check_reset_port_status(): entering...\n"));
1757 dev_mgr
= dev_mgr_from_dev(pdev
);
1758 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->dev_list_lock
);
1759 lock_dev(pdev
, TRUE
);
1761 dev_mgr
= dev_mgr_from_dev(pdev
);
1764 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1766 unlock_dev(pdev
, TRUE
);
1767 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->dev_list_lock
);
1771 hub_ext
= hub_ext_from_dev(pdev
);
1772 port_status
= psq_peek(&hub_ext
->port_status_queue
[port_idx
], 0);
1775 if (port_status
.wPortChange
& USB_PORT_STAT_C_RESET
)
1782 && (port_state(hub_ext
->port_status_queue
[port_idx
].port_flags
) == STATE_WAIT_RESET_COMPLETE
)
1783 && (psq_count(&hub_ext
->port_status_queue
[port_idx
]) == 1))
1785 // a port-reset complete, empty the queue, keep the state
1786 psq_outqueue(&hub_ext
->port_status_queue
[port_idx
]);
1787 set_port_state(hub_ext
->port_status_queue
[port_idx
].port_flags
, STATE_WAIT_ADDRESSED
);
1789 //let's new a dev, and start the set-addr request
1790 if (hub_ext
->child_dev
[port_idx
] == 0)
1792 pdev2
= hub_ext
->child_dev
[port_idx
] = dev_mgr_alloc_device(dev_mgr
, hcd
);
1795 purb2
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
1798 dev_mgr_free_device(dev_mgr
, pdev2
);
1799 pdev2
= hub_ext
->child_dev
[port_idx
] = NULL
;
1803 if (port_status
.wPortStatus
& USB_PORT_STAT_LOW_SPEED
)
1805 pdev2
->flags
|= USB_DEV_FLAG_LOW_SPEED
;
1807 else if (port_status
.wPortStatus
& USB_PORT_STAT_HIGH_SPEED
)
1808 pdev2
->flags
|= USB_DEV_FLAG_HIGH_SPEED
;
1810 pdev2
->parent_dev
= pdev
;
1811 pdev2
->port_idx
= (UCHAR
) port_idx
;
1814 RtlZeroMemory(purb2
, sizeof(URB
));
1816 purb2
->pdev
= pdev2
;
1817 purb2
->pendp
= &pdev2
->default_endp
;
1818 purb2
->context
= hub_ext
;
1819 purb2
->completion
= hub_set_address_completion
;
1821 InitializeListHead(&purb2
->trasac_list
);
1822 purb2
->reference
= port_idx
;
1825 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb2
->setup_packet
;
1826 psetup
->bmRequestType
= 0;
1827 psetup
->bRequest
= USB_REQ_SET_ADDRESS
;
1828 psetup
->wValue
= pdev2
->dev_addr
;
1835 //creation success, emit the urb
1837 InsertTailList(&dev_mgr
->dev_list
, &pdev2
->dev_link
);
1839 unlock_dev(pdev
, TRUE
);
1840 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->dev_list_lock
);
1842 status
= hcd
->hcd_submit_urb(hcd
, pdev2
, purb2
->pendp
, purb2
);
1844 lock_dev(pdev2
, TRUE
);
1846 usb_dbg_print(DBGLVL_MAXIMUM
,
1847 ("hub_check_reset_port_status(): new dev ref_count=0x%x\n", pdev2
->ref_count
));
1848 unlock_dev(pdev2
, TRUE
);
1850 if (status
!= STATUS_PENDING
)
1852 usb_free_mem(purb2
);
1853 //??? do we need to lock it for SMP?
1854 //dev_mgr_free_device( dev_mgr, pdev2 ), let dev_mgr_thread to clean it;
1856 if (hub_disable_port_request(pdev
, (UCHAR
) port_idx
) != STATUS_PENDING
)
1857 goto LBL_RESET_FAIL
;
1865 usb_dbg_print(DBGLVL_MAXIMUM
, ("hub_check_reset_port_status(): not a correct reset status\n"));
1867 unlock_dev(pdev
, TRUE
);
1868 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->dev_list_lock
);
1871 //Any event other than reset cause the reset process stall and another
1872 //pending reset-port requeset is serviced
1873 hub_reexamine_port_status_queue(pdev
, port_idx
, TRUE
);
1874 if (hub_remove_reset_event(pdev
, port_idx
, TRUE
))
1875 hub_start_next_reset_port(dev_mgr
, TRUE
);
1881 hub_reexamine_port_status_queue(PUSB_DEV hub_dev
, ULONG port_idx
, BOOLEAN from_dpc
)
1884 PHUB2_EXTENSION hub_ext
;
1885 PUSB_DEV_MANAGER dev_mgr
;
1887 USE_NON_PENDING_IRQL
;
1889 if (hub_dev
== NULL
|| port_idx
== 0)
1892 dev_mgr
= dev_mgr_from_dev(hub_dev
);
1894 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
1896 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
1898 lock_dev(hub_dev
, TRUE
);
1899 if (dev_state(hub_dev
) != USB_DEV_STATE_ZOMB
)
1902 hub_ext
= hub_ext_from_dev(hub_dev
);
1903 if (psq_is_empty(&hub_ext
->port_status_queue
[port_idx
]))
1905 set_port_state(hub_ext
->port_status_queue
[port_idx
].port_flags
, STATE_IDLE
);
1910 set_port_state(hub_ext
->port_status_queue
[port_idx
].port_flags
, STATE_EXAMINE_STATUS_QUE
);
1912 hub_post_esq_event(hub_dev
, (UCHAR
) port_idx
, hub_event_examine_status_que
);
1915 unlock_dev(hub_dev
, TRUE
);
1918 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
1920 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
1925 hub_connect(PDEV_CONNECT_DATA param
, DEV_HANDLE dev_handle
)
1929 DEV_HANDLE endp_handle
;
1930 USB_DEVICE_DESC dev_desc
;
1931 PUSB_CONFIGURATION_DESC pcfg_desc
;
1932 PUSB_INTERFACE_DESC pif_desc
;
1933 PUSB_CTRL_SETUP_PACKET psetup
;
1935 LONG i
, j
, found
, cfg_val
= 0;
1936 PUSB_DEV_MANAGER dev_mgr
;
1940 if (param
== NULL
|| dev_handle
== 0)
1943 dev_mgr
= param
->dev_mgr
;
1945 pcfg_desc
= (PUSB_CONFIGURATION_DESC
) buf
;
1946 endp_handle
= dev_handle
| 0xffff;
1947 UsbBuildGetDescriptorRequest(&urb
,
1949 USB_DT_DEVICE
, 0, 0, (&dev_desc
), (sizeof(USB_DEVICE_DESC
)), NULL
, 0, 0);
1951 status
= usb_submit_urb(dev_mgr
, &urb
);
1952 if (status
!= STATUS_SUCCESS
)
1956 for(i
= 0; i
< dev_desc
.bNumConfigurations
; i
++)
1958 UsbBuildGetDescriptorRequest(&urb
, endp_handle
, USB_DT_CONFIG
, (USHORT
) i
, 0, buf
, 512, NULL
, 0, 0);
1960 status
= usb_submit_urb(dev_mgr
, &urb
);
1961 if (status
!= STATUS_SUCCESS
)
1966 status
= usb_query_and_lock_dev(dev_mgr
, dev_handle
, &pdev
);
1967 if (status
!= STATUS_SUCCESS
)
1970 pif_desc
= (PUSB_INTERFACE_DESC
) & buf
[sizeof(USB_CONFIGURATION_DESC
)];
1971 for(j
= 0; j
< pcfg_desc
->bNumInterfaces
; j
++)
1973 if (pif_desc
->bInterfaceClass
== USB_CLASS_HUB
1974 && pif_desc
->bInterfaceSubClass
== 0 && pif_desc
->bNumEndpoints
== 1)
1976 if ((pif_desc
->bInterfaceProtocol
> 0 && pif_desc
->bInterfaceProtocol
< 3)
1977 || (pif_desc
->bInterfaceProtocol
== 0 && pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
)
1978 || (pif_desc
->bInterfaceProtocol
== 0 && !usb2(pdev
->hcd
)))
1981 cfg_val
= pcfg_desc
->bConfigurationValue
;
1985 if (usb_skip_if_and_altif((PBYTE
*) & pif_desc
) == FALSE
)
1990 usb_unlock_dev(pdev
);
1995 if (usb_skip_one_config((PBYTE
*) & pcfg_desc
) == FALSE
)
2003 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
2007 psetup
= (PUSB_CTRL_SETUP_PACKET
) (purb
)->setup_packet
;
2010 purb
->endp_handle
= endp_handle
;
2011 purb
->data_buffer
= NULL
;
2012 purb
->data_length
= 0;
2013 purb
->completion
= hub_set_cfg_completion
;
2014 purb
->context
= dev_mgr
;
2015 purb
->reference
= (LONG
) param
->pdriver
;
2016 psetup
->bmRequestType
= 0;
2017 psetup
->bRequest
= USB_REQ_SET_CONFIGURATION
;
2018 psetup
->wValue
= (USHORT
) cfg_val
;
2020 psetup
->wLength
= 0;
2022 status
= usb_submit_urb(dev_mgr
, purb
);
2023 if (status
!= STATUS_PENDING
)
2034 VOID
hub_set_interface_completion(PURB purb
, PVOID pcontext
);
2037 hub_set_cfg_completion(PURB purb
, PVOID pcontext
)
2039 PUSB_DEV_MANAGER dev_mgr
;
2040 PUSB_DRIVER pdriver
;
2041 ULONG endp_handle
, dev_handle
;
2042 PUSB_CTRL_SETUP_PACKET psetup
;
2046 BOOLEAN high_speed
, multiple_tt
;
2048 USE_BASIC_NON_PENDING_IRQL
;
2050 if (purb
== NULL
|| pcontext
== NULL
)
2054 dev_mgr
= (PUSB_DEV_MANAGER
) pcontext
;
2055 endp_handle
= purb
->endp_handle
;
2056 dev_handle
= endp_handle
& 0xffff0000;
2057 pdriver
= (PUSB_DRIVER
) purb
->reference
;
2059 multiple_tt
= FALSE
;
2061 if (purb
->status
!= STATUS_SUCCESS
)
2066 status
= usb_query_and_lock_dev(dev_mgr
, purb
->endp_handle
, &pdev
);
2067 if (status
!= STATUS_SUCCESS
)
2069 usb_unlock_dev(pdev
);
2072 lock_dev(pdev
, TRUE
);
2073 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2075 unlock_dev(pdev
, TRUE
);
2076 usb_unlock_dev(pdev
);
2079 if (pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
)
2082 hub_if_from_dev(pdev
, pif
);
2083 if (pif
->altif_count
)
2086 if_idx
= pif
- &pdev
->usb_config
->interf
[0];
2089 unlock_dev(pdev
, TRUE
);
2090 usb_unlock_dev(pdev
);
2092 if (!high_speed
|| !multiple_tt
)
2094 hub_set_interface_completion(purb
, pcontext
);
2098 psetup
= (PUSB_CTRL_SETUP_PACKET
) (purb
)->setup_packet
;
2101 // set the mult-tt if exist
2102 purb
->endp_handle
= endp_handle
;
2103 purb
->data_buffer
= NULL
;
2104 purb
->data_length
= 0;
2105 purb
->completion
= hub_set_interface_completion
;
2106 purb
->context
= dev_mgr
;
2107 purb
->reference
= (LONG
) pdriver
;
2108 psetup
->bmRequestType
= 0;
2109 psetup
->bRequest
= USB_REQ_SET_INTERFACE
;
2110 psetup
->wValue
= (USHORT
) 1; // alternate tt
2111 psetup
->wIndex
= if_idx
; // if index
2112 psetup
->wLength
= 0;
2114 status
= usb_submit_urb(dev_mgr
, purb
);
2115 if (status
== STATUS_PENDING
)
2125 hub_set_interface_completion(PURB purb
, PVOID pcontext
)
2128 PUSB_CTRL_SETUP_PACKET psetup
;
2129 PUSB_DEV_MANAGER dev_mgr
;
2131 DEV_HANDLE endp_handle
;
2132 PUSB_DRIVER pdriver
;
2134 if (purb
== NULL
|| pcontext
== NULL
)
2138 dev_mgr
= (PUSB_DEV_MANAGER
) pcontext
;
2139 endp_handle
= purb
->endp_handle
;
2140 pdriver
= (PUSB_DRIVER
) purb
->reference
;
2142 if (purb
->status
!= STATUS_SUCCESS
)
2148 dev_ext
= usb_alloc_mem(NonPagedPool
, sizeof(HUB2_EXTENSION
));
2149 if (dev_ext
== NULL
)
2155 //acquire hub descriptor
2157 RtlZeroMemory(dev_ext
, sizeof(HUB2_EXTENSION
));
2160 purb
->data_buffer
= (PUCHAR
) & ((HUB2_EXTENSION
*) dev_ext
)->hub_desc
;
2161 purb
->endp_handle
= endp_handle
;
2162 purb
->data_length
= sizeof(USB_HUB_DESCRIPTOR
);
2163 purb
->completion
= hub_get_hub_desc_completion
;
2164 purb
->context
= (PVOID
) dev_mgr
;
2165 purb
->reference
= (ULONG
) dev_ext
;
2166 purb
->pirp
= (PIRP
) pdriver
;
2168 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2169 psetup
->bmRequestType
= 0xa0;
2170 psetup
->bRequest
= USB_REQ_GET_DESCRIPTOR
;
2171 psetup
->wValue
= (0x29 << 8);
2172 psetup
->wLength
= sizeof(USB_HUB_DESCRIPTOR
);
2173 status
= usb_submit_urb(dev_mgr
, purb
);
2175 if (status
!= STATUS_PENDING
)
2177 usb_free_mem(dev_ext
);
2183 //clear the dev_driver fields in the dev.
2190 hub_power_on_port_completion(PURB purb
, PVOID pcontext
)
2192 PUSB_DEV_MANAGER dev_mgr
;
2196 if (pcontext
== NULL
)
2199 dev_mgr
= (PUSB_DEV_MANAGER
) pcontext
;
2201 if (purb
->status
!= STATUS_SUCCESS
)
2203 usb_dbg_print(DBGLVL_MAXIMUM
,
2204 ("hub_power_on_port_completion(): port%d power on failed\n", purb
->reference
));
2208 usb_dbg_print(DBGLVL_MAXIMUM
,
2209 ("hub_power_on_port_completion(): port%d power on succeed\n", purb
->reference
));
2218 hub_power_on_port(PUSB_DEV pdev
, UCHAR port_idx
)
2221 PUSB_CTRL_SETUP_PACKET psetup
;
2222 PUSB_DEV_MANAGER dev_mgr
;
2226 USE_BASIC_NON_PENDING_IRQL
;
2227 if (pdev
== NULL
|| port_idx
== 0)
2228 return STATUS_INVALID_PARAMETER
;
2230 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
2232 return STATUS_NO_MEMORY
;
2236 lock_dev(pdev
, FALSE
);
2237 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2239 unlock_dev(pdev
, FALSE
);
2240 status
= STATUS_DEVICE_DOES_NOT_EXIST
;
2243 dev_mgr
= dev_mgr_from_dev(pdev
);
2246 purb
->completion
= hub_power_on_port_completion
;
2247 purb
->context
= (PVOID
) dev_mgr
;
2248 purb
->reference
= (ULONG
) port_idx
;
2250 purb
->pendp
= &pdev
->default_endp
;
2252 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2253 psetup
->bmRequestType
= 0x23;
2254 psetup
->bRequest
= USB_REQ_SET_FEATURE
;
2255 psetup
->wValue
= USB_PORT_FEAT_POWER
;
2256 psetup
->wIndex
= (WORD
) port_idx
;
2257 psetup
->wLength
= 0;
2259 unlock_dev(pdev
, FALSE
);
2261 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
2263 if (status
!= STATUS_PENDING
)
2267 return STATUS_PENDING
;
2275 hub_get_hub_desc_completion(PURB purb
, PVOID pcontext
)
2277 PUSB_DEV_MANAGER dev_mgr
;
2278 PHUB2_EXTENSION hub_ext
;
2281 PUSB_INTERFACE pif
= NULL
;
2284 PUSB_DRIVER pdriver
;
2285 DEV_HANDLE dev_handle
;
2287 USE_BASIC_NON_PENDING_IRQL
;
2294 dev_mgr
= (PUSB_DEV_MANAGER
) pcontext
;
2295 hub_ext
= (PHUB2_EXTENSION
) purb
->reference
;
2296 pdriver
= (PUSB_DRIVER
) purb
->pirp
;
2297 dev_handle
= purb
->endp_handle
& 0xffff0000;
2299 if (pcontext
== NULL
|| purb
->reference
== 0)
2302 if (purb
->status
!= STATUS_SUCCESS
)
2307 // obtain the pointer to the dev
2308 status
= usb_query_and_lock_dev(dev_mgr
, purb
->endp_handle
, &pdev
);
2309 if (status
!= STATUS_SUCCESS
)
2311 usb_unlock_dev(pdev
);
2314 // safe to release the pdev ref since we are in urb completion
2315 usb_unlock_dev(pdev
);
2317 lock_dev(pdev
, TRUE
);
2318 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
||
2319 dev_mgr_set_driver(dev_mgr
, dev_handle
, pdriver
, pdev
) == FALSE
)
2321 unlock_dev(pdev
, TRUE
);
2325 //transit the state to configured
2326 pdev
->flags
&= ~USB_DEV_STATE_MASK
;
2327 pdev
->flags
|= USB_DEV_STATE_CONFIGURED
;
2329 pdev
->dev_ext
= (PBYTE
) hub_ext
;
2330 pdev
->dev_ext_size
= sizeof(HUB2_EXTENSION
);
2332 port_count
= hub_ext
->port_count
= hub_ext
->hub_desc
.bNbrPorts
;
2333 hub_ext
->pdev
= pdev
;
2334 for(i
= 0; i
< pdev
->usb_config
->if_count
; i
++)
2336 pif
= &pdev
->usb_config
->interf
[i
];
2337 if (pif
->pusb_if_desc
->bInterfaceClass
== USB_CLASS_HUB
2338 && pif
->pusb_if_desc
->bInterfaceSubClass
== 0
2339 && pif
->pusb_if_desc
->bInterfaceProtocol
< 3 && pif
->pusb_if_desc
->bNumEndpoints
== 1)
2345 for(i
= 0; i
< MAX_HUB_PORTS
+ 1; i
++)
2347 psq_init((PPORT_STATUS_QUEUE
) hub_ext
->port_status_queue
);
2350 hub_ext
->multiple_tt
= (pif
->pusb_if_desc
->bInterfaceProtocol
== 2);
2352 unlock_dev(pdev
, TRUE
);
2355 hub_start_int_request(pdev
);
2357 for(i
= 0; i
< port_count
; i
++)
2359 hub_power_on_port(pdev
, (UCHAR
) (i
+ 1));
2368 usb_free_mem(hub_ext
);
2373 hub_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
2375 UNREFERENCED_PARAMETER(dev_mgr
);
2376 UNREFERENCED_PARAMETER(dev_handle
);
2381 hub_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
2384 //special use of usb_query and lock dev
2385 if (usb_query_and_lock_dev(dev_mgr
, dev_handle
, &pdev
) != STATUS_SUCCESS
)
2387 //will never be success, since the dev is already in zomb state
2388 //at this point, the dev is valid, ref_count is of none use,
2389 //no need to lock it
2392 usb_free_mem(pdev
->dev_ext
);
2400 hub_lock_unlock_tt(PUSB_DEV pdev
, UCHAR port_idx
, UCHAR type
, BOOLEAN lock
)
2402 PHUB2_EXTENSION dev_ext
;
2405 USE_BASIC_NON_PENDING_IRQL
;
2407 if (pdev
== NULL
|| port_idx
> 127)
2410 lock_dev(pdev
, FALSE
);
2411 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2413 unlock_dev(pdev
, FALSE
);
2417 dev_ext
= hub_ext_from_dev(pdev
);
2418 if (dev_ext
== NULL
)
2420 unlock_dev(pdev
, FALSE
);
2423 if (type
== USB_ENDPOINT_XFER_INT
|| type
== USB_ENDPOINT_XFER_ISOC
)
2425 pmap
= dev_ext
->tt_status_map
;
2427 else if (type
== USB_ENDPOINT_XFER_BULK
|| type
== USB_ENDPOINT_XFER_CONTROL
)
2429 pmap
= dev_ext
->tt_bulk_map
;
2434 if (pmap
[port_idx
>> 5] & (1 << port_idx
))
2436 unlock_dev(pdev
, FALSE
);
2439 pmap
[port_idx
>> 5] |= (1 << port_idx
);
2443 pmap
[port_idx
>> 5] &= ~(1 << port_idx
);
2446 unlock_dev(pdev
, FALSE
);
2451 hub_lock_tt(PUSB_DEV pdev
,
2453 UCHAR type
// transfer type
2456 return hub_lock_unlock_tt(pdev
, port_idx
, type
, TRUE
);
2460 hub_unlock_tt(PUSB_DEV pdev
, UCHAR port_idx
, UCHAR type
)
2462 return hub_lock_unlock_tt(pdev
, port_idx
, type
, FALSE
);
2466 hub_clear_tt_buffer_completion(PURB purb
, PVOID context
)
2468 PUSB_CTRL_SETUP_PACKET psetup
;
2469 PURB_HS_PIPE_CONTENT pipe_content
;
2470 PHUB2_EXTENSION hub_ext
;
2473 if (purb
== NULL
|| context
== NULL
)
2476 hub_ext
= (PHUB2_EXTENSION
) context
;
2477 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2478 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->reference
;
2479 hub_unlock_tt(purb
->pdev
, (UCHAR
) psetup
->wIndex
, (UCHAR
) pipe_content
->trans_type
);
2482 hcd
= hub_ext
->pdev
->hcd
;
2484 // let those blocked urbs ( sharing the same tt )have chance to be scheduled
2485 if (hcd
&& usb2(hcd
))
2486 hcd
->hcd_submit_urb(hcd
, NULL
, NULL
, NULL
);
2491 // send CLEAR_TT_BUFFER to the hub
2493 hub_clear_tt_buffer(PUSB_DEV pdev
, URB_HS_PIPE_CONTENT pipe_content
, UCHAR port_idx
)
2496 PUSB_CTRL_SETUP_PACKET psetup
;
2497 PHUB2_EXTENSION hub_ext
;
2500 USE_BASIC_NON_PENDING_IRQL
;
2505 if (pipe_content
.speed_high
)
2508 lock_dev(pdev
, FALSE
);
2509 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2511 unlock_dev(pdev
, FALSE
);
2515 hub_ext
= hub_ext_from_dev(pdev
);
2516 if (hub_ext
== NULL
)
2518 unlock_dev(pdev
, FALSE
);
2521 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
2525 unlock_dev(pdev
, FALSE
);
2529 RtlZeroMemory(purb
, sizeof(URB
));
2532 purb
->status
= STATUS_SUCCESS
;
2533 purb
->data_buffer
= NULL
;
2534 purb
->data_length
= 0; // ( hub_ext->port_count + 7 ) / 8;
2536 // hub_if_from_dev( pdev, pif );
2537 purb
->pendp
= &pdev
->default_endp
;
2540 purb
->completion
= hub_clear_tt_buffer_completion
;
2541 purb
->context
= hub_ext
;
2542 purb
->reference
= *((PLONG
) & pipe_content
);
2547 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2548 psetup
->bmRequestType
= 0x23; //host-device class other recepient
2549 psetup
->bRequest
= HUB_REQ_CLEAR_TT_BUFFER
;
2550 psetup
->wValue
= (USHORT
) ((pipe_content
.endp_addr
) | (pipe_content
.dev_addr
<< 4) |
2551 (pipe_content
.trans_type
<< 10) | (pipe_content
.trans_dir
<< 15));
2553 if (hub_ext
->multiple_tt
)
2555 psetup
->wIndex
= (USHORT
) port_idx
;
2560 psetup
->wLength
= 0;
2561 unlock_dev(pdev
, FALSE
);
2563 status
= hcd
->hcd_submit_urb(hcd
, pdev
, purb
->pendp
, purb
);
2564 if (status
!= STATUS_PENDING
)
2574 hub_event_clear_tt_buffer(PUSB_DEV pdev
, //always null. we do not use this param
2579 UNREFERENCED_PARAMETER(event
);
2580 hub_clear_tt_buffer(pdev
, *((PURB_HS_PIPE_CONTENT
) & context
), (UCHAR
) param
);
2585 hub_post_clear_tt_event(PUSB_DEV pdev
, BYTE port_idx
, ULONG pipe
)
2587 PUSB_DEV_MANAGER dev_mgr
;
2589 USE_NON_PENDING_IRQL
;
2591 dev_mgr
= dev_mgr_from_dev(pdev
);
2593 KeAcquireSpinLock(&dev_mgr
->event_list_lock
, &old_irql
);
2594 lock_dev(pdev
, TRUE
);
2595 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2597 unlock_dev(pdev
, TRUE
);
2598 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
2601 pevent
= alloc_event(&dev_mgr
->event_pool
, 1);
2604 unlock_dev(pdev
, TRUE
);
2605 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
2610 pevent
->event
= USB_EVENT_WAIT_RESET_PORT
;
2611 pevent
->pdev
= pdev
;
2612 pevent
->context
= pipe
;
2613 pevent
->param
= port_idx
;
2614 pevent
->flags
= USB_EVENT_FLAG_ACTIVE
;
2615 pevent
->process_queue
= event_list_default_process_queue
;
2616 pevent
->process_event
= hub_event_clear_tt_buffer
;
2617 pevent
->pnext
= NULL
;
2618 InsertTailList(&dev_mgr
->event_list
, &pevent
->event_link
);
2620 unlock_dev(pdev
, TRUE
);
2621 KeReleaseSpinLock(&dev_mgr
->event_list_lock
, old_irql
);
2623 KeSetEvent(&dev_mgr
->wake_up_event
, 0, FALSE
);
2628 init_irp_list(PIRP_LIST irp_list
)
2631 KeInitializeSpinLock(&irp_list
->irp_list_lock
);
2632 InitializeListHead(&irp_list
->irp_busy_list
);
2633 InitializeListHead(&irp_list
->irp_free_list
);
2634 irp_list
->irp_list_element_array
=
2635 usb_alloc_mem(NonPagedPool
, sizeof(IRP_LIST_ELEMENT
) * MAX_IRP_LIST_SIZE
);
2637 if (irp_list
->irp_list_element_array
== NULL
)
2640 RtlZeroMemory(irp_list
->irp_list_element_array
, sizeof(IRP_LIST_ELEMENT
) * MAX_IRP_LIST_SIZE
);
2641 for(i
= 0; i
< MAX_IRP_LIST_SIZE
; i
++)
2643 InsertTailList(&irp_list
->irp_free_list
, &irp_list
->irp_list_element_array
[i
].irp_link
);
2645 irp_list
->irp_free_list_count
= MAX_IRP_LIST_SIZE
;
2650 destroy_irp_list(PIRP_LIST irp_list
)
2652 InitializeListHead(&irp_list
->irp_busy_list
);
2653 InitializeListHead(&irp_list
->irp_free_list
);
2654 usb_free_mem(irp_list
->irp_list_element_array
);
2655 irp_list
->irp_list_element_array
= NULL
;
2656 irp_list
->irp_free_list_count
= 0;
2661 add_irp_to_list(PIRP_LIST irp_list
, PIRP pirp
, PURB purb
)
2664 PIRP_LIST_ELEMENT pile
;
2666 if (irp_list
== NULL
|| pirp
== NULL
|| purb
== NULL
)
2669 IoAcquireCancelSpinLock(&old_irql
);
2670 KeAcquireSpinLockAtDpcLevel(&irp_list
->irp_list_lock
);
2672 if (irp_list
->irp_free_list_count
== 0)
2674 KeReleaseSpinLockFromDpcLevel(&irp_list
->irp_list_lock
);
2675 IoReleaseCancelSpinLock(old_irql
);
2678 pile
= (PIRP_LIST_ELEMENT
) RemoveHeadList(&irp_list
->irp_free_list
);
2683 irp_list
->irp_free_list_count
--;
2684 InsertTailList(&irp_list
->irp_busy_list
, &pile
->irp_link
);
2685 (void)IoSetCancelRoutine(pirp
, dev_mgr_cancel_irp
);
2687 KeReleaseSpinLockFromDpcLevel(&irp_list
->irp_list_lock
);
2688 IoReleaseCancelSpinLock(old_irql
);
2693 remove_irp_from_list(PIRP_LIST irp_list
,
2695 PUSB_DEV_MANAGER dev_mgr
//if dev_mgr is not NULL, the urb needs to be canceled
2698 PIRP_LIST_ELEMENT pile
;
2699 PLIST_ENTRY pthis
, pnext
;
2701 DEV_HANDLE endp_handle
;
2703 PUSB_ENDPOINT pendp
;
2706 USE_NON_PENDING_IRQL
;
2708 if (irp_list
== NULL
|| pirp
== NULL
)
2711 KeAcquireSpinLock(&irp_list
->irp_list_lock
, &old_irql
);
2713 if (irp_list
->irp_free_list_count
== MAX_IRP_LIST_SIZE
)
2715 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);
2720 ListFirst(&irp_list
->irp_busy_list
, pthis
);
2723 pile
= struct_ptr(pthis
, IRP_LIST_ELEMENT
, irp_link
);
2724 if (pile
->pirp
== pirp
)
2729 RemoveEntryList(pthis
);
2730 InsertTailList(&irp_list
->irp_free_list
, pthis
);
2731 irp_list
->irp_free_list_count
++;
2734 ListNext(&irp_list
->irp_busy_list
, pthis
, pnext
);
2741 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);
2745 endp_handle
= purb
->endp_handle
;
2746 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);
2750 // indicate we needs to cancel the urb, this condition happens only in cancel routine
2751 // we should notice that even the hcd_cancel_urb is called, the irp may not be canceled
2752 // if the urb does not exist in any queue of the host controller driver, indicating
2753 // it is being processed by dpc. Thus, the dpc will certainly prevent the irp in
2754 // completion from being canceled at the same time. On the other hand, if the
2755 // hcd_cancel_urb succeeds, it either directly complete the irp or queue the dpc for
2756 // irp completion. So, there won't be two simutaneous threads processing the same
2759 if (usb_query_and_lock_dev(dev_mgr
, endp_handle
, &pdev
) != STATUS_SUCCESS
)
2762 lock_dev(pdev
, TRUE
);
2763 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2765 unlock_dev(pdev
, FALSE
);
2766 usb_unlock_dev(pdev
);
2771 endp_from_handle(pdev
, endp_handle
, pendp
);
2772 unlock_dev(pdev
, TRUE
);
2773 hcd
->hcd_cancel_urb(hcd
, pdev
, pendp
, purb
);
2774 usb_unlock_dev(pdev
);
2781 irp_list_empty(PIRP_LIST irp_list
)
2785 KeAcquireSpinLock(&irp_list
->irp_list_lock
, &old_irql
);
2786 ret
= (BOOLEAN
) (irp_list
->irp_free_list_count
== MAX_IRP_LIST_SIZE
);
2787 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);
2792 irp_list_full(PIRP_LIST irp_list
)
2796 KeAcquireSpinLock(&irp_list
->irp_list_lock
, &old_irql
);
2797 ret
= (BOOLEAN
) (irp_list
->irp_free_list_count
== 0);
2798 KeReleaseSpinLock(&irp_list
->irp_list_lock
, old_irql
);