10 #include <ntstrsafe.h>
17 #include <drivers/usbport/usbmport.h>
19 #define USB_HUB_TAG 'BUHU'
21 #define USBH_EXTENSION_TYPE_HUB 0x01
22 #define USBH_EXTENSION_TYPE_PORT 0x02
23 #define USBH_EXTENSION_TYPE_PARENT 0x04
24 #define USBH_EXTENSION_TYPE_FUNCTION 0x08
26 #define USBHUB_FDO_FLAG_DEVICE_STARTED (1 << 0)
27 #define USBHUB_FDO_FLAG_DEVICE_STOPPING (1 << 2)
28 #define USBHUB_FDO_FLAG_DEVICE_FAILED (1 << 3)
29 #define USBHUB_FDO_FLAG_REMOTE_WAKEUP (1 << 4)
30 #define USBHUB_FDO_FLAG_DEVICE_STOPPED (1 << 5)
31 #define USBHUB_FDO_FLAG_HUB_BUSY (1 << 6)
32 #define USBHUB_FDO_FLAG_PENDING_WAKE_IRP (1 << 7)
33 #define USBHUB_FDO_FLAG_RESET_PORT_LOCK (1 << 8)
34 #define USBHUB_FDO_FLAG_ESD_RECOVERING (1 << 9)
35 #define USBHUB_FDO_FLAG_SET_D0_STATE (1 << 10)
36 #define USBHUB_FDO_FLAG_NOT_D0_STATE (1 << 11)
37 #define USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST (1 << 12)
38 #define USBHUB_FDO_FLAG_STATE_CHANGING (1 << 13)
39 #define USBHUB_FDO_FLAG_DEVICE_REMOVED (1 << 14)
40 #define USBHUB_FDO_FLAG_USB20_HUB (1 << 15)
41 #define USBHUB_FDO_FLAG_DEFER_CHECK_IDLE (1 << 16)
42 #define USBHUB_FDO_FLAG_WAKEUP_START (1 << 17)
43 #define USBHUB_FDO_FLAG_MULTIPLE_TTS (1 << 18) // High-speed Operating Hub with Multiple TTs
44 #define USBHUB_FDO_FLAG_ENUM_POST_RECOVER (1 << 19)
45 #define USBHUB_FDO_FLAG_DO_ENUMERATION (1 << 20)
46 #define USBHUB_FDO_FLAG_CHECK_IDLE_LOCK (1 << 21)
47 #define USBHUB_FDO_FLAG_HIBERNATE_STATE (1 << 22)
48 #define USBHUB_FDO_FLAG_NOT_ENUMERATED (1 << 23)
49 #define USBHUB_FDO_FLAG_DO_SUSPENSE (1 << 24)
50 #define USBHUB_FDO_FLAG_GOING_IDLE (1 << 25)
51 #define USBHUB_FDO_FLAG_DEVICE_SUSPENDED (1 << 26)
52 #define USBHUB_FDO_FLAG_WITEM_INIT (1 << 27)
54 #define USBHUB_PDO_FLAG_HUB_DEVICE (1 << 0)
55 #define USBHUB_PDO_FLAG_MULTI_INTERFACE (1 << 1)
56 #define USBHUB_PDO_FLAG_INIT_PORT_FAILED (1 << 2)
57 #define USBHUB_PDO_FLAG_PORT_LOW_SPEED (1 << 3)
58 #define USBHUB_PDO_FLAG_REMOTE_WAKEUP (1 << 4)
59 #define USBHUB_PDO_FLAG_WAIT_WAKE (1 << 5)
60 #define USBHUB_PDO_FLAG_NOT_CONNECTED (1 << 6)
61 #define USBHUB_PDO_FLAG_DELETE_PENDING (1 << 7)
62 #define USBHUB_PDO_FLAG_POWER_D3 (1 << 8)
63 #define USBHUB_PDO_FLAG_DEVICE_STARTED (1 << 9)
64 #define USBHUB_PDO_FLAG_HS_USB1_DUALMODE (1 << 10)
65 #define USBHUB_PDO_FLAG_REG_DEV_INTERFACE (1 << 11) // SymbolicLink
66 #define USBHUB_PDO_FLAG_PORT_RESTORE_FAIL (1 << 12)
67 #define USBHUB_PDO_FLAG_POWER_D1_OR_D2 (1 << 13)
68 #define USBHUB_PDO_FLAG_OVERCURRENT_PORT (1 << 14)
69 #define USBHUB_PDO_FLAG_REMOVING_PORT_PDO (1 << 15)
70 #define USBHUB_PDO_FLAG_INSUFFICIENT_PWR (1 << 16)
71 #define USBHUB_PDO_FLAG_ALLOC_BNDW_FAILED (1 << 18)
72 #define USBHUB_PDO_FLAG_PORT_RESSETING (1 << 19)
73 #define USBHUB_PDO_FLAG_IDLE_NOTIFICATION (1 << 22)
74 #define USBHUB_PDO_FLAG_PORT_HIGH_SPEED (1 << 23)
75 #define USBHUB_PDO_FLAG_ENUMERATED (1 << 26)
77 #define USBHUB_ENUM_FLAG_DEVICE_PRESENT 0x01
78 #define USBHUB_ENUM_FLAG_GHOST_DEVICE 0x02
80 /* Hub Class Feature Selectors */
81 #define USBHUB_FEATURE_USBHUB_FEATURE_C_HUB_LOCAL_POWER 0
82 #define USBHUB_FEATURE_C_HUB_OVER_CURRENT 1
84 #define USBHUB_FEATURE_PORT_CONNECTION 0
85 #define USBHUB_FEATURE_PORT_ENABLE 1
86 #define USBHUB_FEATURE_PORT_SUSPEND 2
87 #define USBHUB_FEATURE_PORT_OVER_CURRENT 3
88 #define USBHUB_FEATURE_PORT_RESET 4
89 #define USBHUB_FEATURE_PORT_POWER 8
90 #define USBHUB_FEATURE_PORT_LOW_SPEED 9
91 #define USBHUB_FEATURE_C_PORT_CONNECTION 16
92 #define USBHUB_FEATURE_C_PORT_ENABLE 17
93 #define USBHUB_FEATURE_C_PORT_SUSPEND 18
94 #define USBHUB_FEATURE_C_PORT_OVER_CURRENT 19
95 #define USBHUB_FEATURE_C_PORT_RESET 20
96 #define USBHUB_FEATURE_PORT_TEST 21
97 #define USBHUB_FEATURE_PORT_INDICATOR 22
99 #define USBHUB_MAX_CASCADE_LEVELS 6
100 #define USBHUB_RESET_PORT_MAX_RETRY 3
101 #define USBHUB_MAX_REQUEST_ERRORS 3
104 #define USBHUB_FAIL_NO_FAIL 5
105 #define USBHUB_FAIL_NESTED_TOO_DEEPLY 6
106 #define USBHUB_FAIL_OVERCURRENT 7
108 extern PWSTR GenericUSBDeviceString
;
110 typedef struct _USBHUB_PORT_DATA
{
111 USB_PORT_STATUS_AND_CHANGE PortStatus
;
112 PDEVICE_OBJECT DeviceObject
;
113 USB_CONNECTION_STATUS ConnectionStatus
;
114 ULONG PortAttributes
;
115 } USBHUB_PORT_DATA
, *PUSBHUB_PORT_DATA
;
117 typedef struct _USBHUB_FDO_EXTENSION
*PUSBHUB_FDO_EXTENSION
;
120 (NTAPI
* PUSBHUB_WORKER_ROUTINE
)(
121 IN PUSBHUB_FDO_EXTENSION HubExtension
,
124 typedef struct _USBHUB_IO_WORK_ITEM
{
126 LIST_ENTRY HubWorkItemLink
;
127 LONG HubWorkerQueued
;
128 PIO_WORKITEM HubWorkItem
;
129 WORK_QUEUE_TYPE HubWorkItemType
;
130 PUSBHUB_FDO_EXTENSION HubExtension
;
131 PUSBHUB_WORKER_ROUTINE HubWorkerRoutine
;
132 PVOID HubWorkItemBuffer
;
133 } USBHUB_IO_WORK_ITEM
, *PUSBHUB_IO_WORK_ITEM
;
135 typedef struct _COMMON_DEVICE_EXTENSION
{
137 PDEVICE_OBJECT SelfDevice
;
138 } COMMON_DEVICE_EXTENSION
, *PCOMMON_DEVICE_EXTENSION
;
140 typedef struct _USBHUB_FDO_EXTENSION
{
141 COMMON_DEVICE_EXTENSION Common
;
142 PDEVICE_OBJECT LowerPDO
;
143 PDEVICE_OBJECT LowerDevice
;
144 PDEVICE_OBJECT RootHubPdo
;
145 PDEVICE_OBJECT RootHubPdo2
;
146 KEVENT LowerDeviceEvent
;
148 USB_BUS_INTERFACE_HUB_V5 BusInterface
;
149 USB_BUS_INTERFACE_USBDI_V2 BusInterfaceUSBDI
;
150 DEVICE_POWER_STATE DeviceState
[POWER_SYSTEM_MAXIMUM
];
151 SYSTEM_POWER_STATE SystemWake
;
152 DEVICE_POWER_STATE DeviceWake
;
153 POWER_STATE CurrentPowerState
;
154 POWER_STATE SystemPowerState
;
155 ULONG MaxPowerPerPort
;
156 USB_DEVICE_DESCRIPTOR HubDeviceDescriptor
;
158 PUSB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor
;
159 PUSB_HUB_DESCRIPTOR HubDescriptor
;
160 PUSBHUB_PORT_DATA PortData
;
161 USBD_CONFIGURATION_HANDLE ConfigHandle
;
162 USBD_PIPE_INFORMATION PipeInfo
;
165 PVOID SCEBitmap
; // 11.12.4 Hub and Port Status Change Bitmap (USB 2.0 Specification)
166 ULONG SCEBitmapLength
;
167 KEVENT RootHubNotificationEvent
;
168 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST SCEWorkerUrb
;
169 KEVENT StatusChangeEvent
;
170 KSEMAPHORE IdleSemaphore
;
171 KSPIN_LOCK RelationsWorkerSpinLock
;
173 LONG PendingRequestCount
;
174 KEVENT PendingRequestEvent
;
175 KSEMAPHORE ResetDeviceSemaphore
;
176 PRKEVENT pResetPortEvent
;
177 KSEMAPHORE HubPortSemaphore
;
178 LONG ResetRequestCount
;
182 LONG FdoWaitWakeLock
;
183 LIST_ENTRY WorkItemList
;
184 KSPIN_LOCK WorkItemSpinLock
;
185 KSPIN_LOCK CheckIdleSpinLock
;
187 LONG IdleRequestLock
;
189 KSEMAPHORE HubSemaphore
;
190 PUSBHUB_IO_WORK_ITEM WorkItemToQueue
;
191 USB_IDLE_CALLBACK_INFO IdleCallbackInfo
;
192 USB_PORT_STATUS_AND_CHANGE PortStatus
;
194 } USBHUB_FDO_EXTENSION
, *PUSBHUB_FDO_EXTENSION
;
196 typedef struct _USBHUB_PORT_PDO_EXTENSION
{
197 COMMON_DEVICE_EXTENSION Common
;
200 UNICODE_STRING SymbolicLinkName
;
202 PUSBHUB_FDO_EXTENSION HubExtension
;
203 PUSBHUB_FDO_EXTENSION RootHubExtension
;
204 PUSB_DEVICE_HANDLE DeviceHandle
;
206 USHORT SN_DescriptorLength
;
207 BOOL IgnoringHwSerial
;
208 LPWSTR SerialNumber
; // serial number string
209 USB_DEVICE_DESCRIPTOR DeviceDescriptor
;
210 USB_DEVICE_DESCRIPTOR OldDeviceDescriptor
;
211 USB_CONFIGURATION_DESCRIPTOR ConfigDescriptor
;
212 USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
214 PIRP IdleNotificationIrp
;
215 POWER_STATE CurrentPowerState
;
216 DEVICE_CAPABILITIES Capabilities
;
218 PVOID BndwTimeoutContext
;
219 KSPIN_LOCK PortTimeoutSpinLock
;
221 LONG PoRequestCounter
;
222 LONG PendingSystemPoRequest
;
223 LONG PendingDevicePoRequest
;
226 LIST_ENTRY PortPowerList
;
227 KSPIN_LOCK PortPowerListSpinLock
;
228 } USBHUB_PORT_PDO_EXTENSION
, *PUSBHUB_PORT_PDO_EXTENSION
;
230 typedef struct _USBHUB_URB_TIMEOUT_CONTEXT
{
232 KEVENT UrbTimeoutEvent
;
234 KTIMER UrbTimeoutTimer
;
235 KSPIN_LOCK UrbTimeoutSpinLock
;
236 BOOL IsNormalCompleted
;
237 } USBHUB_URB_TIMEOUT_CONTEXT
, *PUSBHUB_URB_TIMEOUT_CONTEXT
;
239 typedef struct _USBHUB_STATUS_CHANGE_CONTEXT
{
241 BOOL IsRequestErrors
;
242 PUSBHUB_FDO_EXTENSION HubExtension
;
243 } USBHUB_STATUS_CHANGE_CONTEXT
, *PUSBHUB_STATUS_CHANGE_CONTEXT
;
245 typedef struct _USBHUB_IDLE_HUB_CONTEXT
{
248 } USBHUB_IDLE_HUB_CONTEXT
, *PUSBHUB_IDLE_HUB_CONTEXT
;
250 typedef struct _USBHUB_IDLE_PORT_CONTEXT
{
254 } USBHUB_IDLE_PORT_CONTEXT
, *PUSBHUB_IDLE_PORT_CONTEXT
;
256 typedef struct _USBHUB_IDLE_PORT_CANCEL_CONTEXT
{
259 } USBHUB_IDLE_PORT_CANCEL_CONTEXT
, *PUSBHUB_IDLE_PORT_CANCEL_CONTEXT
;
261 typedef struct _USBHUB_RESET_PORT_CONTEXT
{
263 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
265 } USBHUB_RESET_PORT_CONTEXT
, *PUSBHUB_RESET_PORT_CONTEXT
;
270 USBHUB_DumpingDeviceDescriptor(
271 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
);
275 USBHUB_DumpingConfiguration(
276 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor
);
287 IN PUSBHUB_FDO_EXTENSION HubExtension
,
292 USBH_PdoInternalControl(
293 IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
,
299 USBH_PdoRemoveDevice(
300 IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
,
301 IN PUSBHUB_FDO_EXTENSION HubExtension
);
306 IN PUSBHUB_FDO_EXTENSION HubExtension
,
313 IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
,
316 OUT BOOLEAN
* IsCompleteIrp
);
321 USBH_CompletePowerIrp(
322 IN PUSBHUB_FDO_EXTENSION HubExtension
,
324 IN NTSTATUS NtStatus
);
329 IN PUSBHUB_FDO_EXTENSION HubExtension
);
334 IN PUSBHUB_FDO_EXTENSION HubExtension
,
341 IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
,
347 USBH_HubCompletePortWakeIrps(
348 IN PUSBHUB_FDO_EXTENSION HubExtension
,
349 IN NTSTATUS NtStatus
);
353 USBH_HubCancelWakeIrp(
354 IN PUSBHUB_FDO_EXTENSION HubExtension
,
359 USBH_IdleCancelPowerHubWorker(
360 IN PUSBHUB_FDO_EXTENSION HubExtension
,
367 IN ULONG Milliseconds
);
373 IN NTSTATUS CompleteStatus
);
378 IN PDEVICE_OBJECT DeviceObject
,
381 PUSBHUB_PORT_PDO_EXTENSION
384 IN PDEVICE_OBJECT DeviceObject
);
388 USBH_WriteFailReasonID(
389 IN PDEVICE_OBJECT DeviceObject
,
394 USBH_SetPdoRegistryParameter(
395 IN PDEVICE_OBJECT DeviceObject
,
396 IN PCWSTR SourceString
,
400 IN ULONG DevInstKeyType
);
405 IN PDEVICE_OBJECT DeviceObject
,
410 USBH_FdoSyncSubmitUrb(
411 IN PDEVICE_OBJECT FdoDevice
,
417 IN PUSBHUB_FDO_EXTENSION HubExtension
,
423 IN PUSBHUB_FDO_EXTENSION HubExtension
,
424 IN PUSB_DEVICE_HANDLE DeviceHandle
,
425 OUT USB_DEVICE_TYPE
* OutDeviceType
);
427 PUSBHUB_FDO_EXTENSION
429 USBH_GetRootHubExtension(
430 IN PUSBHUB_FDO_EXTENSION HubExtension
);
434 USBH_SyncGetRootHubPdo(
435 IN PDEVICE_OBJECT DeviceObject
,
436 IN OUT PDEVICE_OBJECT
* OutPdo1
,
437 IN OUT PDEVICE_OBJECT
* OutPdo2
);
441 USBH_SyncGetHubCount(
442 IN PDEVICE_OBJECT DeviceObject
,
443 IN OUT PULONG OutHubCount
);
447 USBH_SyncGetDeviceHandle(
448 IN PDEVICE_OBJECT DeviceObject
);
452 USBH_GetDeviceDescriptor(
453 IN PDEVICE_OBJECT DeviceObject
,
454 IN PUSB_DEVICE_DESCRIPTOR HubDeviceDescriptor
);
458 USBH_GetConfigurationDescriptor(
459 IN PDEVICE_OBJECT DeviceObject
,
460 IN PUSB_CONFIGURATION_DESCRIPTOR
* pConfigurationDescriptor
);
464 USBH_SyncGetHubDescriptor(
465 IN PUSBHUB_FDO_EXTENSION HubExtension
);
469 USBH_SyncGetStringDescriptor(
470 IN PDEVICE_OBJECT DeviceObject
,
472 IN USHORT LanguageId
,
473 IN PUSB_STRING_DESCRIPTOR Descriptor
,
474 IN ULONG NumberOfBytes
,
476 IN BOOLEAN IsValidateLength
);
480 USBH_SyncGetPortStatus(
481 IN PUSBHUB_FDO_EXTENSION HubExtension
,
483 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus
,
488 USBH_SyncClearPortStatus(
489 IN PUSBHUB_FDO_EXTENSION HubExtension
,
491 IN USHORT RequestValue
);
495 USBH_SyncPowerOnPorts(
496 IN PUSBHUB_FDO_EXTENSION HubExtension
);
500 USBH_SyncDisablePort(
501 IN PUSBHUB_FDO_EXTENSION HubExtension
,
506 USBH_HubIsBusPowered(
507 IN PDEVICE_OBJECT DeviceObject
,
508 IN PUSB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor
);
512 USBH_SubmitStatusChangeTransfer(
513 IN PUSBHUB_FDO_EXTENSION HubExtension
);
518 IN PUSBHUB_FDO_EXTENSION HubExtension
,
519 IN PUSB_DEVICE_HANDLE
* OutDeviceHandle
,
520 IN USB_PORT_STATUS UsbPortStatus
,
526 IN PUSBHUB_FDO_EXTENSION HubExtension
,
527 IN PUSB_DEVICE_HANDLE DeviceHandle
,
532 USBD_InitializeDeviceEx(
533 IN PUSBHUB_FDO_EXTENSION HubExtension
,
534 IN PUSB_DEVICE_HANDLE DeviceHandle
,
535 IN PUCHAR DeviceDescriptorBuffer
,
536 IN ULONG DeviceDescriptorBufferLength
,
537 IN PUCHAR ConfigDescriptorBuffer
,
538 IN ULONG ConfigDescriptorBufferLength
);
542 USBHUB_SetDeviceHandleData(
543 IN PUSBHUB_FDO_EXTENSION HubExtension
,
544 IN PDEVICE_OBJECT UsbDevicePdo
,
545 IN PVOID DeviceHandle
);
549 USBHUB_FlushAllTransfers(
550 IN PUSBHUB_FDO_EXTENSION HubExtension
);
554 USBD_GetDeviceInformationEx(
555 IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
,
556 IN PUSBHUB_FDO_EXTENSION HubExtension
,
557 IN PUSB_NODE_CONNECTION_INFORMATION_EX Info
,
559 IN PUSB_DEVICE_HANDLE DeviceHandle
);
563 USBD_RestoreDeviceEx(
564 IN PUSBHUB_FDO_EXTENSION HubExtension
,
565 IN OUT PUSB_DEVICE_HANDLE OldDeviceHandle
,
566 IN OUT PUSB_DEVICE_HANDLE NewDeviceHandle
);
570 USBH_AllocateWorkItem(
571 IN PUSBHUB_FDO_EXTENSION HubExtension
,
572 OUT PUSBHUB_IO_WORK_ITEM
* OutHubIoWorkItem
,
573 IN PUSBHUB_WORKER_ROUTINE WorkerRoutine
,
574 IN SIZE_T BufferLength
,
575 OUT PVOID
* OutHubWorkItemBuffer
,
576 IN WORK_QUEUE_TYPE Type
);
581 IN PUSBHUB_FDO_EXTENSION HubExtension
,
582 IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem
);
587 IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem
);
591 USBD_RegisterRootHubCallBack(
592 IN PUSBHUB_FDO_EXTENSION HubExtension
);
596 USBD_UnRegisterRootHubCallBack(
597 IN PUSBHUB_FDO_EXTENSION HubExtension
);
601 USBH_HubCancelIdleIrp(
602 IN PUSBHUB_FDO_EXTENSION HubExtension
,
608 IN PUSBHUB_FDO_EXTENSION HubExtension
,
610 IN BOOLEAN IsExtCheck
);
615 IN PUSBHUB_FDO_EXTENSION HubExtension
);
619 USBH_CheckIdleDeferred(
620 IN PUSBHUB_FDO_EXTENSION HubExtension
);
624 USBH_CheckDeviceLanguage(
625 IN PDEVICE_OBJECT DeviceObject
,
626 IN USHORT LanguageId
);
631 IN PUSBHUB_FDO_EXTENSION HubExtension
,
633 IN USB_PORT_STATUS UsbPortStatus
,
639 IN PUSBHUB_FDO_EXTENSION HubExtension
,
641 IN BOOLEAN IsKeepDeviceData
,
647 IN PDRIVER_OBJECT DriverObject
,
648 IN PUNICODE_STRING RegistryPath
);
650 #endif /* _USBHUB_H_ */