[USBPORT][USBHUB_NEW]
[reactos.git] / reactos / drivers / usb / usbhub_new / usbhub.c
1 #include "usbhub.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 #define NDEBUG_USBHUB_SCE
7 #define NDEBUG_USBHUB_PNP
8 #include "dbg_uhub.h"
9
10 #include <ntddstor.h>
11
12 PWSTR GenericUSBDeviceString = NULL;
13
14 NTSTATUS
15 NTAPI
16 USBH_Wait(IN ULONG Milliseconds)
17 {
18 LARGE_INTEGER Interval;
19
20 DPRINT("USBH_Wait: Milliseconds - %x\n", Milliseconds);
21 Interval.QuadPart = -10000 * Milliseconds + (KeQueryTimeIncrement() - 1);
22 return KeDelayExecutionThread(KernelMode, FALSE, &Interval);
23 }
24
25 NTSTATUS
26 NTAPI
27 USBH_GetConfigValue(IN PWSTR ValueName,
28 IN ULONG ValueType,
29 IN PVOID ValueData,
30 IN ULONG ValueLength,
31 IN PVOID Context,
32 IN PVOID EntryContext)
33 {
34 NTSTATUS Status = STATUS_SUCCESS;
35
36 DPRINT("USBHUB_GetConfigValue: ... \n");
37
38 if (ValueType == REG_BINARY)
39 {
40 *(PUCHAR)EntryContext = *(PUCHAR)ValueData;
41 }
42 else if (ValueType == REG_DWORD)
43 {
44 *(PULONG)EntryContext = *(PULONG)ValueData;
45 }
46 else
47 {
48 Status = STATUS_INVALID_PARAMETER;
49 }
50
51 return Status;
52 }
53
54 VOID
55 NTAPI
56 USBH_CompleteIrp(IN PIRP Irp,
57 IN NTSTATUS CompleteStatus)
58 {
59 if (CompleteStatus != STATUS_SUCCESS)
60 {
61 DPRINT1("USBH_CompleteIrp: Irp - %p, CompleteStatus - %X\n",
62 Irp,
63 CompleteStatus);
64 }
65
66 Irp->IoStatus.Status = CompleteStatus;
67 IoCompleteRequest(Irp, IO_NO_INCREMENT);
68 }
69
70 NTSTATUS
71 NTAPI
72 USBH_PassIrp(IN PDEVICE_OBJECT DeviceObject,
73 IN PIRP Irp)
74 {
75 DPRINT_PNP("USBH_PassIrp: DeviceObject - %p, Irp - %p\n",
76 DeviceObject,
77 Irp);
78
79 IoSkipCurrentIrpStackLocation(Irp);
80 return IoCallDriver(DeviceObject, Irp);
81 }
82
83 NTSTATUS
84 NTAPI
85 USBH_SyncIrpComplete(IN PDEVICE_OBJECT DeviceObject,
86 IN PIRP Irp,
87 IN PVOID Context)
88 {
89 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
90 KIRQL OldIrql;
91 BOOLEAN TimerCancelled;
92
93 DPRINT("USBH_SyncIrpComplete: ... \n");
94
95 HubTimeoutContext = Context;
96
97 KeAcquireSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, &OldIrql);
98 HubTimeoutContext->IsNormalCompleted = TRUE;
99 TimerCancelled = KeCancelTimer(&HubTimeoutContext->UrbTimeoutTimer);
100 KeReleaseSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, OldIrql);
101
102 if (TimerCancelled)
103 {
104 KeSetEvent(&HubTimeoutContext->UrbTimeoutEvent,
105 EVENT_INCREMENT,
106 FALSE);
107 }
108
109 return STATUS_SUCCESS;
110 }
111
112 BOOLEAN
113 NTAPI
114 IsBitSet(IN PUCHAR BitMapAddress,
115 IN USHORT Bit)
116 {
117 BOOLEAN IsSet;
118
119 IsSet = (BitMapAddress[Bit / 8] & (1 << (Bit & 7))) != 0;
120 DPRINT("IsBitSet: Bit - %lX, IsSet - %x\n", Bit, IsSet);
121 return IsSet;
122 }
123
124 PUSBHUB_PORT_PDO_EXTENSION
125 NTAPI
126 PdoExt(IN PDEVICE_OBJECT DeviceObject)
127 {
128 PVOID PdoExtension;
129
130 DPRINT("PdoExt: DeviceObject - %p\n", DeviceObject);
131
132 if (DeviceObject)
133 {
134 PdoExtension = DeviceObject->DeviceExtension;
135 }
136 else
137 {
138 PdoExtension = NULL;
139 }
140
141 return (PUSBHUB_PORT_PDO_EXTENSION)PdoExtension;
142 }
143
144 NTSTATUS
145 NTAPI
146 USBH_WriteFailReasonID(IN PDEVICE_OBJECT DeviceObject,
147 IN ULONG FailReason)
148 {
149 NTSTATUS Status;
150 HANDLE KeyHandle;
151 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"FailReasonID");
152
153 DPRINT("USBH_WriteFailReason: ID - %x\n", FailReason);
154
155 Status = IoOpenDeviceRegistryKey(DeviceObject,
156 PLUGPLAY_REGKEY_DEVICE,
157 STANDARD_RIGHTS_ALL,
158 &KeyHandle);
159
160 if (NT_SUCCESS(Status))
161 {
162 ZwSetValueKey(KeyHandle,
163 &ValueName,
164 0,
165 REG_DWORD,
166 &FailReason,
167 sizeof(FailReason));
168
169 ZwClose(KeyHandle);
170 }
171
172 return Status;
173 }
174
175 VOID
176 NTAPI
177 USBH_UrbTimeoutDPC(IN PKDPC Dpc,
178 IN PVOID DeferredContext,
179 IN PVOID SystemArgument1,
180 IN PVOID SystemArgument2)
181 {
182 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
183 KIRQL OldIrql;
184 BOOL IsCompleted;
185
186 DPRINT("USBH_TimeoutDPC ... \n");
187
188 HubTimeoutContext = DeferredContext;
189
190 KeAcquireSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, &OldIrql);
191 IsCompleted = HubTimeoutContext->IsNormalCompleted;
192 KeReleaseSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, OldIrql);
193
194 if (!IsCompleted)
195 {
196 IoCancelIrp(HubTimeoutContext->Irp);
197 }
198
199 KeSetEvent(&HubTimeoutContext->UrbTimeoutEvent,
200 EVENT_INCREMENT,
201 FALSE);
202 }
203
204 NTSTATUS
205 NTAPI
206 USBH_SetPdoRegistryParameter(IN PDEVICE_OBJECT DeviceObject,
207 IN PCWSTR ValueName,
208 IN PVOID Data,
209 IN ULONG DataSize,
210 IN ULONG Type,
211 IN ULONG DevInstKeyType)
212 {
213 NTSTATUS Status;
214 UNICODE_STRING ValueNameString;
215 HANDLE KeyHandle;
216
217 DPRINT("USBH_SetPdoRegistryParameter ... \n");
218
219 RtlInitUnicodeString(&ValueNameString, ValueName);
220
221 Status = IoOpenDeviceRegistryKey(DeviceObject,
222 DevInstKeyType,
223 STANDARD_RIGHTS_ALL,
224 &KeyHandle);
225
226 if (NT_SUCCESS(Status))
227 {
228 ZwSetValueKey(KeyHandle,
229 &ValueNameString,
230 0,
231 Type,
232 Data,
233 DataSize);
234
235 ZwClose(KeyHandle);
236 }
237
238 return Status;
239 }
240
241 NTSTATUS
242 NTAPI
243 USBH_SyncSubmitUrb(IN PDEVICE_OBJECT DeviceObject,
244 IN PURB Urb)
245 {
246 KEVENT Event;
247 IO_STATUS_BLOCK IoStatusBlock;
248 PIRP Irp;
249 PIO_STACK_LOCATION IoStack;
250 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
251 BOOLEAN IsWaitTimeout = FALSE;
252 LARGE_INTEGER DueTime;
253 NTSTATUS Status;
254
255 DPRINT("USBH_SyncSubmitUrb: ... \n");
256
257 Urb->UrbHeader.UsbdDeviceHandle = NULL;
258
259 KeInitializeEvent(&Event, NotificationEvent, FALSE);
260
261 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
262 DeviceObject,
263 NULL,
264 0,
265 NULL,
266 0,
267 TRUE,
268 &Event,
269 &IoStatusBlock);
270
271 if (!Irp)
272 {
273 return STATUS_INSUFFICIENT_RESOURCES;
274 }
275
276 IoStack = IoGetNextIrpStackLocation(Irp);
277 IoStack->Parameters.Others.Argument1 = Urb;
278
279 HubTimeoutContext = ExAllocatePoolWithTag(NonPagedPool,
280 sizeof(USBHUB_URB_TIMEOUT_CONTEXT),
281 USB_HUB_TAG);
282
283 if (HubTimeoutContext)
284 {
285 RtlZeroMemory(HubTimeoutContext, sizeof(USBHUB_URB_TIMEOUT_CONTEXT));
286
287 HubTimeoutContext->Irp = Irp;
288 HubTimeoutContext->IsNormalCompleted = FALSE;
289
290 KeInitializeEvent(&HubTimeoutContext->UrbTimeoutEvent,
291 NotificationEvent,
292 FALSE);
293
294 KeInitializeSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock);
295 KeInitializeTimer(&HubTimeoutContext->UrbTimeoutTimer);
296
297 KeInitializeDpc(&HubTimeoutContext->UrbTimeoutDPC,
298 USBH_UrbTimeoutDPC,
299 HubTimeoutContext);
300
301 DueTime.QuadPart = -5000 * 10000; // Timeout 5 sec.
302
303 KeSetTimer(&HubTimeoutContext->UrbTimeoutTimer,
304 DueTime,
305 &HubTimeoutContext->UrbTimeoutDPC);
306
307 IoSetCompletionRoutine(Irp,
308 USBH_SyncIrpComplete,
309 HubTimeoutContext,
310 TRUE,
311 TRUE,
312 TRUE);
313
314 IsWaitTimeout = TRUE;
315 }
316
317 Status = IoCallDriver(DeviceObject, Irp);
318
319 if (Status == STATUS_PENDING)
320 {
321 KeWaitForSingleObject(&Event,
322 Suspended,
323 KernelMode,
324 FALSE,
325 NULL);
326 }
327 else
328 {
329 IoStatusBlock.Status = Status;
330 }
331
332 if (IsWaitTimeout)
333 {
334 KeWaitForSingleObject(&HubTimeoutContext->UrbTimeoutEvent,
335 Suspended,
336 KernelMode,
337 FALSE,
338 NULL);
339
340 ExFreePoolWithTag(HubTimeoutContext, USB_HUB_TAG);
341 }
342
343 return IoStatusBlock.Status;
344 }
345
346 NTSTATUS
347 NTAPI
348 USBH_FdoSyncSubmitUrb(IN PDEVICE_OBJECT FdoDevice,
349 IN PURB Urb)
350 {
351 PUSBHUB_FDO_EXTENSION HubExtension;
352
353 DPRINT("USBH_FdoSyncSubmitUrb: FdoDevice - %p, Urb - %p\n",
354 FdoDevice,
355 Urb);
356
357 HubExtension = FdoDevice->DeviceExtension;
358 return USBH_SyncSubmitUrb(HubExtension->LowerDevice, Urb);
359 }
360
361 NTSTATUS
362 NTAPI
363 USBH_Transact(IN PUSBHUB_FDO_EXTENSION HubExtension,
364 IN PVOID TransferBuffer,
365 IN ULONG BufferLen,
366 IN BOOLEAN IsDeviceToHost,
367 IN USHORT Function,
368 IN BM_REQUEST_TYPE RequestType,
369 IN UCHAR Request,
370 IN USHORT RequestValue,
371 IN USHORT RequestIndex)
372 {
373 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb;
374 ULONG TransferFlags;
375 PVOID Buffer = NULL;
376 ULONG Length;
377 NTSTATUS Status;
378
379 DPRINT("USBH_Transact: ... \n");
380
381 if (BufferLen)
382 {
383 Length = ALIGN_DOWN_BY(BufferLen + sizeof(ULONG), sizeof(ULONG));
384
385 Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, USB_HUB_TAG);
386
387 if (!Buffer)
388 {
389 return STATUS_INSUFFICIENT_RESOURCES;
390 }
391
392 RtlZeroMemory(Buffer, Length);
393 }
394
395 Urb = ExAllocatePoolWithTag(NonPagedPool,
396 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
397 USB_HUB_TAG);
398
399 if (!Urb)
400 {
401 if (Buffer)
402 {
403 ExFreePoolWithTag(Buffer, USB_HUB_TAG);
404 }
405
406 return STATUS_INSUFFICIENT_RESOURCES;
407 }
408
409 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
410
411 if (IsDeviceToHost)
412 {
413 if (BufferLen)
414 {
415 RtlZeroMemory(TransferBuffer, BufferLen);
416 }
417
418 TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
419 }
420 else
421 {
422 if (BufferLen)
423 {
424 RtlCopyMemory(Buffer, TransferBuffer, BufferLen);
425 }
426
427 TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
428 }
429
430 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
431 Urb->Hdr.Function = Function;
432 Urb->Hdr.UsbdDeviceHandle = NULL;
433
434 Urb->TransferFlags = TransferFlags;
435 Urb->TransferBuffer = BufferLen != 0 ? Buffer : NULL;
436 Urb->TransferBufferLength = BufferLen;
437 Urb->TransferBufferMDL = NULL;
438 Urb->UrbLink = NULL;
439
440 Urb->RequestTypeReservedBits = RequestType.B;
441 Urb->Request = Request;
442 Urb->Value = RequestValue;
443 Urb->Index = RequestIndex;
444
445 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice, (PURB)Urb);
446
447 if (IsDeviceToHost && BufferLen)
448 {
449 RtlCopyMemory(TransferBuffer, Buffer, BufferLen);
450 }
451
452 if (Buffer)
453 {
454 ExFreePoolWithTag(Buffer, USB_HUB_TAG);
455 }
456
457 ExFreePoolWithTag(Urb, USB_HUB_TAG);
458
459 return Status;
460 }
461
462 NTSTATUS
463 NTAPI
464 USBH_SyncResetPort(IN PUSBHUB_FDO_EXTENSION HubExtension,
465 IN USHORT Port)
466 {
467 USB_PORT_STATUS_AND_CHANGE PortStatus;
468 KEVENT Event;
469 LARGE_INTEGER Timeout;
470 ULONG ResetRetry = 0;
471 NTSTATUS Status;
472
473 DPRINT("USBH_SyncResetPort: Port - %x\n", Port);
474
475 InterlockedIncrement(&HubExtension->PendingRequestCount);
476
477 KeWaitForSingleObject(&HubExtension->HubPortSemaphore,
478 Executive,
479 KernelMode,
480 FALSE,
481 NULL);
482
483 Status = USBH_SyncGetPortStatus(HubExtension,
484 Port,
485 &PortStatus,
486 sizeof(USB_PORT_STATUS_AND_CHANGE));
487
488 if (NT_SUCCESS(Status) &&
489 (PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0))
490 {
491 Status = STATUS_UNSUCCESSFUL;
492 goto Exit;
493 }
494
495 HubExtension->HubFlags |= USBHUB_FDO_FLAG_RESET_PORT_LOCK;
496
497 while (TRUE)
498 {
499 BM_REQUEST_TYPE RequestType;
500
501 KeInitializeEvent(&Event, NotificationEvent, FALSE);
502
503 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
504 &Event);
505
506 RequestType.B = 0;
507 RequestType.Recipient = BMREQUEST_TO_DEVICE;
508 RequestType.Type = BMREQUEST_CLASS;
509 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
510
511 Status = USBH_Transact(HubExtension,
512 NULL,
513 0,
514 BMREQUEST_HOST_TO_DEVICE,
515 URB_FUNCTION_CLASS_OTHER,
516 RequestType,
517 USB_REQUEST_SET_FEATURE,
518 USBHUB_FEATURE_PORT_RESET,
519 Port);
520
521 Timeout.QuadPart = -5000 * 10000;
522
523 if (!NT_SUCCESS(Status))
524 {
525 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
526 NULL);
527
528 USBH_Wait(10);
529 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK;
530
531 goto Exit;
532 }
533
534 Status = KeWaitForSingleObject(&Event,
535 Suspended,
536 KernelMode,
537 FALSE,
538 &Timeout);
539
540 if (Status != STATUS_TIMEOUT)
541 {
542 break;
543 }
544
545 Status = USBH_SyncGetPortStatus(HubExtension,
546 Port,
547 &PortStatus,
548 sizeof(USB_PORT_STATUS_AND_CHANGE));
549
550 if (!NT_SUCCESS(Status) ||
551 (PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0) ||
552 ResetRetry >= USBHUB_RESET_PORT_MAX_RETRY)
553 {
554 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
555 NULL);
556
557 USBH_Wait(10);
558 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK;
559
560 Status = STATUS_DEVICE_DATA_ERROR;
561 goto Exit;
562 }
563
564 ResetRetry++;
565 }
566
567 Status = USBH_SyncGetPortStatus(HubExtension,
568 Port,
569 &PortStatus,
570 sizeof(USB_PORT_STATUS_AND_CHANGE));
571
572 if ((PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0) &&
573 NT_SUCCESS(Status) &&
574 HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB)
575 {
576 Status = STATUS_DEVICE_DATA_ERROR;
577 }
578
579 USBH_Wait(10);
580 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK;
581
582 Exit:
583
584 KeReleaseSemaphore(&HubExtension->HubPortSemaphore,
585 LOW_REALTIME_PRIORITY,
586 1,
587 FALSE);
588
589 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
590 {
591 KeSetEvent(&HubExtension->PendingRequestEvent,
592 EVENT_INCREMENT,
593 FALSE);
594 }
595
596 return Status;
597 }
598
599 NTSTATUS
600 NTAPI
601 USBH_GetDeviceType(IN PUSBHUB_FDO_EXTENSION HubExtension,
602 IN PUSB_DEVICE_HANDLE DeviceHandle,
603 OUT USB_DEVICE_TYPE * OutDeviceType)
604 {
605 PUSB_BUSIFFN_GET_DEVICE_INFORMATION QueryDeviceInformation;
606 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
607 SIZE_T DeviceInformationBufferLength;
608 USB_DEVICE_TYPE DeviceType = Usb11Device;
609 ULONG dummy;
610 NTSTATUS Status;
611
612 DPRINT("USBH_GetDeviceType: ... \n");
613
614 QueryDeviceInformation = HubExtension->BusInterface.QueryDeviceInformation;
615
616 if (!QueryDeviceInformation)
617 {
618 DPRINT1("USBH_GetDeviceType: no QueryDeviceInformation()\n");
619 return STATUS_NOT_IMPLEMENTED;
620 }
621
622 DeviceInformationBufferLength = sizeof(USB_DEVICE_INFORMATION_0);
623
624 while (TRUE)
625 {
626 DeviceInfo = ExAllocatePoolWithTag(PagedPool,
627 DeviceInformationBufferLength,
628 USB_HUB_TAG);
629
630 if (!DeviceInfo)
631 {
632 DPRINT1("USBH_GetDeviceType: ExAllocatePoolWithTag() failed\n");
633 Status = STATUS_INSUFFICIENT_RESOURCES;
634 break;
635 }
636
637 RtlZeroMemory(DeviceInfo, DeviceInformationBufferLength);
638
639 DeviceInfo->InformationLevel = 0;
640
641 Status = QueryDeviceInformation(HubExtension->BusInterface.BusContext,
642 DeviceHandle,
643 DeviceInfo,
644 DeviceInformationBufferLength,
645 &dummy);
646
647 if (Status != STATUS_BUFFER_TOO_SMALL)
648 {
649 if (NT_SUCCESS(Status))
650 {
651 DeviceType = DeviceInfo->DeviceType;
652 }
653
654 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
655 break;
656 }
657
658 DeviceInformationBufferLength = DeviceInfo->ActualLength;
659 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
660 }
661
662 if (OutDeviceType)
663 {
664 *OutDeviceType = DeviceType;
665 DPRINT("USBH_GetDeviceType: DeviceType - %x\n", DeviceType);
666 }
667
668 return Status;
669 }
670
671 NTSTATUS
672 NTAPI
673 USBHUB_GetExtendedHubInfo(IN PUSBHUB_FDO_EXTENSION HubExtension,
674 IN PUSB_EXTHUB_INFORMATION_0 HubInfoBuffer)
675 {
676 PUSB_BUSIFFN_GET_EXTENDED_HUB_INFO GetExtendedHubInformation;
677 ULONG dummy = 0;
678
679 DPRINT("USBHUB_GetExtendedHubInfo: ... \n");
680
681 GetExtendedHubInformation = HubExtension->BusInterface.GetExtendedHubInformation;
682
683 return GetExtendedHubInformation(HubExtension->BusInterface.BusContext,
684 HubExtension->LowerPDO,
685 HubInfoBuffer,
686 sizeof(USB_EXTHUB_INFORMATION_0),
687 &dummy);
688 }
689
690 PUSBHUB_FDO_EXTENSION
691 NTAPI
692 USBH_GetRootHubExtension(IN PUSBHUB_FDO_EXTENSION HubExtension)
693 {
694 PDEVICE_OBJECT Device;
695 PUSBHUB_FDO_EXTENSION RootHubExtension;
696
697 DPRINT("USBH_GetRootHubExtension: HubExtension - %p\n", HubExtension);
698
699 RootHubExtension = HubExtension;
700
701 if (HubExtension->LowerPDO != HubExtension->RootHubPdo)
702 {
703 Device = HubExtension->RootHubPdo;
704
705 do
706 {
707 Device = Device->AttachedDevice;
708 }
709 while (Device->DriverObject != HubExtension->Common.SelfDevice->DriverObject);
710
711 RootHubExtension = Device->DeviceExtension;
712 }
713
714 DPRINT("USBH_GetRootHubExtension: RootHubExtension - %p\n", RootHubExtension);
715
716 return RootHubExtension;
717 }
718
719 NTSTATUS
720 NTAPI
721 USBH_SyncGetRootHubPdo(IN PDEVICE_OBJECT DeviceObject,
722 IN OUT PDEVICE_OBJECT * OutPdo1,
723 IN OUT PDEVICE_OBJECT * OutPdo2)
724 {
725 KEVENT Event;
726 IO_STATUS_BLOCK IoStatusBlock;
727 PIRP Irp;
728 PIO_STACK_LOCATION IoStack;
729 NTSTATUS Status;
730
731 DPRINT("USBH_SyncGetRootHubPdo: ... \n");
732
733 KeInitializeEvent(&Event, NotificationEvent, FALSE);
734
735 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
736 DeviceObject,
737 NULL,
738 0,
739 NULL,
740 0,
741 TRUE,
742 &Event,
743 &IoStatusBlock);
744
745 if (!Irp)
746 {
747 return STATUS_INSUFFICIENT_RESOURCES;
748 }
749
750 IoStack = IoGetNextIrpStackLocation(Irp);
751 IoStack->Parameters.Others.Argument1 = OutPdo1;
752 IoStack->Parameters.Others.Argument2 = OutPdo2;
753
754 Status = IoCallDriver(DeviceObject, Irp);
755
756 if (Status == STATUS_PENDING)
757 {
758 KeWaitForSingleObject(&Event,
759 Suspended,
760 KernelMode,
761 FALSE,
762 NULL);
763 }
764 else
765 {
766 IoStatusBlock.Status = Status;
767 }
768
769 return IoStatusBlock.Status;
770 }
771
772 NTSTATUS
773 NTAPI
774 USBH_SyncGetHubCount(IN PDEVICE_OBJECT DeviceObject,
775 IN OUT PULONG OutHubCount)
776 {
777 KEVENT Event;
778 IO_STATUS_BLOCK IoStatusBlock;
779 PIRP Irp;
780 PIO_STACK_LOCATION IoStack;
781 NTSTATUS Status;
782
783 DPRINT("USBH_SyncGetHubCount: *OutHubCount - %x\n", *OutHubCount);
784
785 KeInitializeEvent(&Event, NotificationEvent, FALSE);
786
787 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_HUB_COUNT,
788 DeviceObject,
789 NULL,
790 0,
791 NULL,
792 0,
793 TRUE,
794 &Event,
795 &IoStatusBlock);
796
797 if (!Irp)
798 {
799 return STATUS_INSUFFICIENT_RESOURCES;
800 }
801
802 IoStack = IoGetNextIrpStackLocation(Irp);
803 IoStack->Parameters.Others.Argument1 = OutHubCount;
804
805 Status = IoCallDriver(DeviceObject, Irp);
806
807 if (Status == STATUS_PENDING)
808 {
809 KeWaitForSingleObject(&Event,
810 Suspended,
811 KernelMode,
812 FALSE,
813 NULL);
814 }
815 else
816 {
817 IoStatusBlock.Status = Status;
818 }
819
820 return IoStatusBlock.Status;
821 }
822
823 PUSB_DEVICE_HANDLE
824 NTAPI
825 USBH_SyncGetDeviceHandle(IN PDEVICE_OBJECT DeviceObject)
826 {
827 PIRP Irp;
828 KEVENT Event;
829 IO_STATUS_BLOCK IoStatusBlock;
830 PUSB_DEVICE_HANDLE DeviceHandle = NULL;
831 PIO_STACK_LOCATION IoStack;
832
833 DPRINT("USBH_SyncGetDeviceHandle: ... \n");
834
835 KeInitializeEvent(&Event, NotificationEvent, FALSE);
836
837 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
838 DeviceObject,
839 NULL,
840 0,
841 NULL,
842 0,
843 TRUE,
844 &Event,
845 &IoStatusBlock);
846
847 if (!Irp)
848 {
849 DPRINT1("USBH_SyncGetDeviceHandle: Irp - NULL!\n");
850 return NULL;
851 }
852
853 IoStack = IoGetNextIrpStackLocation(Irp);
854 IoStack->Parameters.Others.Argument1 = &DeviceHandle;
855
856 if (IoCallDriver(DeviceObject, Irp) == STATUS_PENDING)
857 {
858 KeWaitForSingleObject(&Event,
859 Suspended,
860 KernelMode,
861 FALSE,
862 NULL);
863 }
864
865 return DeviceHandle;
866 }
867
868 NTSTATUS
869 NTAPI
870 USBH_GetDeviceDescriptor(IN PDEVICE_OBJECT DeviceObject,
871 IN PUSB_DEVICE_DESCRIPTOR HubDeviceDescriptor)
872 {
873 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb;
874 NTSTATUS Status;
875
876 DPRINT("USBH_GetDeviceDescriptor: ... \n");
877
878 Urb = ExAllocatePoolWithTag(NonPagedPool,
879 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
880 USB_HUB_TAG);
881
882 if (!Urb)
883 {
884 DPRINT1("USBH_SyncGetDeviceHandle: Urb - NULL!\n");
885 return STATUS_INSUFFICIENT_RESOURCES;
886 }
887
888 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
889
890 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
891 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
892
893 Urb->TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
894 Urb->TransferBuffer = HubDeviceDescriptor;
895 Urb->DescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
896
897 Status = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb);
898
899 ExFreePoolWithTag(Urb, USB_HUB_TAG);
900
901 return Status;
902 }
903
904 NTSTATUS
905 NTAPI
906 USBH_SyncGetDeviceConfigurationDescriptor(IN PDEVICE_OBJECT DeviceObject,
907 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
908 IN ULONG NumberOfBytes,
909 IN PULONG OutLength)
910 {
911 PCOMMON_DEVICE_EXTENSION DeviceExtension;
912 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb;
913 NTSTATUS Status;
914
915 DPRINT("USBH_SyncGetDeviceConfigurationDescriptor: ... \n");
916
917 DeviceExtension = DeviceObject->DeviceExtension;
918
919 if (OutLength)
920 {
921 *OutLength = 0;
922 }
923
924 Urb = ExAllocatePoolWithTag(NonPagedPool,
925 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
926 USB_HUB_TAG);
927
928 if (!Urb)
929 {
930 return STATUS_INSUFFICIENT_RESOURCES;
931 }
932
933 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
934
935 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
936 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
937
938 Urb->TransferBufferLength = NumberOfBytes;
939 Urb->TransferBuffer = ConfigDescriptor;
940 Urb->DescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE;
941
942 if (DeviceExtension->ExtensionType == USBH_EXTENSION_TYPE_HUB ||
943 DeviceExtension->ExtensionType == USBH_EXTENSION_TYPE_PARENT)
944 {
945 Status = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb);
946 }
947 else
948 {
949 Status = USBH_SyncSubmitUrb(DeviceObject, (PURB)Urb);
950 }
951
952 if (OutLength)
953 {
954 *OutLength = Urb->TransferBufferLength;
955 }
956
957 if (Urb)
958 {
959 ExFreePoolWithTag(Urb, USB_HUB_TAG);
960 }
961
962 return Status;
963 }
964
965 NTSTATUS
966 NTAPI
967 USBH_GetConfigurationDescriptor(IN PDEVICE_OBJECT DeviceObject,
968 IN PUSB_CONFIGURATION_DESCRIPTOR * OutDescriptor)
969 {
970 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
971 ULONG ReturnedLen;
972 SIZE_T DescriptorLen;
973 NTSTATUS Status;
974
975 DPRINT("USBH_GetConfigurationDescriptor: ... \n");
976
977 DescriptorLen = MAXUCHAR;
978
979 while (TRUE)
980 {
981 ConfigDescriptor = ExAllocatePoolWithTag(NonPagedPool,
982 DescriptorLen,
983 USB_HUB_TAG);
984
985 if (!ConfigDescriptor)
986 {
987 Status = STATUS_INSUFFICIENT_RESOURCES;
988 break;
989 }
990
991 Status = USBH_SyncGetDeviceConfigurationDescriptor(DeviceObject,
992 ConfigDescriptor,
993 DescriptorLen,
994 &ReturnedLen);
995
996 if (ReturnedLen < sizeof(USB_CONFIGURATION_DESCRIPTOR))
997 {
998 Status = STATUS_DEVICE_DATA_ERROR;
999 }
1000
1001 if (!NT_SUCCESS(Status))
1002 {
1003 break;
1004 }
1005
1006 *OutDescriptor = ConfigDescriptor;
1007
1008 if (ConfigDescriptor->wTotalLength <= DescriptorLen)
1009 {
1010 break;
1011 }
1012
1013 DescriptorLen = ConfigDescriptor->wTotalLength;
1014
1015 ExFreePool(ConfigDescriptor);
1016 *OutDescriptor = NULL;
1017 }
1018
1019 if (NT_SUCCESS(Status))
1020 {
1021 if (ReturnedLen < ConfigDescriptor->wTotalLength)
1022 {
1023 Status = STATUS_DEVICE_DATA_ERROR;
1024 }
1025 }
1026 else
1027 {
1028 if (ConfigDescriptor)
1029 {
1030 ExFreePool(ConfigDescriptor);
1031 }
1032
1033 *OutDescriptor = NULL;
1034 }
1035
1036 return Status;
1037 }
1038
1039 NTSTATUS
1040 NTAPI
1041 USBH_SyncGetHubDescriptor(IN PUSBHUB_FDO_EXTENSION HubExtension)
1042 {
1043 PUSB_EXTHUB_INFORMATION_0 ExtendedHubInfo;
1044 ULONG NumberPorts;
1045 PUSBHUB_PORT_DATA PortData;
1046 USHORT RequestValue;
1047 ULONG NumberOfBytes;
1048 NTSTATUS Status;
1049 PUSB_HUB_DESCRIPTOR HubDescriptor = NULL;
1050 ULONG ix;
1051 ULONG Retry;
1052
1053 DPRINT("USBH_SyncGetHubDescriptor: ... \n");
1054
1055 ExtendedHubInfo = ExAllocatePoolWithTag(NonPagedPool,
1056 sizeof(USB_EXTHUB_INFORMATION_0),
1057 USB_HUB_TAG);
1058
1059 if (!ExtendedHubInfo)
1060 {
1061 Status = STATUS_INSUFFICIENT_RESOURCES;
1062 goto ErrorExit;
1063 }
1064
1065 RtlZeroMemory(ExtendedHubInfo, sizeof(USB_EXTHUB_INFORMATION_0));
1066
1067 Status = USBHUB_GetExtendedHubInfo(HubExtension, ExtendedHubInfo);
1068
1069 if (!NT_SUCCESS(Status))
1070 {
1071 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG);
1072 ExtendedHubInfo = NULL;
1073 }
1074
1075 NumberOfBytes = sizeof(USB_HUB_DESCRIPTOR);
1076
1077 HubDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1078 NumberOfBytes,
1079 USB_HUB_TAG);
1080
1081 if (!HubDescriptor)
1082 {
1083 Status = STATUS_INSUFFICIENT_RESOURCES;
1084 goto ErrorExit;
1085 }
1086
1087 RtlZeroMemory(HubDescriptor, NumberOfBytes);
1088
1089 RequestValue = 0;
1090 Retry = 0;
1091
1092 while (TRUE)
1093 {
1094 while (Retry <= 5)
1095 {
1096 BM_REQUEST_TYPE RequestType;
1097
1098 RequestType.B = 0;
1099 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1100 RequestType.Type = BMREQUEST_STANDARD;
1101 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1102
1103 Status = USBH_Transact(HubExtension,
1104 HubDescriptor,
1105 NumberOfBytes,
1106 BMREQUEST_DEVICE_TO_HOST,
1107 URB_FUNCTION_CLASS_DEVICE,
1108 RequestType,
1109 USB_REQUEST_GET_DESCRIPTOR,
1110 RequestValue,
1111 0);
1112
1113 if (NT_SUCCESS(Status))
1114 {
1115 break;
1116 }
1117
1118 RequestValue = 0x2900; // Hub DescriptorType - 0x29
1119
1120 Retry++;
1121 }
1122
1123 if (HubDescriptor->bDescriptorLength <= NumberOfBytes)
1124 {
1125 break;
1126 }
1127
1128 NumberOfBytes = HubDescriptor->bDescriptorLength;
1129 ExFreePoolWithTag(HubDescriptor, USB_HUB_TAG);
1130
1131 if (Retry >= 5)
1132 {
1133 Status = STATUS_DEVICE_DATA_ERROR;
1134 HubDescriptor = NULL;
1135 goto ErrorExit;
1136 }
1137
1138 HubDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1139 NumberOfBytes,
1140 USB_HUB_TAG);
1141
1142 if (!HubDescriptor)
1143 {
1144 Status = STATUS_INSUFFICIENT_RESOURCES;
1145 goto ErrorExit;
1146 }
1147
1148 RtlZeroMemory(HubDescriptor, NumberOfBytes);
1149 }
1150
1151 NumberPorts = HubDescriptor->bNumberOfPorts;
1152
1153 if (HubExtension->PortData)
1154 {
1155 PortData = HubExtension->PortData;
1156
1157 for (ix = 0; ix < NumberPorts; ix++)
1158 {
1159 PortData[ix].PortStatus.AsUlong32 = 0;
1160
1161 if (ExtendedHubInfo)
1162 {
1163 PortData[ix].PortAttributes = ExtendedHubInfo->Port[ix].PortAttributes;
1164 }
1165 else
1166 {
1167 PortData[ix].PortAttributes = 0;
1168 }
1169
1170 PortData[ix].ConnectionStatus = NoDeviceConnected;
1171
1172 if (PortData[ix].DeviceObject != NULL)
1173 {
1174 PortData[ix].ConnectionStatus = DeviceConnected;
1175 }
1176 }
1177 }
1178 else
1179 {
1180 PortData = NULL;
1181
1182 if (HubDescriptor->bNumberOfPorts)
1183 {
1184 PortData = ExAllocatePoolWithTag(NonPagedPool,
1185 NumberPorts * sizeof(USBHUB_PORT_DATA),
1186 USB_HUB_TAG);
1187 }
1188
1189 if (!PortData)
1190 {
1191 Status = STATUS_INSUFFICIENT_RESOURCES;
1192 goto ErrorExit;
1193 }
1194
1195 RtlZeroMemory(PortData, NumberPorts * sizeof(USBHUB_PORT_DATA));
1196
1197 for (ix = 0; ix < NumberPorts; ix++)
1198 {
1199 PortData[ix].ConnectionStatus = NoDeviceConnected;
1200
1201 if (ExtendedHubInfo)
1202 {
1203 PortData[ix].PortAttributes = ExtendedHubInfo->Port[ix].PortAttributes;
1204 }
1205 }
1206 }
1207
1208 if (!NT_SUCCESS(Status))
1209 {
1210 goto ErrorExit;
1211 }
1212
1213 HubExtension->HubDescriptor = HubDescriptor;
1214
1215 HubExtension->PortData = PortData;
1216
1217 if (ExtendedHubInfo)
1218 {
1219 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG);
1220 }
1221
1222 return Status;
1223
1224 ErrorExit:
1225
1226 if (HubDescriptor)
1227 {
1228 ExFreePoolWithTag(HubDescriptor, USB_HUB_TAG);
1229 }
1230
1231 if (ExtendedHubInfo)
1232 {
1233 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG);
1234 }
1235
1236 return Status;
1237 }
1238
1239 NTSTATUS
1240 NTAPI
1241 USBH_SyncGetStringDescriptor(IN PDEVICE_OBJECT DeviceObject,
1242 IN UCHAR Index,
1243 IN USHORT LanguageId,
1244 IN PUSB_STRING_DESCRIPTOR Descriptor,
1245 IN ULONG NumberOfBytes,
1246 IN PULONG OutLength,
1247 IN BOOLEAN IsValidateLength)
1248 {
1249 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb;
1250 ULONG TransferedLength;
1251 NTSTATUS Status;
1252
1253 DPRINT("USBH_SyncGetStringDescriptor: Index - %x, LanguageId - %x\n",
1254 Index,
1255 LanguageId);
1256
1257 Urb = ExAllocatePoolWithTag(NonPagedPool,
1258 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
1259 USB_HUB_TAG);
1260
1261 if (!Urb)
1262 {
1263 return STATUS_INSUFFICIENT_RESOURCES;
1264 }
1265
1266 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
1267
1268 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
1269 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
1270
1271 Urb->TransferBuffer = Descriptor;
1272 Urb->TransferBufferLength = NumberOfBytes;
1273
1274 Urb->Index = Index;
1275 Urb->DescriptorType = USB_STRING_DESCRIPTOR_TYPE;
1276 Urb->LanguageId = LanguageId;
1277
1278 Status = USBH_SyncSubmitUrb(DeviceObject, (PURB)Urb);
1279
1280 if (!NT_SUCCESS(Status))
1281 {
1282 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1283 return Status;
1284 }
1285
1286 TransferedLength = Urb->TransferBufferLength;
1287
1288 if (TransferedLength > NumberOfBytes)
1289 {
1290 Status = STATUS_DEVICE_DATA_ERROR;
1291 }
1292
1293 if (!NT_SUCCESS(Status))
1294 {
1295 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1296 return Status;
1297 }
1298
1299 if (OutLength)
1300 {
1301 *OutLength = TransferedLength;
1302 }
1303
1304 if (IsValidateLength && TransferedLength != Descriptor->bLength)
1305 {
1306 Status = STATUS_DEVICE_DATA_ERROR;
1307 }
1308
1309 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1310
1311 return Status;
1312 }
1313
1314 NTSTATUS
1315 NTAPI
1316 USBH_SyncGetStatus(IN PDEVICE_OBJECT DeviceObject,
1317 IN PUSHORT OutStatus,
1318 IN USHORT Function,
1319 IN USHORT RequestIndex)
1320 {
1321 struct _URB_CONTROL_GET_STATUS_REQUEST * Urb;
1322 NTSTATUS NtStatus;
1323 USHORT UsbStatus;
1324
1325 DPRINT("USBH_SyncGetStatus: ... \n");
1326
1327 Urb = ExAllocatePoolWithTag(NonPagedPool,
1328 sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST),
1329 USB_HUB_TAG);
1330
1331 if (!Urb)
1332 {
1333 return STATUS_INSUFFICIENT_RESOURCES;
1334 }
1335
1336 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST));
1337
1338 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST);
1339 Urb->Hdr.Function = Function;
1340
1341 Urb->TransferBuffer = &UsbStatus;
1342 Urb->TransferBufferLength = sizeof(UsbStatus);
1343 Urb->Index = RequestIndex;
1344
1345 NtStatus = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb);
1346
1347 *OutStatus = UsbStatus;
1348
1349 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1350
1351 return NtStatus;
1352 }
1353
1354 NTSTATUS
1355 NTAPI
1356 USBH_SyncGetPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension,
1357 IN USHORT Port,
1358 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus,
1359 IN ULONG Length)
1360 {
1361 BM_REQUEST_TYPE RequestType;
1362
1363 DPRINT("USBH_SyncGetPortStatus: Port - %x\n", Port);
1364
1365 RequestType.B = 0;
1366 RequestType.Recipient = BMREQUEST_TO_OTHER;
1367 RequestType.Type = BMREQUEST_CLASS;
1368 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1369
1370 return USBH_Transact(HubExtension,
1371 PortStatus,
1372 Length,
1373 BMREQUEST_DEVICE_TO_HOST,
1374 URB_FUNCTION_CLASS_OTHER,
1375 RequestType,
1376 USB_REQUEST_GET_STATUS,
1377 0,
1378 Port);
1379 }
1380
1381
1382 NTSTATUS
1383 NTAPI
1384 USBH_SyncClearPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension,
1385 IN USHORT Port,
1386 IN USHORT RequestValue)
1387 {
1388 BM_REQUEST_TYPE RequestType;
1389
1390 DPRINT("USBH_SyncClearPortStatus: Port - %x, RequestValue - %x\n",
1391 Port,
1392 RequestValue);
1393
1394 RequestType.B = 0;
1395 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1396 RequestType.Type = BMREQUEST_CLASS;
1397 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1398
1399 return USBH_Transact(HubExtension,
1400 NULL,
1401 0,
1402 BMREQUEST_HOST_TO_DEVICE,
1403 URB_FUNCTION_CLASS_OTHER,
1404 RequestType,
1405 USB_REQUEST_CLEAR_FEATURE,
1406 RequestValue,
1407 Port);
1408 }
1409
1410 NTSTATUS
1411 NTAPI
1412 USBH_SyncPowerOnPort(IN PUSBHUB_FDO_EXTENSION HubExtension,
1413 IN USHORT Port,
1414 IN BOOLEAN IsWait)
1415 {
1416 PUSBHUB_PORT_DATA PortData;
1417 PUSB_HUB_DESCRIPTOR HubDescriptor;
1418 NTSTATUS Status = STATUS_SUCCESS;
1419 BM_REQUEST_TYPE RequestType;
1420 PUSB_PORT_STATUS_AND_CHANGE PortStatus;
1421
1422 DPRINT("USBH_SyncPowerOnPort: Port - %x, IsWait - %x\n", Port, IsWait);
1423
1424 ASSERT(Port > 0);
1425 PortData = &HubExtension->PortData[Port - 1];
1426 PortStatus = &PortData->PortStatus;
1427
1428 if (PortStatus->PortStatus.Usb20PortStatus.CurrentConnectStatus == 1)
1429 {
1430 return Status;
1431 }
1432
1433 RequestType.B = 0;
1434 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1435 RequestType.Type = BMREQUEST_CLASS;
1436 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1437
1438 Status = USBH_Transact(HubExtension,
1439 NULL,
1440 0,
1441 BMREQUEST_HOST_TO_DEVICE,
1442 URB_FUNCTION_CLASS_OTHER,
1443 RequestType,
1444 USB_REQUEST_SET_FEATURE,
1445 USBHUB_FEATURE_PORT_POWER,
1446 Port);
1447
1448 if (NT_SUCCESS(Status))
1449 {
1450 if (IsWait)
1451 {
1452 HubDescriptor = HubExtension->HubDescriptor;
1453 USBH_Wait(2 * HubDescriptor->bPowerOnToPowerGood);
1454 }
1455
1456 PortStatus->PortStatus.Usb20PortStatus.CurrentConnectStatus = 1;
1457 }
1458
1459 return Status;
1460 }
1461
1462 NTSTATUS
1463 NTAPI
1464 USBH_SyncPowerOnPorts(IN PUSBHUB_FDO_EXTENSION HubExtension)
1465 {
1466 PUSB_HUB_DESCRIPTOR HubDescriptor;
1467 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1468 USHORT Port;
1469 UCHAR NumberOfPorts;
1470
1471 DPRINT("USBH_SyncPowerOnPorts: ... \n");
1472
1473 HubDescriptor = HubExtension->HubDescriptor;
1474 NumberOfPorts = HubDescriptor->bNumberOfPorts;
1475
1476 for (Port = 1; Port <= NumberOfPorts; ++Port)
1477 {
1478 Status = USBH_SyncPowerOnPort(HubExtension, Port, 0);
1479
1480 if (!NT_SUCCESS(Status))
1481 {
1482 DPRINT1("USBH_SyncPowerOnPorts: USBH_SyncPowerOnPort() failed - %lX\n",
1483 Status);
1484 break;
1485 }
1486 }
1487
1488 USBH_Wait(2 * HubDescriptor->bPowerOnToPowerGood);
1489
1490 return Status;
1491 }
1492
1493 NTSTATUS
1494 NTAPI
1495 USBH_SyncDisablePort(IN PUSBHUB_FDO_EXTENSION HubExtension,
1496 IN USHORT Port)
1497 {
1498 PUSBHUB_PORT_DATA PortData;
1499 NTSTATUS Status;
1500 BM_REQUEST_TYPE RequestType;
1501
1502 DPRINT("USBH_SyncDisablePort ... \n");
1503
1504 PortData = &HubExtension->PortData[Port - 1];
1505
1506 RequestType.B = 0;
1507 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1508 RequestType.Type = BMREQUEST_CLASS;
1509 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1510
1511 Status = USBH_Transact(HubExtension,
1512 NULL,
1513 0,
1514 BMREQUEST_HOST_TO_DEVICE,
1515 URB_FUNCTION_CLASS_OTHER,
1516 RequestType,
1517 USB_REQUEST_CLEAR_FEATURE,
1518 USBHUB_FEATURE_PORT_ENABLE,
1519 Port);
1520
1521 if (NT_SUCCESS(Status))
1522 {
1523 PortData->PortStatus.PortStatus.Usb20PortStatus.PortEnabledDisabled = 0;
1524 }
1525
1526 return Status;
1527 }
1528
1529 BOOLEAN
1530 NTAPI
1531 USBH_HubIsBusPowered(IN PDEVICE_OBJECT DeviceObject,
1532 IN PUSB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor)
1533 {
1534 BOOLEAN Result;
1535 USHORT UsbStatus;
1536 NTSTATUS Status;
1537
1538 DPRINT("USBH_HubIsBusPowered: ... \n");
1539
1540 Status = USBH_SyncGetStatus(DeviceObject,
1541 &UsbStatus,
1542 URB_FUNCTION_GET_STATUS_FROM_DEVICE,
1543 0);
1544
1545 if (!NT_SUCCESS(Status))
1546 {
1547 Result = (HubConfigDescriptor->bmAttributes & USB_CONFIG_POWERED_MASK)
1548 == USB_CONFIG_BUS_POWERED;
1549 }
1550 else
1551 {
1552 Result = (UsbStatus & USB_GETSTATUS_SELF_POWERED) == 0;
1553 }
1554
1555 return Result;
1556 }
1557
1558 NTSTATUS
1559 NTAPI
1560 USBH_ChangeIndicationAckChangeComplete(IN PDEVICE_OBJECT DeviceObject,
1561 IN PIRP Irp,
1562 IN PVOID Context)
1563 {
1564 PUSBHUB_FDO_EXTENSION HubExtension;
1565 PVOID Event;
1566 USHORT Port;
1567
1568 HubExtension = Context;
1569
1570 DPRINT_SCE("USBH_ChangeIndicationAckChangeComplete: ... \n");
1571
1572 ASSERT(HubExtension->Port > 0);
1573 Port = HubExtension->Port - 1;
1574
1575 HubExtension->PortData[Port].PortStatus = HubExtension->PortStatus;
1576
1577 Event = InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
1578 NULL);
1579
1580 if (Event)
1581 {
1582 KeSetEvent(Event, EVENT_INCREMENT, FALSE);
1583 }
1584
1585 USBH_SubmitStatusChangeTransfer(HubExtension);
1586
1587 if (!InterlockedDecrement(&HubExtension->ResetRequestCount))
1588 {
1589 KeSetEvent(&HubExtension->ResetEvent,
1590 EVENT_INCREMENT,
1591 FALSE);
1592 }
1593
1594 return STATUS_MORE_PROCESSING_REQUIRED;
1595 }
1596
1597 NTSTATUS
1598 NTAPI
1599 USBH_ChangeIndicationAckChange(IN PUSBHUB_FDO_EXTENSION HubExtension,
1600 IN PIRP Irp,
1601 IN struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb,
1602 IN USHORT Port,
1603 IN USHORT RequestValue)
1604 {
1605 PIO_STACK_LOCATION IoStack;
1606 BM_REQUEST_TYPE RequestType;
1607
1608 DPRINT_SCE("USBH_ChangeIndicationAckChange: ... \n");
1609
1610 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
1611 Urb->Hdr.Function = URB_FUNCTION_CLASS_OTHER;
1612 Urb->Hdr.UsbdDeviceHandle = NULL;
1613
1614 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK;
1615 Urb->TransferBufferLength = 0;
1616 Urb->TransferBuffer = NULL;
1617 Urb->TransferBufferMDL = NULL;
1618 Urb->UrbLink = NULL;
1619
1620 RequestType.B = 0;
1621 RequestType.Recipient = BMREQUEST_TO_OTHER;
1622 RequestType.Type = BMREQUEST_CLASS;
1623 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1624
1625 Urb->RequestTypeReservedBits = RequestType.B;
1626 Urb->Request = USB_REQUEST_CLEAR_FEATURE;
1627 Urb->Index = Port;
1628 Urb->Value = RequestValue;
1629
1630 IoInitializeIrp(Irp,
1631 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
1632 HubExtension->LowerDevice->StackSize);
1633
1634 IoStack = IoGetNextIrpStackLocation(Irp);
1635
1636 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1637 IoStack->Parameters.Others.Argument1 = Urb;
1638 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
1639
1640 IoSetCompletionRoutine(Irp,
1641 USBH_ChangeIndicationAckChangeComplete,
1642 HubExtension,
1643 TRUE,
1644 TRUE,
1645 TRUE);
1646
1647 return IoCallDriver(HubExtension->LowerDevice, Irp);
1648 }
1649
1650 NTSTATUS
1651 NTAPI
1652 USBH_ChangeIndicationProcessChange(IN PDEVICE_OBJECT DeviceObject,
1653 IN PIRP Irp,
1654 IN PVOID Context)
1655 {
1656 PUSBHUB_FDO_EXTENSION HubExtension;
1657 PUSBHUB_IO_WORK_ITEM WorkItem;
1658 USHORT RequestValue;
1659
1660 HubExtension = Context;
1661
1662 DPRINT_SCE("USBH_ChangeIndicationProcessChange: PortStatus - %lX\n",
1663 HubExtension->PortStatus.AsUlong32);
1664
1665 if ((NT_SUCCESS(Irp->IoStatus.Status) ||
1666 USBD_SUCCESS(HubExtension->SCEWorkerUrb.Hdr.Status)) &&
1667 (HubExtension->PortStatus.PortChange.Usb20PortChange.ResetChange ||
1668 HubExtension->PortStatus.PortChange.Usb20PortChange.PortEnableDisableChange))
1669 {
1670 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
1671 {
1672 KeSetEvent(&HubExtension->PendingRequestEvent,
1673 EVENT_INCREMENT,
1674 FALSE);
1675 }
1676
1677 USBH_FreeWorkItem(HubExtension->WorkItemToQueue);
1678
1679 HubExtension->WorkItemToQueue = NULL;
1680
1681 if (HubExtension->PortStatus.PortChange.Usb20PortChange.ResetChange)
1682 {
1683 RequestValue = USBHUB_FEATURE_C_PORT_RESET;
1684 }
1685 else
1686 {
1687 RequestValue = USBHUB_FEATURE_C_PORT_ENABLE;
1688 }
1689
1690 USBH_ChangeIndicationAckChange(HubExtension,
1691 HubExtension->ResetPortIrp,
1692 &HubExtension->SCEWorkerUrb,
1693 HubExtension->Port,
1694 RequestValue);
1695 }
1696 else
1697 {
1698 ASSERT(HubExtension->WorkItemToQueue != NULL);
1699
1700 WorkItem = HubExtension->WorkItemToQueue;
1701 HubExtension->WorkItemToQueue = NULL;
1702
1703 USBH_QueueWorkItem(HubExtension, WorkItem);
1704 }
1705
1706 return STATUS_MORE_PROCESSING_REQUIRED;
1707 }
1708
1709 NTSTATUS
1710 NTAPI
1711 USBH_ChangeIndicationQueryChange(IN PUSBHUB_FDO_EXTENSION HubExtension,
1712 IN PIRP Irp,
1713 IN struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb,
1714 IN USHORT Port)
1715 {
1716 PUSBHUB_IO_WORK_ITEM WorkItem;
1717 NTSTATUS Status;
1718 PIO_STACK_LOCATION IoStack;
1719 BM_REQUEST_TYPE RequestType;
1720
1721 DPRINT_SCE("USBH_ChangeIndicationQueryChange: Port - %x\n", Port);
1722
1723 InterlockedIncrement(&HubExtension->PendingRequestCount);
1724
1725 if (!Port)
1726 {
1727 ASSERT(HubExtension->WorkItemToQueue != NULL);
1728
1729 WorkItem = HubExtension->WorkItemToQueue;
1730 HubExtension->WorkItemToQueue = NULL;
1731
1732 USBH_QueueWorkItem(HubExtension, WorkItem);
1733
1734 return STATUS_SUCCESS;
1735 }
1736
1737 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
1738 Urb->Hdr.UsbdDeviceHandle = NULL;
1739 Urb->Hdr.Function = URB_FUNCTION_CLASS_OTHER;
1740
1741 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN;
1742 Urb->TransferBuffer = &HubExtension->PortStatus;
1743 Urb->TransferBufferLength = sizeof(HubExtension->PortStatus);
1744 Urb->TransferBufferMDL = NULL;
1745 Urb->UrbLink = NULL;
1746
1747 RequestType.B = 0;
1748 RequestType.Recipient = BMREQUEST_TO_OTHER;
1749 RequestType.Type = BMREQUEST_CLASS;
1750 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1751
1752 Urb->RequestTypeReservedBits = RequestType.B;
1753 Urb->Request = USB_REQUEST_GET_STATUS;
1754 Urb->Value = 0;
1755 Urb->Index = Port;
1756
1757 HubExtension->Port = Port;
1758
1759 IoInitializeIrp(Irp,
1760 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
1761 HubExtension->LowerDevice->StackSize);
1762
1763 IoStack = IoGetNextIrpStackLocation(Irp);
1764
1765 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1766 IoStack->Parameters.Others.Argument1 = Urb;
1767 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
1768
1769 IoSetCompletionRoutine(Irp,
1770 USBH_ChangeIndicationProcessChange,
1771 HubExtension,
1772 TRUE,
1773 TRUE,
1774 TRUE);
1775
1776 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
1777
1778 return Status;
1779 }
1780
1781 VOID
1782 NTAPI
1783 USBH_ProcessPortStateChange(IN PUSBHUB_FDO_EXTENSION HubExtension,
1784 IN USHORT Port,
1785 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
1786 {
1787 PUSBHUB_PORT_DATA PortData;
1788 USB_20_PORT_CHANGE PortStatusChange;
1789 PDEVICE_OBJECT PortDevice;
1790 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
1791 PVOID SerialNumber;
1792 PVOID DeviceHandle;
1793 USHORT RequestValue;
1794 KIRQL Irql;
1795
1796 DPRINT_SCE("USBH_ProcessPortStateChange ... \n");
1797
1798 ASSERT(Port > 0);
1799 PortData = &HubExtension->PortData[Port - 1];
1800
1801 PortStatusChange = PortStatus->PortChange.Usb20PortChange;
1802
1803 if (PortStatusChange.ConnectStatusChange)
1804 {
1805 PortData->PortStatus = *PortStatus;
1806
1807 USBH_SyncClearPortStatus(HubExtension,
1808 Port,
1809 USBHUB_FEATURE_C_PORT_CONNECTION);
1810
1811 PortData = &HubExtension->PortData[Port - 1];
1812
1813 PortDevice = PortData->DeviceObject;
1814
1815 if (!PortDevice)
1816 {
1817 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations);
1818 return;
1819 }
1820
1821 PortExtension = PortDevice->DeviceExtension;
1822
1823 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_OVERCURRENT_PORT)
1824 {
1825 return;
1826 }
1827
1828 KeAcquireSpinLock(&HubExtension->RelationsWorkerSpinLock, &Irql);
1829
1830 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3)
1831 {
1832 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, Irql);
1833 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations);
1834 return;
1835 }
1836
1837 PortData->DeviceObject = NULL;
1838 PortData->ConnectionStatus = NoDeviceConnected;
1839
1840 HubExtension->HubFlags |= USBHUB_FDO_FLAG_STATE_CHANGING;
1841
1842 InsertTailList(&HubExtension->PdoList, &PortExtension->PortLink);
1843
1844 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, Irql);
1845
1846 SerialNumber = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber,
1847 NULL);
1848
1849 if (SerialNumber)
1850 {
1851 ExFreePoolWithTag(SerialNumber, USB_HUB_TAG);
1852 }
1853
1854 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle,
1855 NULL);
1856
1857 if (DeviceHandle)
1858 {
1859 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0);
1860 USBH_SyncDisablePort(HubExtension, Port);
1861 }
1862
1863 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations);
1864 }
1865 else if (PortStatusChange.PortEnableDisableChange)
1866 {
1867 RequestValue = USBHUB_FEATURE_C_PORT_ENABLE;
1868 PortData->PortStatus = *PortStatus;
1869 USBH_SyncClearPortStatus(HubExtension, Port, RequestValue);
1870 return;
1871 }
1872 else if (PortStatusChange.SuspendChange)
1873 {
1874 DPRINT1("USBH_ProcessPortStateChange: SuspendChange UNIMPLEMENTED. FIXME\n");
1875 DbgBreakPoint();
1876 }
1877 else if (PortStatusChange.OverCurrentIndicatorChange)
1878 {
1879 DPRINT1("USBH_ProcessPortStateChange: OverCurrentIndicatorChange UNIMPLEMENTED. FIXME\n");
1880 DbgBreakPoint();
1881 }
1882 else if (PortStatusChange.ResetChange)
1883 {
1884 RequestValue = USBHUB_FEATURE_C_PORT_RESET;
1885 PortData->PortStatus = *PortStatus;
1886 USBH_SyncClearPortStatus(HubExtension, Port, RequestValue);
1887 }
1888 }
1889
1890 NTSTATUS
1891 NTAPI
1892 USBH_GetPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension,
1893 IN PULONG PortStatus)
1894 {
1895 PIRP Irp;
1896 PIO_STACK_LOCATION IoStack;
1897 NTSTATUS Status;
1898 KEVENT Event;
1899 IO_STATUS_BLOCK IoStatusBlock;
1900
1901 DPRINT("USBH_GetPortStatus ... \n");
1902
1903 *PortStatus = 0;
1904
1905 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1906
1907 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_PORT_STATUS,
1908 HubExtension->LowerDevice,
1909 NULL,
1910 0,
1911 NULL,
1912 0,
1913 TRUE,
1914 &Event,
1915 &IoStatusBlock);
1916
1917 if (!Irp)
1918 {
1919 return STATUS_INSUFFICIENT_RESOURCES;
1920 }
1921
1922 IoStack = IoGetNextIrpStackLocation(Irp);
1923 IoStack->Parameters.Others.Argument1 = PortStatus;
1924
1925 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
1926
1927 if (Status == STATUS_PENDING)
1928 {
1929 KeWaitForSingleObject(&Event,
1930 Suspended,
1931 KernelMode,
1932 FALSE,
1933 NULL);
1934 }
1935 else
1936 {
1937 IoStatusBlock.Status = Status;
1938 }
1939
1940 return IoStatusBlock.Status;
1941 }
1942
1943 NTSTATUS
1944 NTAPI
1945 USBH_EnableParentPort(IN PUSBHUB_FDO_EXTENSION HubExtension)
1946 {
1947 PIRP Irp;
1948 NTSTATUS Status;
1949 KEVENT Event;
1950 IO_STATUS_BLOCK IoStatusBlock;
1951
1952 DPRINT("USBH_EnableParentPort ... \n");
1953
1954 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1955
1956 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_ENABLE_PORT,
1957 HubExtension->LowerDevice,
1958 NULL,
1959 0,
1960 NULL,
1961 0,
1962 TRUE,
1963 &Event,
1964 &IoStatusBlock);
1965
1966 if (!Irp)
1967 {
1968 return STATUS_INSUFFICIENT_RESOURCES;
1969 }
1970
1971 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
1972
1973 if (Status == STATUS_PENDING)
1974 {
1975 KeWaitForSingleObject(&Event,
1976 Suspended,
1977 KernelMode,
1978 FALSE,
1979 NULL);
1980 }
1981 else
1982 {
1983 IoStatusBlock.Status = Status;
1984 }
1985
1986 return IoStatusBlock.Status;
1987 }
1988
1989 NTSTATUS
1990 NTAPI
1991 USBH_ResetInterruptPipe(IN PUSBHUB_FDO_EXTENSION HubExtension)
1992 {
1993 struct _URB_PIPE_REQUEST * Urb;
1994 NTSTATUS Status;
1995
1996 DPRINT("USBH_ResetInterruptPipe ... \n");
1997
1998 Urb = ExAllocatePoolWithTag(NonPagedPool,
1999 sizeof(struct _URB_PIPE_REQUEST),
2000 USB_HUB_TAG);
2001
2002 if (Urb)
2003 {
2004 RtlZeroMemory(Urb, sizeof(struct _URB_PIPE_REQUEST));
2005
2006 Urb->Hdr.Length = sizeof(struct _URB_PIPE_REQUEST);
2007 Urb->Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL;
2008 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle;
2009
2010 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice,
2011 (PURB)Urb);
2012
2013 ExFreePoolWithTag(Urb, USB_HUB_TAG);
2014 }
2015 else
2016 {
2017 Status = STATUS_INSUFFICIENT_RESOURCES;
2018 }
2019
2020 if (NT_SUCCESS(Status))
2021 {
2022 HubExtension->RequestErrors = 0;
2023 }
2024
2025 return Status;
2026 }
2027
2028 NTSTATUS
2029 NTAPI
2030 USBH_ResetHub(IN PUSBHUB_FDO_EXTENSION HubExtension)
2031 {
2032 NTSTATUS Status;
2033 ULONG PortStatusFlags = 0;
2034
2035 DPRINT("USBH_ResetHub: ... \n");
2036
2037 Status = USBH_GetPortStatus(HubExtension, &PortStatusFlags);
2038
2039 if (!NT_SUCCESS(Status))
2040 {
2041 return Status;
2042 }
2043
2044 if (!(PortStatusFlags & USBD_PORT_ENABLED))
2045 {
2046 if (PortStatusFlags & USBD_PORT_CONNECTED)
2047 {
2048 USBH_EnableParentPort(HubExtension);
2049 }
2050 }
2051
2052 Status = USBH_ResetInterruptPipe(HubExtension);
2053
2054 return Status;
2055 }
2056
2057 VOID
2058 NTAPI
2059 USBH_ChangeIndicationWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
2060 IN PVOID Context)
2061 {
2062 PUSBHUB_FDO_EXTENSION LowerHubExtension;
2063 PUSBHUB_PORT_PDO_EXTENSION LowerPortExtension;
2064 PUSBHUB_STATUS_CHANGE_CONTEXT WorkItem;
2065 USB_PORT_STATUS_AND_CHANGE PortStatus;
2066 NTSTATUS Status;
2067 USHORT Port = 0;
2068
2069 DPRINT_SCE("USBH_ChangeIndicationWorker ... \n");
2070
2071 WorkItem = Context;
2072
2073 KeWaitForSingleObject(&HubExtension->HubSemaphore,
2074 Executive,
2075 KernelMode,
2076 FALSE,
2077 NULL);
2078
2079 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING)
2080 {
2081 KeSetEvent(&HubExtension->StatusChangeEvent,
2082 EVENT_INCREMENT,
2083 FALSE);
2084
2085 goto Exit;
2086 }
2087
2088 if (!HubExtension->RequestErrors)
2089 {
2090 goto Enum;
2091 }
2092
2093 DPRINT_SCE("USBH_ChangeIndicationWorker: RequestErrors - %x\n",
2094 HubExtension->RequestErrors);
2095
2096 if (HubExtension->LowerPDO == HubExtension->RootHubPdo)
2097 {
2098 goto Enum;
2099 }
2100
2101 LowerPortExtension = HubExtension->LowerPDO->DeviceExtension;
2102
2103 if (LowerPortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D1_OR_D2)
2104 {
2105 goto Enum;
2106 }
2107
2108 LowerHubExtension = LowerPortExtension->HubExtension;
2109
2110 if (!LowerHubExtension)
2111 {
2112 goto Enum;
2113 }
2114
2115 Status = USBH_SyncGetPortStatus(LowerHubExtension,
2116 LowerPortExtension->PortNumber,
2117 &PortStatus,
2118 sizeof(USB_PORT_STATUS_AND_CHANGE));
2119
2120 if (!NT_SUCCESS(Status) ||
2121 !PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus)
2122 {
2123 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_REMOVED;
2124
2125 KeSetEvent(&HubExtension->StatusChangeEvent,
2126 EVENT_INCREMENT,
2127 FALSE);
2128
2129 goto Exit;
2130 }
2131
2132 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING))
2133 {
2134 HubExtension->HubFlags |= USBHUB_FDO_FLAG_ESD_RECOVERING;
2135
2136 DPRINT1("USBH_ChangeIndicationWorker: USBHUB_FDO_FLAG_ESD_RECOVERING FIXME\n");
2137 DbgBreakPoint();
2138
2139 goto Exit;
2140 }
2141
2142 Enum:
2143
2144 if (WorkItem->IsRequestErrors)
2145 {
2146 USBH_ResetHub(HubExtension);
2147 }
2148 else
2149 {
2150 for (Port = 0;
2151 Port < HubExtension->HubDescriptor->bNumberOfPorts;
2152 Port++)
2153 {
2154 if (IsBitSet((PUCHAR)(WorkItem + 1), Port))
2155 {
2156 break;
2157 }
2158 }
2159
2160 if (Port)
2161 {
2162 Status = USBH_SyncGetPortStatus(HubExtension,
2163 Port,
2164 &PortStatus,
2165 sizeof(USB_PORT_STATUS_AND_CHANGE));
2166 }
2167 else
2168 {
2169 DPRINT1("USBH_ChangeIndicationWorker: USBH_SyncGetHubStatus() UNIMPLEMENTED. FIXME\n");
2170 DbgBreakPoint();
2171 Status = STATUS_ASSERTION_FAILURE;
2172 }
2173
2174 if (NT_SUCCESS(Status))
2175 {
2176 if (Port)
2177 {
2178 USBH_ProcessPortStateChange(HubExtension,
2179 Port,
2180 &PortStatus);
2181 }
2182 else
2183 {
2184 DPRINT1("USBH_ChangeIndicationWorker: USBH_ProcessHubStateChange() UNIMPLEMENTED. FIXME\n");
2185 DbgBreakPoint();
2186 }
2187 }
2188 else
2189 {
2190 HubExtension->RequestErrors++;
2191
2192 if (HubExtension->RequestErrors > USBHUB_MAX_REQUEST_ERRORS)
2193 {
2194 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED;
2195 goto Exit;
2196 }
2197 }
2198 }
2199
2200 USBH_SubmitStatusChangeTransfer(HubExtension);
2201
2202 Exit:
2203
2204 KeReleaseSemaphore(&HubExtension->HubSemaphore,
2205 LOW_REALTIME_PRIORITY,
2206 1,
2207 FALSE);
2208
2209 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
2210 {
2211 KeSetEvent(&HubExtension->PendingRequestEvent,
2212 EVENT_INCREMENT,
2213 FALSE);
2214 }
2215
2216 if (!InterlockedDecrement((PLONG)&HubExtension->ResetRequestCount))
2217 {
2218 KeSetEvent(&HubExtension->ResetEvent,
2219 EVENT_INCREMENT,
2220 FALSE);
2221
2222 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEFER_CHECK_IDLE)
2223 {
2224 USBH_CheckHubIdle(HubExtension);
2225 }
2226 }
2227 }
2228
2229 NTSTATUS
2230 NTAPI
2231 USBH_ChangeIndication(IN PDEVICE_OBJECT DeviceObject,
2232 IN PIRP Irp,
2233 IN PVOID Context)
2234 {
2235 PUSBHUB_FDO_EXTENSION HubExtension;
2236 USBD_STATUS UrbStatus;
2237 BOOLEAN IsErrors = FALSE;
2238 PUSBHUB_IO_WORK_ITEM HubWorkItem;
2239 PUSBHUB_STATUS_CHANGE_CONTEXT HubWorkItemBuffer;
2240 USHORT NumPorts;
2241 USHORT Port;
2242 NTSTATUS Status;
2243 PVOID Bitmap;
2244 ULONG BufferLength;
2245
2246 HubExtension = Context;
2247 UrbStatus = HubExtension->SCEWorkerUrb.Hdr.Status;
2248
2249 DPRINT_SCE("USBH_ChangeIndication: IrpStatus - %x, UrbStatus - %x, HubFlags - %lX\n",
2250 Irp->IoStatus.Status,
2251 UrbStatus,
2252 HubExtension->HubFlags);
2253
2254 if (NT_ERROR(Irp->IoStatus.Status) || USBD_ERROR(UrbStatus) ||
2255 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) ||
2256 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING))
2257 {
2258 HubExtension->RequestErrors++;
2259
2260 IsErrors = TRUE;
2261
2262 KeSetEvent(&HubExtension->StatusChangeEvent,
2263 EVENT_INCREMENT,
2264 FALSE);
2265
2266 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING ||
2267 HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED ||
2268 HubExtension->RequestErrors > USBHUB_MAX_REQUEST_ERRORS ||
2269 Irp->IoStatus.Status == STATUS_DELETE_PENDING)
2270 {
2271 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n",
2272 HubExtension->RequestErrors);
2273
2274 return STATUS_MORE_PROCESSING_REQUIRED;
2275 }
2276
2277 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n",
2278 HubExtension->RequestErrors);
2279 }
2280 else
2281 {
2282 HubExtension->RequestErrors = 0;
2283 }
2284
2285 BufferLength = sizeof(USBHUB_STATUS_CHANGE_CONTEXT) +
2286 HubExtension->SCEBitmapLength;
2287
2288 Status = USBH_AllocateWorkItem(HubExtension,
2289 &HubWorkItem,
2290 USBH_ChangeIndicationWorker,
2291 BufferLength,
2292 (PVOID *)&HubWorkItemBuffer,
2293 DelayedWorkQueue);
2294
2295 if (!NT_SUCCESS(Status))
2296 {
2297 return STATUS_MORE_PROCESSING_REQUIRED;
2298 }
2299
2300 RtlZeroMemory(HubWorkItemBuffer, BufferLength);
2301
2302 HubWorkItemBuffer->IsRequestErrors = FALSE;
2303
2304 if (IsErrors)
2305 {
2306 HubWorkItemBuffer->IsRequestErrors = TRUE;
2307 }
2308
2309 if (InterlockedIncrement(&HubExtension->ResetRequestCount) == 1)
2310 {
2311 KeResetEvent(&HubExtension->ResetEvent);
2312 }
2313
2314 HubWorkItemBuffer->HubExtension = HubExtension;
2315
2316 HubExtension->WorkItemToQueue = HubWorkItem;
2317
2318 Bitmap = HubWorkItemBuffer + 1;
2319
2320 RtlCopyMemory(Bitmap,
2321 HubExtension->SCEBitmap,
2322 HubExtension->SCEBitmapLength);
2323
2324 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts;
2325
2326 for (Port = 0; Port <= NumPorts; ++Port)
2327 {
2328 if (IsBitSet(Bitmap, Port))
2329 {
2330 break;
2331 }
2332 }
2333
2334 if (Port > NumPorts)
2335 {
2336 Port = 0;
2337 }
2338
2339 Status = USBH_ChangeIndicationQueryChange(HubExtension,
2340 HubExtension->ResetPortIrp,
2341 &HubExtension->SCEWorkerUrb,
2342 Port);
2343
2344 if (NT_ERROR(Status))
2345 {
2346 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED;
2347 }
2348
2349 return STATUS_MORE_PROCESSING_REQUIRED;
2350 }
2351
2352 NTSTATUS
2353 NTAPI
2354 USBH_SubmitStatusChangeTransfer(IN PUSBHUB_FDO_EXTENSION HubExtension)
2355 {
2356 PIRP Irp;
2357 NTSTATUS Status;
2358 struct _URB_BULK_OR_INTERRUPT_TRANSFER * Urb;
2359 PIO_STACK_LOCATION IoStack;
2360
2361 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: HubExtension - %p, SCEIrp - %p\n",
2362 HubExtension,
2363 HubExtension->SCEIrp);
2364
2365 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_NOT_D0_STATE)
2366 {
2367 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: USBHUB_FDO_FLAG_NOT_D0_STATE\n");
2368 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: HubFlags - %lX\n",
2369 HubExtension->HubFlags);
2370
2371 return STATUS_INVALID_DEVICE_STATE;
2372 }
2373
2374 Irp = HubExtension->SCEIrp;
2375
2376 if (!Irp)
2377 {
2378 return STATUS_INVALID_DEVICE_STATE;
2379 }
2380
2381 Urb = (struct _URB_BULK_OR_INTERRUPT_TRANSFER *)&HubExtension->SCEWorkerUrb;
2382
2383 Urb->Hdr.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
2384 Urb->Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
2385 Urb->Hdr.UsbdDeviceHandle = NULL;
2386
2387 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle;
2388 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK;
2389 Urb->TransferBuffer = HubExtension->SCEBitmap;
2390 Urb->TransferBufferLength = HubExtension->SCEBitmapLength;
2391 Urb->TransferBufferMDL = NULL;
2392 Urb->UrbLink = NULL;
2393
2394 IoInitializeIrp(Irp,
2395 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
2396 HubExtension->LowerDevice->StackSize);
2397
2398 IoStack = IoGetNextIrpStackLocation(Irp);
2399
2400 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
2401 IoStack->Parameters.Others.Argument1 = &HubExtension->SCEWorkerUrb;
2402 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
2403
2404 IoSetCompletionRoutine(Irp,
2405 USBH_ChangeIndication,
2406 HubExtension,
2407 TRUE,
2408 TRUE,
2409 TRUE);
2410
2411 KeResetEvent(&HubExtension->StatusChangeEvent);
2412
2413 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
2414
2415 return Status;
2416 }
2417
2418 NTSTATUS
2419 NTAPI
2420 USBD_CreateDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension,
2421 IN PUSB_DEVICE_HANDLE * OutDeviceHandle,
2422 IN USB_PORT_STATUS UsbPortStatus,
2423 IN USHORT Port)
2424 {
2425 PUSB_DEVICE_HANDLE HubDeviceHandle;
2426 PUSB_BUSIFFN_CREATE_USB_DEVICE CreateUsbDevice;
2427
2428 DPRINT("USBD_CreateDeviceEx: Port - %x, UsbPortStatus - 0x%04X\n",
2429 Port,
2430 UsbPortStatus.AsUshort16);
2431
2432 CreateUsbDevice = HubExtension->BusInterface.CreateUsbDevice;
2433
2434 if (!CreateUsbDevice)
2435 {
2436 return STATUS_NOT_IMPLEMENTED;
2437 }
2438
2439 HubDeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice);
2440
2441 return CreateUsbDevice(HubExtension->BusInterface.BusContext,
2442 OutDeviceHandle,
2443 HubDeviceHandle,
2444 UsbPortStatus.AsUshort16,
2445 Port);
2446 }
2447
2448 NTSTATUS
2449 NTAPI
2450 USBD_RemoveDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension,
2451 IN PUSB_DEVICE_HANDLE DeviceHandle,
2452 IN ULONG Flags)
2453 {
2454 PUSB_BUSIFFN_REMOVE_USB_DEVICE RemoveUsbDevice;
2455
2456 DPRINT("USBD_RemoveDeviceEx: DeviceHandle - %p, Flags - %X\n",
2457 DeviceHandle,
2458 Flags);
2459
2460 RemoveUsbDevice = HubExtension->BusInterface.RemoveUsbDevice;
2461
2462 if (!RemoveUsbDevice)
2463 {
2464 return STATUS_NOT_IMPLEMENTED;
2465 }
2466
2467 return RemoveUsbDevice(HubExtension->BusInterface.BusContext,
2468 DeviceHandle,
2469 Flags);
2470 }
2471
2472 NTSTATUS
2473 NTAPI
2474 USBD_InitializeDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension,
2475 IN PUSB_DEVICE_HANDLE DeviceHandle,
2476 IN PUCHAR DeviceDescriptorBuffer,
2477 IN ULONG DeviceDescriptorBufferLength,
2478 IN PUCHAR ConfigDescriptorBuffer,
2479 IN ULONG ConfigDescriptorBufferLength)
2480 {
2481 NTSTATUS Status;
2482 PUSB_BUSIFFN_INITIALIZE_USB_DEVICE InitializeUsbDevice;
2483 PUSB_BUSIFFN_GET_USB_DESCRIPTORS GetUsbDescriptors;
2484
2485 DPRINT("USBD_InitializeDeviceEx: ... \n");
2486
2487 InitializeUsbDevice = HubExtension->BusInterface.InitializeUsbDevice;
2488 GetUsbDescriptors = HubExtension->BusInterface.GetUsbDescriptors;
2489
2490 if (!InitializeUsbDevice || !GetUsbDescriptors)
2491 {
2492 return STATUS_NOT_IMPLEMENTED;
2493 }
2494
2495 Status = InitializeUsbDevice(HubExtension->BusInterface.BusContext,
2496 DeviceHandle);
2497
2498 if (!NT_SUCCESS(Status))
2499 {
2500 return Status;
2501 }
2502
2503 return GetUsbDescriptors(HubExtension->BusInterface.BusContext,
2504 DeviceHandle,
2505 DeviceDescriptorBuffer,
2506 &DeviceDescriptorBufferLength,
2507 ConfigDescriptorBuffer,
2508 &ConfigDescriptorBufferLength);
2509 }
2510
2511 VOID
2512 NTAPI
2513 USBHUB_SetDeviceHandleData(IN PUSBHUB_FDO_EXTENSION HubExtension,
2514 IN PDEVICE_OBJECT UsbDevicePdo,
2515 IN PVOID DeviceHandle)
2516 {
2517 PUSB_BUSIFFN_SET_DEVHANDLE_DATA SetDeviceHandleData;
2518
2519 DPRINT("USBHUB_SetDeviceHandleData ... \n");
2520
2521 SetDeviceHandleData = HubExtension->BusInterface.SetDeviceHandleData;
2522
2523 if (!SetDeviceHandleData)
2524 {
2525 return;
2526 }
2527
2528 SetDeviceHandleData(HubExtension->BusInterface.BusContext,
2529 DeviceHandle,
2530 UsbDevicePdo);
2531 }
2532
2533 VOID
2534 NTAPI
2535 USBHUB_FlushAllTransfers(IN PUSBHUB_FDO_EXTENSION HubExtension)
2536 {
2537 PUSB_BUSIFFN_FLUSH_TRANSFERS FlushTransfers;
2538
2539 DPRINT("USBHUB_FlushAllTransfers ... \n");
2540
2541 FlushTransfers = HubExtension->BusInterface.FlushTransfers;
2542
2543 if (FlushTransfers)
2544 {
2545 FlushTransfers(HubExtension->BusInterface.BusContext, NULL);
2546 }
2547 }
2548
2549 NTSTATUS
2550 NTAPI
2551 USBD_GetDeviceInformationEx(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
2552 IN PUSBHUB_FDO_EXTENSION HubExtension,
2553 IN PUSB_NODE_CONNECTION_INFORMATION_EX Info,
2554 IN ULONG Length,
2555 IN PUSB_DEVICE_HANDLE DeviceHandle)
2556 {
2557 PUSB_BUSIFFN_GET_DEVICE_INFORMATION QueryDeviceInformation;
2558 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
2559 SIZE_T DeviceInfoLength;
2560 PUSB_NODE_CONNECTION_INFORMATION_EX NodeInfo;
2561 SIZE_T NodeInfoLength;
2562 ULONG PipeNumber;
2563 ULONG dummy;
2564 NTSTATUS Status;
2565
2566 DPRINT("USBD_GetDeviceInformationEx ... \n");
2567
2568 QueryDeviceInformation = HubExtension->BusInterface.QueryDeviceInformation;
2569
2570 if (!QueryDeviceInformation)
2571 {
2572 Status = STATUS_NOT_IMPLEMENTED;
2573 return Status;
2574 }
2575
2576 DeviceInfoLength = sizeof(USB_DEVICE_INFORMATION_0);
2577
2578 while (TRUE)
2579 {
2580 DeviceInfo = ExAllocatePoolWithTag(PagedPool,
2581 DeviceInfoLength,
2582 USB_HUB_TAG);
2583
2584 if (!DeviceInfo)
2585 {
2586 return STATUS_INSUFFICIENT_RESOURCES;
2587 }
2588
2589 RtlZeroMemory(DeviceInfo, DeviceInfoLength);
2590
2591 DeviceInfo->InformationLevel = 0;
2592
2593 Status = QueryDeviceInformation(HubExtension->BusInterface.BusContext,
2594 DeviceHandle,
2595 DeviceInfo,
2596 DeviceInfoLength,
2597 &dummy);
2598
2599 if (Status != STATUS_BUFFER_TOO_SMALL)
2600 {
2601 break;
2602 }
2603
2604 DeviceInfoLength = DeviceInfo->ActualLength;
2605
2606 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
2607 }
2608
2609 NodeInfo = NULL;
2610 NodeInfoLength = 0;
2611
2612 if (NT_SUCCESS(Status))
2613 {
2614 NodeInfoLength = (sizeof(USB_NODE_CONNECTION_INFORMATION_EX) - sizeof(USB_PIPE_INFO)) +
2615 DeviceInfo->NumberOfOpenPipes * sizeof(USB_PIPE_INFO);
2616
2617 NodeInfo = ExAllocatePoolWithTag(PagedPool, NodeInfoLength, USB_HUB_TAG);
2618
2619 if (!NodeInfo)
2620 {
2621 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
2622 return STATUS_INSUFFICIENT_RESOURCES;
2623 }
2624
2625 RtlZeroMemory(NodeInfo, NodeInfoLength);
2626
2627 NodeInfo->ConnectionIndex = Info->ConnectionIndex;
2628
2629 RtlCopyMemory(&NodeInfo->DeviceDescriptor,
2630 &DeviceInfo->DeviceDescriptor,
2631 sizeof(USB_DEVICE_DESCRIPTOR));
2632
2633 NodeInfo->CurrentConfigurationValue = DeviceInfo->CurrentConfigurationValue;
2634 NodeInfo->Speed = DeviceInfo->DeviceSpeed;
2635 NodeInfo->DeviceIsHub = PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE;
2636 NodeInfo->DeviceAddress = DeviceInfo->DeviceAddress;
2637 NodeInfo->NumberOfOpenPipes = DeviceInfo->NumberOfOpenPipes;
2638 NodeInfo->ConnectionStatus = Info->ConnectionStatus;
2639
2640 for (PipeNumber = 0;
2641 PipeNumber < DeviceInfo->NumberOfOpenPipes;
2642 PipeNumber++)
2643 {
2644 RtlCopyMemory(&NodeInfo->PipeList[PipeNumber],
2645 &DeviceInfo->PipeList[PipeNumber],
2646 sizeof(USB_PIPE_INFO));
2647 }
2648 }
2649
2650 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
2651
2652 if (NodeInfo)
2653 {
2654 if (NodeInfoLength <= Length)
2655 {
2656 Length = NodeInfoLength;
2657 }
2658 else
2659 {
2660 Status = STATUS_BUFFER_TOO_SMALL;
2661 }
2662
2663 RtlCopyMemory(Info, NodeInfo, Length);
2664
2665 ExFreePoolWithTag(NodeInfo, USB_HUB_TAG);
2666 }
2667
2668 return Status;
2669 }
2670
2671 NTSTATUS
2672 NTAPI
2673 USBD_RestoreDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension,
2674 IN OUT PUSB_DEVICE_HANDLE OldDeviceHandle,
2675 IN OUT PUSB_DEVICE_HANDLE NewDeviceHandle)
2676 {
2677 PUSB_BUSIFFN_RESTORE_DEVICE RestoreUsbDevice;
2678 NTSTATUS Status;
2679
2680 DPRINT("USBD_RestoreDeviceEx: HubExtension - %p, OldDeviceHandle - %p, NewDeviceHandle - %p\n",
2681 HubExtension,
2682 OldDeviceHandle,
2683 NewDeviceHandle);
2684
2685 RestoreUsbDevice = HubExtension->BusInterface.RestoreUsbDevice;
2686
2687 if (RestoreUsbDevice)
2688 {
2689 Status = RestoreUsbDevice(HubExtension->BusInterface.BusContext,
2690 OldDeviceHandle,
2691 NewDeviceHandle);
2692 }
2693 else
2694 {
2695 Status = STATUS_NOT_IMPLEMENTED;
2696 }
2697
2698 return Status;
2699 }
2700
2701 NTSTATUS
2702 NTAPI
2703 USBH_AllocateWorkItem(PUSBHUB_FDO_EXTENSION HubExtension,
2704 PUSBHUB_IO_WORK_ITEM * OutHubIoWorkItem,
2705 PUSBHUB_WORKER_ROUTINE WorkerRoutine,
2706 SIZE_T BufferLength,
2707 PVOID * OutHubWorkItemBuffer,
2708 WORK_QUEUE_TYPE Type)
2709 {
2710 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
2711 PIO_WORKITEM WorkItem;
2712 PVOID WorkItemBuffer;
2713
2714 DPRINT("USBH_AllocateWorkItem: ... \n");
2715
2716 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_WITEM_INIT))
2717 {
2718 return STATUS_INVALID_PARAMETER;
2719 }
2720
2721 HubIoWorkItem = ExAllocatePoolWithTag(NonPagedPool,
2722 sizeof(USBHUB_IO_WORK_ITEM),
2723 USB_HUB_TAG);
2724
2725 if (!HubIoWorkItem)
2726 {
2727 return STATUS_INSUFFICIENT_RESOURCES;
2728 }
2729
2730 RtlZeroMemory(HubIoWorkItem, sizeof(USBHUB_IO_WORK_ITEM));
2731
2732 WorkItem = IoAllocateWorkItem(HubExtension->Common.SelfDevice);
2733
2734 HubIoWorkItem->HubWorkItem = WorkItem;
2735
2736 if (!WorkItem)
2737 {
2738 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2739 return STATUS_INSUFFICIENT_RESOURCES;
2740 }
2741
2742 if (BufferLength && OutHubWorkItemBuffer)
2743 {
2744 WorkItemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2745 BufferLength,
2746 USB_HUB_TAG);
2747
2748 HubIoWorkItem->HubWorkItemBuffer = WorkItemBuffer;
2749
2750 if (!WorkItemBuffer)
2751 {
2752 IoFreeWorkItem(HubIoWorkItem->HubWorkItem);
2753 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2754
2755 return STATUS_INSUFFICIENT_RESOURCES;
2756 }
2757
2758 RtlZeroMemory(WorkItemBuffer, BufferLength);
2759 }
2760 else
2761 {
2762 HubIoWorkItem->HubWorkItemBuffer = NULL;
2763 }
2764
2765 HubIoWorkItem->HubWorkItemType = Type;
2766 HubIoWorkItem->HubExtension = HubExtension;
2767 HubIoWorkItem->HubWorkerRoutine = WorkerRoutine;
2768
2769 if (OutHubIoWorkItem)
2770 {
2771 *OutHubIoWorkItem = HubIoWorkItem;
2772 }
2773
2774 if (OutHubWorkItemBuffer)
2775 {
2776 *OutHubWorkItemBuffer = HubIoWorkItem->HubWorkItemBuffer;
2777 }
2778
2779 return STATUS_SUCCESS;
2780 }
2781
2782 VOID
2783 NTAPI
2784 USBH_Worker(IN PDEVICE_OBJECT DeviceObject,
2785 IN PVOID Context)
2786 {
2787 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
2788 PUSBHUB_FDO_EXTENSION HubExtension;
2789 KIRQL OldIrql;
2790 PIO_WORKITEM WorkItem;
2791
2792 DPRINT("USBH_Worker: HubIoWorkItem - %p\n", Context);
2793
2794 HubIoWorkItem = Context;
2795
2796 InterlockedDecrement(&HubIoWorkItem->HubWorkerQueued);
2797
2798 HubExtension = HubIoWorkItem->HubExtension;
2799 WorkItem = HubIoWorkItem->HubWorkItem;
2800
2801 HubIoWorkItem->HubWorkerRoutine(HubIoWorkItem->HubExtension,
2802 HubIoWorkItem->HubWorkItemBuffer);
2803
2804 KeAcquireSpinLock(&HubExtension->WorkItemSpinLock, &OldIrql);
2805 RemoveEntryList(&HubIoWorkItem->HubWorkItemLink);
2806 KeReleaseSpinLock(&HubExtension->WorkItemSpinLock, OldIrql);
2807
2808 if (HubIoWorkItem->HubWorkItemBuffer)
2809 {
2810 ExFreePoolWithTag(HubIoWorkItem->HubWorkItemBuffer, USB_HUB_TAG);
2811 }
2812
2813 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2814
2815 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
2816 {
2817 KeSetEvent(&HubExtension->PendingRequestEvent,
2818 EVENT_INCREMENT,
2819 FALSE);
2820 }
2821
2822 IoFreeWorkItem(WorkItem);
2823
2824 DPRINT("USBH_Worker: HubIoWorkItem %p complete\n", Context);
2825 }
2826
2827 VOID
2828 NTAPI
2829 USBH_QueueWorkItem(IN PUSBHUB_FDO_EXTENSION HubExtension,
2830 IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem)
2831 {
2832 DPRINT("USBH_QueueWorkItem: ... \n");
2833
2834 InterlockedIncrement(&HubExtension->PendingRequestCount);
2835 InterlockedIncrement(&HubIoWorkItem->HubWorkerQueued);
2836
2837 ExInterlockedInsertTailList(&HubExtension->WorkItemList,
2838 &HubIoWorkItem->HubWorkItemLink,
2839 &HubExtension->WorkItemSpinLock);
2840
2841 IoQueueWorkItem(HubIoWorkItem->HubWorkItem,
2842 USBH_Worker,
2843 HubIoWorkItem->HubWorkItemType,
2844 HubIoWorkItem);
2845 }
2846
2847 VOID
2848 NTAPI
2849 USBH_FreeWorkItem(IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem)
2850 {
2851 PIO_WORKITEM WorkItem;
2852
2853 DPRINT("USBH_FreeWorkItem: ... \n");
2854
2855 WorkItem = HubIoWorkItem->HubWorkItem;
2856
2857 if (HubIoWorkItem->HubWorkItemBuffer)
2858 {
2859 ExFreePoolWithTag(HubIoWorkItem->HubWorkItemBuffer, USB_HUB_TAG);
2860 }
2861
2862 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2863
2864 IoFreeWorkItem(WorkItem);
2865 }
2866
2867 VOID
2868 NTAPI
2869 USBHUB_RootHubCallBack(IN PVOID Context)
2870 {
2871 PUSBHUB_FDO_EXTENSION HubExtension;
2872
2873 DPRINT("USBHUB_RootHubCallBack: ... \n");
2874
2875 HubExtension = Context;
2876
2877 if (HubExtension->SCEIrp)
2878 {
2879 HubExtension->HubFlags |= (USBHUB_FDO_FLAG_DO_ENUMERATION |
2880 USBHUB_FDO_FLAG_NOT_ENUMERATED);
2881
2882 USBH_SubmitStatusChangeTransfer(HubExtension);
2883
2884 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations);
2885 }
2886 else
2887 {
2888 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_ENUMERATION;
2889 }
2890
2891 KeSetEvent(&HubExtension->RootHubNotificationEvent,
2892 EVENT_INCREMENT,
2893 FALSE);
2894 }
2895
2896 NTSTATUS
2897 NTAPI
2898 USBD_RegisterRootHubCallBack(IN PUSBHUB_FDO_EXTENSION HubExtension)
2899 {
2900 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification;
2901
2902 DPRINT("USBD_RegisterRootHubCallBack: ... \n");
2903
2904 RootHubInitNotification = HubExtension->BusInterface.RootHubInitNotification;
2905
2906 if (!RootHubInitNotification)
2907 {
2908 return STATUS_NOT_IMPLEMENTED;
2909 }
2910
2911 KeResetEvent(&HubExtension->RootHubNotificationEvent);
2912
2913 return RootHubInitNotification(HubExtension->BusInterface.BusContext,
2914 HubExtension,
2915 USBHUB_RootHubCallBack);
2916 }
2917
2918 NTSTATUS
2919 NTAPI
2920 USBD_UnRegisterRootHubCallBack(IN PUSBHUB_FDO_EXTENSION HubExtension)
2921 {
2922 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification;
2923 NTSTATUS Status;
2924
2925 DPRINT("USBD_UnRegisterRootHubCallBack ... \n");
2926
2927 RootHubInitNotification = HubExtension->BusInterface.RootHubInitNotification;
2928
2929 if (!RootHubInitNotification)
2930 {
2931 return STATUS_NOT_IMPLEMENTED;
2932 }
2933
2934 Status = RootHubInitNotification(HubExtension->BusInterface.BusContext,
2935 NULL,
2936 NULL);
2937
2938 if (!NT_SUCCESS(Status))
2939 {
2940 KeWaitForSingleObject(&HubExtension->RootHubNotificationEvent,
2941 Executive,
2942 KernelMode,
2943 FALSE,
2944 NULL);
2945 }
2946
2947 return Status;
2948 }
2949
2950 VOID
2951 NTAPI
2952 USBH_HubSetDWakeCompletion(IN PDEVICE_OBJECT DeviceObject,
2953 IN UCHAR MinorFunction,
2954 IN POWER_STATE PowerState,
2955 IN PVOID Context,
2956 IN PIO_STATUS_BLOCK IoStatus)
2957 {
2958 DPRINT("USBH_HubSetDWakeCompletion: ... \n");
2959 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
2960 }
2961
2962 VOID
2963 NTAPI
2964 USBH_HubQueuePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,
2965 IN PLIST_ENTRY IdleList)
2966 {
2967 PDEVICE_OBJECT PortDevice;
2968 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
2969 PIRP IdleIrp;
2970 PIRP HubIdleIrp;
2971 ULONG NumPorts;
2972 ULONG Port;
2973 KIRQL Irql;
2974
2975 DPRINT("USBH_HubQueuePortIdleIrps ... \n");
2976
2977 InitializeListHead(IdleList);
2978
2979 IoAcquireCancelSpinLock(&Irql);
2980
2981 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts;
2982
2983 for (Port = 0; Port < NumPorts; ++Port)
2984 {
2985 PortDevice = HubExtension->PortData[Port].DeviceObject;
2986
2987 if (PortDevice)
2988 {
2989 PortExtension = PortDevice->DeviceExtension;
2990
2991 IdleIrp = PortExtension->IdleNotificationIrp;
2992 PortExtension->IdleNotificationIrp = NULL;
2993
2994 if (IdleIrp && IoSetCancelRoutine(IdleIrp, NULL))
2995 {
2996 DPRINT1("USBH_HubQueuePortIdleIrps: IdleIrp != NULL. FIXME\n");
2997 DbgBreakPoint();
2998 }
2999 }
3000 }
3001
3002 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST)
3003 {
3004 HubIdleIrp = HubExtension->PendingIdleIrp;
3005 HubExtension->PendingIdleIrp = NULL;
3006 }
3007 else
3008 {
3009 HubIdleIrp = NULL;
3010 }
3011
3012 IoReleaseCancelSpinLock(Irql);
3013
3014 if (HubIdleIrp)
3015 {
3016 USBH_HubCancelIdleIrp(HubExtension, HubIdleIrp);
3017 }
3018 }
3019
3020 VOID
3021 NTAPI
3022 USBH_HubCompleteQueuedPortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,
3023 IN PLIST_ENTRY IdleList,
3024 IN NTSTATUS NtStatus)
3025 {
3026 DPRINT("USBH_HubCompleteQueuedPortIdleIrps ... \n");
3027
3028 while (!IsListEmpty(IdleList))
3029 {
3030 DPRINT1("USBH_HubCompleteQueuedPortIdleIrps: IdleList not Empty. FIXME\n");
3031 DbgBreakPoint();
3032 }
3033 }
3034
3035 VOID
3036 NTAPI
3037 USBH_FlushPortPwrList(IN PUSBHUB_FDO_EXTENSION HubExtension)
3038 {
3039 PDEVICE_OBJECT PortDevice;
3040 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3041 PLIST_ENTRY Entry;
3042 ULONG Port;
3043
3044 DPRINT("USBH_FlushPortPwrList ... \n");
3045
3046 InterlockedIncrement((PLONG)&HubExtension->PendingRequestCount);
3047
3048 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
3049 Executive,
3050 KernelMode,
3051 FALSE,
3052 NULL);
3053
3054 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; ++Port)
3055 {
3056 PortDevice = HubExtension->PortData[Port].DeviceObject;
3057
3058 if (!PortDevice)
3059 {
3060 continue;
3061 }
3062
3063 PortExtension = PortDevice->DeviceExtension;
3064
3065 InterlockedExchange((PLONG)&PortExtension->StateBehindD2, 0);
3066
3067 while (TRUE)
3068 {
3069 Entry = ExInterlockedRemoveHeadList(&PortExtension->PortPowerList,
3070 &PortExtension->PortPowerListSpinLock);
3071
3072 if (!Entry)
3073 {
3074 break;
3075 }
3076
3077 DPRINT1("USBH_FlushPortPwrList: PortPowerList FIXME\n");
3078 DbgBreakPoint();
3079 }
3080 }
3081
3082 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3083 LOW_REALTIME_PRIORITY,
3084 1,
3085 FALSE);
3086
3087 if (!InterlockedDecrement((PLONG)&HubExtension->PendingRequestCount))
3088 {
3089 KeSetEvent(&HubExtension->PendingRequestEvent,
3090 EVENT_INCREMENT,
3091 FALSE);
3092 }
3093 }
3094
3095 VOID
3096 NTAPI
3097 USBH_HubCompletePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,
3098 IN NTSTATUS NtStatus)
3099 {
3100 LIST_ENTRY IdleList;
3101
3102 DPRINT("USBH_HubCompletePortIdleIrps ... \n");
3103
3104 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED)
3105 {
3106 USBH_HubQueuePortIdleIrps(HubExtension, &IdleList);
3107
3108 USBH_HubCompleteQueuedPortIdleIrps(HubExtension,
3109 &IdleList,
3110 NtStatus);
3111
3112 USBH_FlushPortPwrList(HubExtension);
3113 }
3114 }
3115
3116 VOID
3117 NTAPI
3118 USBH_HubCancelIdleIrp(IN PUSBHUB_FDO_EXTENSION HubExtension,
3119 IN PIRP IdleIrp)
3120 {
3121 DPRINT("USBH_HubCancelIdleIrp ... \n");
3122
3123 IoCancelIrp(IdleIrp);
3124
3125 if (InterlockedExchange(&HubExtension->IdleRequestLock, 1))
3126 {
3127 IoFreeIrp(IdleIrp);
3128 }
3129 }
3130
3131 BOOLEAN
3132 NTAPI
3133 USBH_CheckIdleAbort(IN PUSBHUB_FDO_EXTENSION HubExtension,
3134 IN BOOLEAN IsWait,
3135 IN BOOLEAN IsExtCheck)
3136 {
3137 PDEVICE_OBJECT PdoDevice;
3138 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3139 PUSBHUB_PORT_DATA PortData;
3140 ULONG Port;
3141 BOOLEAN Result = FALSE;
3142
3143 DPRINT("USBH_CheckIdleAbort: ... \n");
3144
3145 InterlockedIncrement(&HubExtension->PendingRequestCount);
3146
3147 if (IsWait == TRUE)
3148 {
3149 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
3150 Executive,
3151 KernelMode,
3152 FALSE,
3153 NULL);
3154 }
3155
3156 PortData = HubExtension->PortData;
3157
3158 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; Port++)
3159 {
3160 PdoDevice = PortData[Port].DeviceObject;
3161
3162 if (PdoDevice)
3163 {
3164 PortExtension = PdoDevice->DeviceExtension;
3165
3166 if (PortExtension->PoRequestCounter)
3167 {
3168 Result = TRUE;
3169 goto Wait;
3170 }
3171 }
3172 }
3173
3174 if (IsExtCheck == TRUE)
3175 {
3176 PortData = HubExtension->PortData;
3177
3178 for (Port = 0;
3179 Port < HubExtension->HubDescriptor->bNumberOfPorts;
3180 Port++)
3181 {
3182 PdoDevice = PortData[Port].DeviceObject;
3183
3184 if (PdoDevice)
3185 {
3186 PortExtension = PdoDevice->DeviceExtension;
3187 InterlockedExchange(&PortExtension->StateBehindD2, 0);
3188 }
3189 }
3190 }
3191
3192 Wait:
3193
3194 if (IsWait == TRUE)
3195 {
3196 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3197 LOW_REALTIME_PRIORITY,
3198 1,
3199 FALSE);
3200 }
3201
3202 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3203 {
3204 KeSetEvent(&HubExtension->PendingRequestEvent,
3205 EVENT_INCREMENT,
3206 FALSE);
3207 }
3208
3209 return Result;
3210 }
3211
3212 VOID
3213 NTAPI
3214 USBH_FdoWaitWakeIrpCompletion(IN PDEVICE_OBJECT DeviceObject,
3215 IN UCHAR MinorFunction,
3216 IN POWER_STATE PowerState,
3217 IN PVOID Context,
3218 IN PIO_STATUS_BLOCK IoStatus)
3219 {
3220 DPRINT("USBH_FdoWaitWakeIrpCompletion ... \n");
3221 }
3222
3223 NTSTATUS
3224 NTAPI
3225 USBH_FdoSubmitWaitWakeIrp(IN PUSBHUB_FDO_EXTENSION HubExtension)
3226 {
3227 POWER_STATE PowerState;
3228 NTSTATUS Status;
3229 PIRP Irp = NULL;
3230 KIRQL Irql;
3231
3232 DPRINT("USBH_FdoSubmitWaitWakeIrp: ... \n");
3233
3234 PowerState.SystemState = HubExtension->SystemWake;
3235 HubExtension->HubFlags |= USBHUB_FDO_FLAG_PENDING_WAKE_IRP;
3236
3237 InterlockedIncrement(&HubExtension->PendingRequestCount);
3238 InterlockedExchange(&HubExtension->FdoWaitWakeLock, 0);
3239
3240 Status = PoRequestPowerIrp(HubExtension->LowerPDO,
3241 IRP_MN_WAIT_WAKE,
3242 PowerState,
3243 USBH_FdoWaitWakeIrpCompletion,
3244 HubExtension,
3245 &Irp);
3246
3247 IoAcquireCancelSpinLock(&Irql);
3248
3249 if (Status == STATUS_PENDING)
3250 {
3251 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_PENDING_WAKE_IRP)
3252 {
3253 HubExtension->PendingWakeIrp = Irp;
3254 DPRINT("USBH_FdoSubmitWaitWakeIrp: PendingWakeIrp - %p\n",
3255 HubExtension->PendingWakeIrp);
3256 }
3257 }
3258 else
3259 {
3260 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_PENDING_WAKE_IRP;
3261
3262 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3263 {
3264 KeSetEvent(&HubExtension->PendingRequestEvent,
3265 EVENT_INCREMENT,
3266 FALSE);
3267 }
3268 }
3269
3270 IoReleaseCancelSpinLock(Irql);
3271
3272 return Status;
3273 }
3274
3275 VOID
3276 NTAPI
3277 USBH_FdoIdleNotificationCallback(IN PVOID Context)
3278 {
3279 PUSBHUB_FDO_EXTENSION HubExtension;
3280 PUSBHUB_PORT_DATA PortData;
3281 PDEVICE_OBJECT PortDevice;
3282 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3283 PIRP Irp = NULL;
3284 PIRP IdleIrp;
3285 POWER_STATE PowerState;
3286 KEVENT Event;
3287 ULONG Port;
3288 PIO_STACK_LOCATION IoStack;
3289 PUSB_IDLE_CALLBACK_INFO CallbackInfo;
3290 BOOLEAN IsReady;
3291 KIRQL OldIrql;
3292 NTSTATUS Status;
3293
3294 HubExtension = Context;
3295
3296 DPRINT("USBH_FdoIdleNotificationCallback: HubExtension - %p, HubFlags - %lX\n",
3297 HubExtension,
3298 HubExtension->HubFlags);
3299
3300 if (HubExtension->HubFlags & (USBHUB_FDO_FLAG_ENUM_POST_RECOVER |
3301 USBHUB_FDO_FLAG_WAKEUP_START |
3302 USBHUB_FDO_FLAG_DEVICE_REMOVED |
3303 USBHUB_FDO_FLAG_STATE_CHANGING |
3304 USBHUB_FDO_FLAG_ESD_RECOVERING |
3305 USBHUB_FDO_FLAG_DEVICE_FAILED |
3306 USBHUB_FDO_FLAG_DEVICE_STOPPING))
3307 {
3308 DbgBreakPoint();
3309 return;
3310 }
3311
3312 HubExtension->HubFlags |= USBHUB_FDO_FLAG_GOING_IDLE;
3313
3314 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_PENDING_WAKE_IRP))
3315 {
3316 Status = USBH_FdoSubmitWaitWakeIrp(HubExtension);
3317
3318 if (Status != STATUS_PENDING)
3319 {
3320 DPRINT("Status != STATUS_PENDING. DbgBreakPoint()\n");
3321 DbgBreakPoint();
3322 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_GOING_IDLE;
3323 return;
3324 }
3325 }
3326
3327 InterlockedIncrement(&HubExtension->PendingRequestCount);
3328
3329 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
3330 Executive,
3331 KernelMode,
3332 FALSE,
3333 NULL);
3334
3335 PortData = HubExtension->PortData;
3336 IsReady = TRUE;
3337
3338 for (Port = 0;
3339 Port < HubExtension->HubDescriptor->bNumberOfPorts;
3340 Port++)
3341 {
3342 PortDevice = PortData[Port].DeviceObject;
3343
3344 if (PortDevice)
3345 {
3346 PortExtension = PortDevice->DeviceExtension;
3347
3348 IdleIrp = PortExtension->IdleNotificationIrp;
3349
3350 if (!IdleIrp)
3351 {
3352 IsReady = FALSE;
3353 goto IdleHub;
3354 }
3355
3356 IoStack = IoGetCurrentIrpStackLocation(IdleIrp);
3357
3358 CallbackInfo = IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
3359
3360 if (!CallbackInfo)
3361 {
3362 IsReady = FALSE;
3363 goto IdleHub;
3364 }
3365
3366 if (!CallbackInfo->IdleCallback)
3367 {
3368 IsReady = FALSE;
3369 goto IdleHub;
3370 }
3371
3372 if (PortExtension->PendingSystemPoRequest)
3373 {
3374 IsReady = FALSE;
3375 goto IdleHub;
3376 }
3377
3378 if (InterlockedCompareExchange(&PortExtension->StateBehindD2,
3379 1,
3380 0))
3381 {
3382 IsReady = FALSE;
3383 goto IdleHub;
3384 }
3385
3386 DPRINT("USBH_FdoIdleNotificationCallback: IdleContext - %p\n",
3387 CallbackInfo->IdleContext);
3388
3389 CallbackInfo->IdleCallback(CallbackInfo->IdleContext);
3390
3391 if (PortExtension->CurrentPowerState.DeviceState == PowerDeviceD0)
3392 {
3393 IsReady = FALSE;
3394 goto IdleHub;
3395 }
3396 }
3397 }
3398
3399 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING) &&
3400 (USBH_CheckIdleAbort(HubExtension, FALSE, FALSE) == TRUE))
3401 {
3402 IsReady = FALSE;
3403 }
3404
3405 IdleHub:
3406
3407 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3408 LOW_REALTIME_PRIORITY,
3409 1,
3410 FALSE);
3411
3412 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3413 {
3414 KeSetEvent(&HubExtension->PendingRequestEvent,
3415 EVENT_INCREMENT,
3416 FALSE);
3417 }
3418
3419 if (!IsReady ||
3420 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_SUSPENDED))
3421 {
3422 DPRINT1("USBH_FdoIdleNotificationCallback: HubFlags - %lX\n",
3423 HubExtension->HubFlags);
3424
3425 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED |
3426 USBHUB_FDO_FLAG_GOING_IDLE);
3427
3428 /* Aborting Idle for Hub */
3429 IoAcquireCancelSpinLock(&OldIrql);
3430
3431 if (HubExtension->PendingIdleIrp)
3432 {
3433 Irp = HubExtension->PendingIdleIrp;
3434 HubExtension->PendingIdleIrp = NULL;
3435 }
3436
3437 IoReleaseCancelSpinLock(OldIrql);
3438
3439 if (Irp)
3440 {
3441 USBH_HubCancelIdleIrp(HubExtension, Irp);
3442 }
3443
3444 DbgBreakPoint();
3445 USBH_HubCompletePortIdleIrps(HubExtension, STATUS_CANCELLED);
3446 }
3447 else
3448 {
3449 PowerState.DeviceState = HubExtension->DeviceWake;
3450
3451 KeWaitForSingleObject(&HubExtension->IdleSemaphore,
3452 Executive,
3453 KernelMode,
3454 FALSE,
3455 NULL);
3456
3457 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_GOING_IDLE;
3458 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_SUSPENSE;
3459
3460 KeInitializeEvent(&Event, NotificationEvent, FALSE);
3461
3462 DPRINT("USBH_FdoIdleNotificationCallback: LowerPdo - %p\n",
3463 HubExtension->LowerPDO);
3464
3465 DPRINT("USBH_FdoIdleNotificationCallback: PowerState.DeviceState - %x\n",
3466 PowerState.DeviceState);
3467
3468 Status = PoRequestPowerIrp(HubExtension->LowerPDO,
3469 IRP_MN_SET_POWER,
3470 PowerState,
3471 USBH_HubSetDWakeCompletion,
3472 &Event,
3473 NULL);
3474
3475 if (Status == STATUS_PENDING)
3476 {
3477 KeWaitForSingleObject(&Event,
3478 Executive,
3479 KernelMode,
3480 FALSE,
3481 NULL);
3482 }
3483 }
3484 }
3485
3486 VOID
3487 NTAPI
3488 USBH_CompletePortIdleIrpsWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
3489 IN PVOID Context)
3490 {
3491 PUSBHUB_IDLE_PORT_CONTEXT IdlePortContext;
3492 NTSTATUS NtStatus;
3493 NTSTATUS Status;
3494 BOOLEAN IsFlush = FALSE;
3495
3496 DPRINT("USBH_CompletePortIdleIrpsWorker ... \n");
3497
3498 IdlePortContext = Context;
3499 NtStatus = IdlePortContext->Status;
3500
3501 USBH_HubCompleteQueuedPortIdleIrps(HubExtension,
3502 &IdlePortContext->PwrList,
3503 NtStatus);
3504
3505 DPRINT1("USBH_CompletePortIdleIrpsWorker: USBH_RegQueryFlushPortPowerIrpsFlag() UNIMPLEMENTED. FIXME\n");
3506 Status = STATUS_NOT_IMPLEMENTED;// USBH_RegQueryFlushPortPowerIrpsFlag(&IsFlush);
3507
3508 if (NT_SUCCESS(Status))
3509 {
3510 if (IsFlush)
3511 {
3512 USBH_FlushPortPwrList(HubExtension);
3513 }
3514 }
3515 }
3516
3517 VOID
3518 NTAPI
3519 USBH_IdleCompletePowerHubWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
3520 IN PVOID Context)
3521 {
3522 PUSBHUB_IDLE_HUB_CONTEXT HubWorkItemBuffer;
3523
3524 DPRINT("USBH_IdleCompletePowerHubWorker ... \n");
3525
3526 if (HubExtension &&
3527 HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0 &&
3528 HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED)
3529 {
3530 USBH_HubSetD0(HubExtension);
3531 }
3532
3533 HubWorkItemBuffer = Context;
3534
3535 USBH_HubCompletePortIdleIrps(HubExtension, HubWorkItemBuffer->Status);
3536
3537 }
3538
3539 NTSTATUS
3540 NTAPI
3541 USBH_FdoIdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject,
3542 IN PIRP Irp,
3543 IN PVOID Context)
3544 {
3545 PUSBHUB_FDO_EXTENSION HubExtension;
3546 NTSTATUS NtStatus;
3547 PVOID IdleIrp;
3548 KIRQL Irql;
3549 NTSTATUS Status;
3550 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
3551
3552 IoAcquireCancelSpinLock(&Irql);
3553
3554 HubExtension = Context;
3555 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST;
3556
3557 IdleIrp = InterlockedExchangePointer((PVOID)&HubExtension->PendingIdleIrp,
3558 NULL);
3559
3560 DPRINT("USBH_FdoIdleNotificationRequestComplete: IdleIrp - %p\n", IdleIrp);
3561
3562 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3563 {
3564 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE);
3565 }
3566
3567 IoReleaseCancelSpinLock(Irql);
3568
3569 NtStatus = Irp->IoStatus.Status;
3570
3571 DPRINT("USBH_FdoIdleNotificationRequestComplete: NtStatus - %lX\n",
3572 NtStatus);
3573
3574 if (!NT_SUCCESS(NtStatus) &&
3575 NtStatus != STATUS_POWER_STATE_INVALID &&
3576 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED) &&
3577 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
3578 {
3579 DPRINT("USBH_FdoIdleNotificationRequestComplete: DeviceState - %x\n",
3580 HubExtension->CurrentPowerState.DeviceState);
3581
3582 if (HubExtension->CurrentPowerState.DeviceState == PowerDeviceD0)
3583 {
3584 PUSBHUB_IDLE_PORT_CONTEXT HubWorkItemBuffer;
3585
3586 Status = USBH_AllocateWorkItem(HubExtension,
3587 &HubIoWorkItem,
3588 USBH_CompletePortIdleIrpsWorker,
3589 sizeof(USBHUB_IDLE_PORT_CONTEXT),
3590 (PVOID *)&HubWorkItemBuffer,
3591 DelayedWorkQueue);
3592
3593 if (NT_SUCCESS(Status))
3594 {
3595 HubWorkItemBuffer->Status = NtStatus;
3596
3597 USBH_HubQueuePortIdleIrps(HubExtension,
3598 &HubWorkItemBuffer->PwrList);
3599
3600 USBH_QueueWorkItem(HubExtension, HubIoWorkItem);
3601 }
3602 }
3603 else
3604 {
3605 PUSBHUB_IDLE_HUB_CONTEXT HubWorkItemBuffer;
3606
3607 Status = USBH_AllocateWorkItem(HubExtension,
3608 &HubIoWorkItem,
3609 USBH_IdleCompletePowerHubWorker,
3610 sizeof(USBHUB_IDLE_HUB_CONTEXT),
3611 (PVOID *)&HubWorkItemBuffer,
3612 DelayedWorkQueue);
3613
3614 if (NT_SUCCESS(Status))
3615 {
3616 HubWorkItemBuffer->Status = NtStatus;
3617 USBH_QueueWorkItem(HubExtension, HubIoWorkItem);
3618 }
3619 }
3620 }
3621
3622 if (IdleIrp ||
3623 InterlockedExchange((PLONG)&HubExtension->IdleRequestLock, 1))
3624 {
3625 DPRINT("USBH_FdoIdleNotificationRequestComplete: Irp - %p\n", Irp);
3626 IoFreeIrp(Irp);
3627 }
3628
3629 return STATUS_MORE_PROCESSING_REQUIRED;
3630 }
3631
3632 NTSTATUS
3633 NTAPI
3634 USBH_FdoSubmitIdleRequestIrp(IN PUSBHUB_FDO_EXTENSION HubExtension)
3635 {
3636 NTSTATUS Status;
3637 ULONG HubFlags;
3638 PDEVICE_OBJECT LowerPDO;
3639 PIRP Irp;
3640 PIO_STACK_LOCATION IoStack;
3641 KIRQL Irql;
3642
3643 DPRINT("USBH_FdoSubmitIdleRequestIrp: HubExtension - %p, PendingIdleIrp - %p\n",
3644 HubExtension,
3645 HubExtension->PendingIdleIrp);
3646
3647 if (HubExtension->PendingIdleIrp)
3648 {
3649 Status = STATUS_DEVICE_BUSY;
3650 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3651 return Status;
3652 }
3653
3654 HubFlags = HubExtension->HubFlags;
3655
3656 if (HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING ||
3657 HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED)
3658 {
3659 HubExtension->HubFlags = HubFlags & ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST;
3660 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3661 return STATUS_DEVICE_REMOVED;
3662 }
3663
3664 LowerPDO = HubExtension->LowerPDO;
3665
3666 HubExtension->IdleCallbackInfo.IdleCallback = USBH_FdoIdleNotificationCallback;
3667 HubExtension->IdleCallbackInfo.IdleContext = HubExtension;
3668
3669 Irp = IoAllocateIrp(LowerPDO->StackSize, FALSE);
3670
3671 if (!Irp)
3672 {
3673 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST;
3674 Status = STATUS_INSUFFICIENT_RESOURCES;
3675
3676 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3677 return Status;
3678 }
3679
3680 IoStack = IoGetNextIrpStackLocation(Irp);
3681
3682 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
3683
3684 IoStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(USB_IDLE_CALLBACK_INFO);
3685 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION;
3686 IoStack->Parameters.DeviceIoControl.Type3InputBuffer = &HubExtension->IdleCallbackInfo;
3687
3688 IoSetCompletionRoutine(Irp,
3689 USBH_FdoIdleNotificationRequestComplete,
3690 HubExtension,
3691 TRUE,
3692 TRUE,
3693 TRUE);
3694
3695 InterlockedIncrement(&HubExtension->PendingRequestCount);
3696 InterlockedExchange(&HubExtension->IdleRequestLock, 0);
3697
3698 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED |
3699 USBHUB_FDO_FLAG_GOING_IDLE);
3700
3701 Status = IoCallDriver(HubExtension->LowerPDO, Irp);
3702
3703 IoAcquireCancelSpinLock(&Irql);
3704
3705 if (Status == STATUS_PENDING &&
3706 HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST)
3707 {
3708 HubExtension->PendingIdleIrp = Irp;
3709 }
3710
3711 IoReleaseCancelSpinLock(Irql);
3712
3713 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3714
3715 return Status;
3716 }
3717
3718 VOID
3719 NTAPI
3720 USBH_CheckHubIdle(IN PUSBHUB_FDO_EXTENSION HubExtension)
3721 {
3722 PDEVICE_OBJECT PdoDevice;
3723 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3724 PUSBHUB_PORT_DATA PortData;
3725 ULONG HubFlags;
3726 ULONG Port;
3727 KIRQL Irql;
3728 BOOLEAN IsHubIdle = FALSE;
3729 BOOLEAN IsAllPortsIdle;
3730 BOOLEAN IsHubCheck = TRUE;
3731
3732 DPRINT("USBH_CheckHubIdle: FIXME !!! HubExtension - %p\n", HubExtension);
3733
3734 return; //HACK: delete it line after fixing Power Manager!!!
3735
3736 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql);
3737
3738 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_CHECK_IDLE_LOCK)
3739 {
3740 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3741 return;
3742 }
3743
3744 HubExtension->HubFlags |= USBHUB_FDO_FLAG_CHECK_IDLE_LOCK;
3745 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3746
3747 if (USBH_GetRootHubExtension(HubExtension)->SystemPowerState.SystemState != PowerSystemWorking)
3748 {
3749 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql);
3750 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK;
3751 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3752 return;
3753 }
3754
3755 HubFlags = HubExtension->HubFlags;
3756 DPRINT("USBH_CheckHubIdle: HubFlags - %lX\n", HubFlags);
3757
3758 if (!(HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) ||
3759 !(HubFlags & USBHUB_FDO_FLAG_DO_ENUMERATION))
3760 {
3761 goto Exit;
3762 }
3763
3764 if (HubFlags & USBHUB_FDO_FLAG_NOT_ENUMERATED ||
3765 HubFlags & USBHUB_FDO_FLAG_ENUM_POST_RECOVER ||
3766 HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED ||
3767 HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING ||
3768 HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED ||
3769 HubFlags & USBHUB_FDO_FLAG_STATE_CHANGING ||
3770 HubFlags & USBHUB_FDO_FLAG_WAKEUP_START ||
3771 HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING)
3772 {
3773 goto Exit;
3774 }
3775
3776 if (HubExtension->ResetRequestCount)
3777 {
3778 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEFER_CHECK_IDLE;
3779 goto Exit;
3780 }
3781
3782 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DEFER_CHECK_IDLE;
3783
3784 InterlockedIncrement(&HubExtension->PendingRequestCount);
3785
3786 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
3787 Executive,
3788 KernelMode,
3789 FALSE,
3790 NULL);
3791
3792 IoAcquireCancelSpinLock(&Irql);
3793
3794 IsAllPortsIdle = TRUE;
3795
3796 PortData = HubExtension->PortData;
3797
3798 for (Port = 0;
3799 Port < HubExtension->HubDescriptor->bNumberOfPorts;
3800 Port++)
3801 {
3802 PdoDevice = PortData[Port].DeviceObject;
3803
3804 if (PdoDevice)
3805 {
3806 PortExtension = PdoDevice->DeviceExtension;
3807
3808 if (!PortExtension->IdleNotificationIrp)
3809 {
3810 DPRINT("USBH_CheckHubIdle: PortExtension - %p\n",
3811 PortExtension);
3812
3813 IsAllPortsIdle = FALSE;
3814 IsHubCheck = FALSE;
3815
3816 break;
3817 }
3818 }
3819 }
3820
3821 if (IsHubCheck &&
3822 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST))
3823 {
3824 KeResetEvent(&HubExtension->IdleEvent);
3825 HubExtension->HubFlags |= USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST;
3826 IsHubIdle = TRUE;
3827 }
3828
3829 IoReleaseCancelSpinLock(Irql);
3830
3831 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3832 LOW_REALTIME_PRIORITY,
3833 1,
3834 FALSE);
3835
3836 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3837 {
3838 KeSetEvent(&HubExtension->PendingRequestEvent,
3839 EVENT_INCREMENT,
3840 FALSE);
3841 }
3842
3843 DPRINT("USBH_CheckHubIdle: IsAllPortsIdle - %x, IsHubIdle - %x\n",
3844 IsAllPortsIdle,
3845 IsHubIdle);
3846
3847 if (IsAllPortsIdle && IsHubIdle)
3848 {
3849 USBH_FdoSubmitIdleRequestIrp(HubExtension);
3850 }
3851
3852 Exit:
3853 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql);
3854 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK;
3855 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3856 }
3857
3858 VOID
3859 NTAPI
3860 USBH_CheckIdleWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
3861 IN PVOID Context)
3862 {
3863 DPRINT("USBH_CheckIdleWorker: ... \n");
3864 USBH_CheckHubIdle(HubExtension);
3865 }
3866
3867 VOID
3868 NTAPI
3869 USBH_CheckIdleDeferred(IN PUSBHUB_FDO_EXTENSION HubExtension)
3870 {
3871 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
3872 NTSTATUS Status;
3873
3874 DPRINT("USBH_CheckIdleDeferred: HubExtension - %p\n", HubExtension);
3875
3876 Status = USBH_AllocateWorkItem(HubExtension,
3877 &HubIoWorkItem,
3878 USBH_CheckIdleWorker,
3879 0,
3880 NULL,
3881 DelayedWorkQueue);
3882
3883 DPRINT("USBH_CheckIdleDeferred: HubIoWorkItem - %p\n", HubIoWorkItem);
3884
3885 if (NT_SUCCESS(Status))
3886 {
3887 USBH_QueueWorkItem(HubExtension, HubIoWorkItem);
3888 }
3889 }
3890
3891 VOID
3892 NTAPI
3893 USBH_PdoSetCapabilities(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension)
3894 {
3895 PUSBHUB_FDO_EXTENSION HubExtension;
3896 ULONG State;
3897 SYSTEM_POWER_STATE SystemPowerState;
3898 PDEVICE_POWER_STATE pDeviceState;
3899
3900 DPRINT("USBH_PdoSetCapabilities ... \n");
3901
3902 HubExtension = PortExtension->HubExtension;
3903
3904 PortExtension->Capabilities.Size = 64;
3905 PortExtension->Capabilities.Version = 1;
3906
3907 PortExtension->Capabilities.Removable = 1;
3908 PortExtension->Capabilities.Address = PortExtension->PortNumber;
3909
3910 if (PortExtension->SerialNumber)
3911 {
3912 PortExtension->Capabilities.UniqueID = 1;
3913 }
3914 else
3915 {
3916 PortExtension->Capabilities.UniqueID = 0;
3917 }
3918
3919 PortExtension->Capabilities.RawDeviceOK = 0;
3920
3921 RtlCopyMemory(PortExtension->Capabilities.DeviceState,
3922 HubExtension->DeviceState,
3923 (PowerSystemMaximum + 2) * sizeof(POWER_STATE));
3924
3925 PortExtension->Capabilities.DeviceState[1] = PowerDeviceD0;
3926
3927 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REMOTE_WAKEUP)
3928 {
3929 PortExtension->Capabilities.DeviceWake = PowerDeviceD2;
3930
3931 PortExtension->Capabilities.DeviceD1 = 1;
3932 PortExtension->Capabilities.DeviceD2 = 1;
3933
3934 PortExtension->Capabilities.WakeFromD0 = 1;
3935 PortExtension->Capabilities.WakeFromD1 = 1;
3936 PortExtension->Capabilities.WakeFromD2 = 1;
3937
3938 pDeviceState = &PortExtension->Capabilities.DeviceState[2];
3939
3940 for (State = 2; State <= 5; State++)
3941 {
3942 SystemPowerState = State;
3943
3944 if (PortExtension->Capabilities.SystemWake < SystemPowerState)
3945 {
3946 *pDeviceState = PowerDeviceD3;
3947 }
3948 else
3949 {
3950 *pDeviceState = PowerDeviceD2;
3951 }
3952
3953 ++pDeviceState;
3954 }
3955 }
3956 else
3957 {
3958 PortExtension->Capabilities.DeviceWake = PowerDeviceD0;
3959 PortExtension->Capabilities.DeviceState[2] = PowerDeviceD3;
3960 PortExtension->Capabilities.DeviceState[3] = PowerDeviceD3;
3961 PortExtension->Capabilities.DeviceState[4] = PowerDeviceD3;
3962 PortExtension->Capabilities.DeviceState[5] = PowerDeviceD3;
3963 }
3964 }
3965
3966 NTSTATUS
3967 NTAPI
3968 USBH_ProcessDeviceInformation(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension)
3969 {
3970 PUSB_INTERFACE_DESCRIPTOR Pid;
3971 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
3972 NTSTATUS Status;
3973
3974 DPRINT("USBH_ProcessDeviceInformation ... \n");
3975
3976 ConfigDescriptor = NULL;
3977
3978 RtlZeroMemory(&PortExtension->InterfaceDescriptor,
3979 sizeof(PortExtension->InterfaceDescriptor));
3980
3981 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_HUB_DEVICE;
3982
3983 Status = USBH_GetConfigurationDescriptor(PortExtension->Common.SelfDevice,
3984 &ConfigDescriptor);
3985
3986 if (!NT_SUCCESS(Status))
3987 {
3988 if (ConfigDescriptor)
3989 {
3990 ExFreePool(ConfigDescriptor);
3991 }
3992
3993 return Status;
3994 }
3995
3996 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REMOTE_WAKEUP;
3997
3998 if (ConfigDescriptor->bmAttributes & 0x20)
3999 {
4000 /* device configuration supports remote wakeup */
4001 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REMOTE_WAKEUP;
4002 }
4003
4004 USBHUB_DumpingDeviceDescriptor(&PortExtension->DeviceDescriptor);
4005 USBHUB_DumpingConfiguration(ConfigDescriptor);
4006
4007 DPRINT_PNP("USBH_ProcessDeviceInformation: Class - %x, SubClass - %x, Protocol - %x\n",
4008 PortExtension->DeviceDescriptor.bDeviceClass,
4009 PortExtension->DeviceDescriptor.bDeviceSubClass,
4010 PortExtension->DeviceDescriptor.bDeviceProtocol);
4011
4012 DPRINT_PNP("USBH_ProcessDeviceInformation: bNumConfigurations - %x, bNumInterfaces - %x\n",
4013 PortExtension->DeviceDescriptor.bNumConfigurations,
4014 ConfigDescriptor->bNumInterfaces);
4015
4016
4017 /* Enumeration of USB Composite Devices (msdn):
4018 1) The device class field of the device descriptor (bDeviceClass) must contain a value of zero,
4019 or the class (bDeviceClass), subclass (bDeviceSubClass), and protocol (bDeviceProtocol)
4020 fields of the device descriptor must have the values 0xEF, 0x02 and 0x01 respectively,
4021 as explained in USB Interface Association Descriptor.
4022 2) The device must have multiple interfaces
4023 3) The device must have a single configuration.
4024 */
4025
4026 if (((PortExtension->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_RESERVED) ||
4027 (PortExtension->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_MISCELLANEOUS &&
4028 PortExtension->DeviceDescriptor.bDeviceSubClass == 0x02 &&
4029 PortExtension->DeviceDescriptor.bDeviceProtocol == 0x01)) &&
4030 (ConfigDescriptor->bNumInterfaces > 1) &&
4031 (PortExtension->DeviceDescriptor.bNumConfigurations < 2))
4032 {
4033 DPRINT("USBH_ProcessDeviceInformation: Multi-Interface configuration\n");
4034
4035 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_MULTI_INTERFACE;
4036
4037 if (ConfigDescriptor)
4038 {
4039 ExFreePool(ConfigDescriptor);
4040 }
4041
4042 return Status;
4043 }
4044
4045 Pid = USBD_ParseConfigurationDescriptorEx(ConfigDescriptor,
4046 ConfigDescriptor,
4047 -1,
4048 -1,
4049 -1,
4050 -1,
4051 -1);
4052 if (Pid)
4053 {
4054 RtlCopyMemory(&PortExtension->InterfaceDescriptor,
4055 Pid,
4056 sizeof(PortExtension->InterfaceDescriptor));
4057
4058 if (Pid->bInterfaceClass == USB_DEVICE_CLASS_HUB)
4059 {
4060 PortExtension->PortPdoFlags |= (USBHUB_PDO_FLAG_HUB_DEVICE |
4061 USBHUB_PDO_FLAG_REMOTE_WAKEUP);
4062 }
4063 }
4064 else
4065 {
4066 Status = STATUS_UNSUCCESSFUL;
4067 }
4068
4069 if (ConfigDescriptor)
4070 {
4071 ExFreePool(ConfigDescriptor);
4072 }
4073
4074 return Status;
4075 }
4076
4077 BOOLEAN
4078 NTAPI
4079 USBH_CheckDeviceIDUnique(IN PUSBHUB_FDO_EXTENSION HubExtension,
4080 IN USHORT idVendor,
4081 IN USHORT idProduct,
4082 IN PVOID SerialNumber,
4083 IN USHORT SN_DescriptorLength)
4084 {
4085 PDEVICE_OBJECT PortDevice;
4086 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
4087 ULONG Port;
4088 SIZE_T NumberBytes;
4089
4090 DPRINT("USBH_CheckDeviceIDUnique: idVendor - 0x%04X, idProduct - 0x%04X\n",
4091 idVendor,
4092 idProduct);
4093
4094 if (!HubExtension->HubDescriptor->bNumberOfPorts)
4095 {
4096 return TRUE;
4097 }
4098
4099 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; Port++)
4100 {
4101 PortDevice = HubExtension->PortData[Port].DeviceObject;
4102
4103 if (PortDevice)
4104 {
4105 PortExtension = PortDevice->DeviceExtension;
4106
4107 if (PortExtension->DeviceDescriptor.idVendor == idVendor &&
4108 PortExtension->DeviceDescriptor.idProduct == idProduct &&
4109 PortExtension->SN_DescriptorLength == SN_DescriptorLength)
4110 {
4111 if (PortExtension->SerialNumber)
4112 {
4113 NumberBytes = RtlCompareMemory(PortExtension->SerialNumber,
4114 SerialNumber,
4115 SN_DescriptorLength);
4116
4117 if (NumberBytes == SN_DescriptorLength)
4118 {
4119 break;
4120 }
4121 }
4122 }
4123 }
4124 }
4125
4126 return FALSE;
4127 }
4128
4129 BOOLEAN
4130 NTAPI
4131 USBH_ValidateSerialNumberString(IN PUSHORT SerialNumberString)
4132 {
4133 USHORT ix;
4134 USHORT Symbol;
4135
4136 DPRINT("USBH_ValidateSerialNumberString: ... \n");
4137
4138 for (ix = 0; SerialNumberString[ix] != UNICODE_NULL; ix++)
4139 {
4140 Symbol = SerialNumberString[ix];
4141
4142 if (Symbol < 0x20 || Symbol > 0x7F || Symbol == 0x2C) // ','
4143 {
4144 return FALSE;
4145 }
4146 }
4147
4148 return TRUE;
4149 }
4150
4151
4152 NTSTATUS
4153 NTAPI
4154 USBH_CheckDeviceLanguage(IN PDEVICE_OBJECT DeviceObject,
4155 IN USHORT LanguageId)
4156 {
4157 PUSB_STRING_DESCRIPTOR Descriptor;
4158 NTSTATUS Status;
4159 ULONG NumSymbols;
4160 ULONG ix;
4161 PWCHAR pSymbol;
4162 ULONG Length;
4163
4164 DPRINT("USBH_CheckDeviceLanguage: LanguageId - 0x%04X\n", LanguageId);
4165
4166 Descriptor = ExAllocatePoolWithTag(NonPagedPool,
4167 MAXIMUM_USB_STRING_LENGTH,
4168 USB_HUB_TAG);
4169
4170 if (!Descriptor)
4171 {
4172 return STATUS_INSUFFICIENT_RESOURCES;
4173 }
4174
4175 RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH);
4176
4177 Status = USBH_SyncGetStringDescriptor(DeviceObject,
4178 0,
4179 0,
4180 Descriptor,
4181 MAXIMUM_USB_STRING_LENGTH,
4182 &Length,
4183 TRUE);
4184
4185 if (!NT_SUCCESS(Status) ||
4186 Length < sizeof(USB_COMMON_DESCRIPTOR))
4187 {
4188 goto Exit;
4189 }
4190
4191 NumSymbols = (Length -
4192 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) / sizeof(WCHAR);
4193
4194 pSymbol = Descriptor->bString;
4195
4196 for (ix = 1; ix < NumSymbols; ix++)
4197 {
4198 if (*pSymbol == (WCHAR)LanguageId)
4199 {
4200 Status = STATUS_SUCCESS;
4201 goto Exit;
4202 }
4203
4204 pSymbol++;
4205 }
4206
4207 Status = STATUS_NOT_SUPPORTED;
4208
4209 Exit:
4210 ExFreePoolWithTag(Descriptor, USB_HUB_TAG);
4211 return Status;
4212 }
4213
4214 NTSTATUS
4215 NTAPI
4216 USBH_GetSerialNumberString(IN PDEVICE_OBJECT DeviceObject,
4217 IN LPWSTR * OutSerialNumber,
4218 IN PUSHORT OutDescriptorLength,
4219 IN USHORT LanguageId,
4220 IN UCHAR Index)
4221 {
4222 PUSB_STRING_DESCRIPTOR Descriptor;
4223 NTSTATUS Status;
4224 LPWSTR SerialNumberBuffer = NULL;
4225 UCHAR StringLength;
4226 UCHAR Length;
4227
4228 DPRINT("USBH_GetSerialNumberString: ... \n");
4229
4230 *OutSerialNumber = NULL;
4231 *OutDescriptorLength = 0;
4232
4233 Descriptor = ExAllocatePoolWithTag(NonPagedPool,
4234 MAXIMUM_USB_STRING_LENGTH,
4235 USB_HUB_TAG);
4236
4237 if (!Descriptor)
4238 {
4239 return STATUS_INSUFFICIENT_RESOURCES;
4240 }
4241
4242 RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH);
4243
4244 Status = USBH_CheckDeviceLanguage(DeviceObject, LanguageId);
4245
4246 if (!NT_SUCCESS(Status))
4247 {
4248 goto Exit;
4249 }
4250
4251 Status = USBH_SyncGetStringDescriptor(DeviceObject,
4252 Index,
4253 LanguageId,
4254 Descriptor,
4255 MAXIMUM_USB_STRING_LENGTH,
4256 NULL,
4257 TRUE);
4258
4259 if (!NT_SUCCESS(Status) ||
4260 Descriptor->bLength <= sizeof(USB_COMMON_DESCRIPTOR))
4261 {
4262 Status = STATUS_INSUFFICIENT_RESOURCES;
4263 goto Exit;
4264 }
4265
4266 StringLength = Descriptor->bLength -
4267 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString);
4268
4269 Length = StringLength + sizeof(UNICODE_NULL);
4270
4271 SerialNumberBuffer = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG);
4272
4273 if (!SerialNumberBuffer)
4274 {
4275 goto Exit;
4276 }
4277
4278 RtlZeroMemory(SerialNumberBuffer, Length);
4279 RtlCopyMemory(SerialNumberBuffer, Descriptor->bString, StringLength);
4280
4281 *OutSerialNumber = SerialNumberBuffer;
4282 *OutDescriptorLength = Length;
4283
4284 Exit:
4285 ExFreePoolWithTag(Descriptor, USB_HUB_TAG);
4286 return Status;
4287 }
4288
4289 NTSTATUS
4290 NTAPI
4291 USBH_CreateDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
4292 IN USHORT Port,
4293 IN USB_PORT_STATUS UsbPortStatus,
4294 IN ULONG IsWait)
4295 {
4296 ULONG PdoNumber = 0;
4297 WCHAR CharDeviceName[64];
4298 UNICODE_STRING DeviceName;
4299 PDEVICE_OBJECT DeviceObject = NULL;
4300 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
4301 PUSB_DEVICE_HANDLE DeviceHandle;
4302 LPWSTR SerialNumberBuffer;
4303 BOOLEAN IsHsDevice;
4304 BOOLEAN IsLsDevice;
4305 BOOLEAN IgnoringHwSerial = FALSE;
4306 NTSTATUS Status;
4307 UNICODE_STRING DestinationString;
4308
4309 DPRINT("USBH_CreateDevice: Port - %x, UsbPortStatus - %lX\n",
4310 Port,
4311 UsbPortStatus.AsUshort16);
4312
4313 do
4314 {
4315 RtlStringCbPrintfW(CharDeviceName,
4316 sizeof(CharDeviceName),
4317 L"\\Device\\USBPDO-%d",
4318 PdoNumber);
4319
4320 RtlInitUnicodeString(&DeviceName, CharDeviceName);
4321
4322 Status = IoCreateDevice(HubExtension->Common.SelfDevice->DriverObject,
4323 sizeof(USBHUB_PORT_PDO_EXTENSION),
4324 &DeviceName,
4325 FILE_DEVICE_USB,
4326 0,
4327 FALSE,
4328 &DeviceObject);
4329
4330 ++PdoNumber;
4331 }
4332 while (Status == STATUS_OBJECT_NAME_COLLISION);
4333
4334 if (!NT_SUCCESS(Status))
4335 {
4336 ASSERT(Port > 0);
4337 HubExtension->PortData[Port-1].DeviceObject = DeviceObject;
4338 return Status;
4339 }
4340
4341 DeviceObject->StackSize = HubExtension->RootHubPdo2->StackSize;
4342
4343 PortExtension = DeviceObject->DeviceExtension;
4344
4345 DPRINT("USBH_CreateDevice: PortDevice - %p, <%wZ>\n", DeviceObject, &DeviceName);
4346 DPRINT("USBH_CreateDevice: PortExtension - %p\n", PortExtension);
4347
4348 RtlZeroMemory(PortExtension, sizeof(USBHUB_PORT_PDO_EXTENSION));
4349
4350 PortExtension->Common.ExtensionType = USBH_EXTENSION_TYPE_PORT;
4351 PortExtension->Common.SelfDevice = DeviceObject;
4352
4353 PortExtension->HubExtension = HubExtension;
4354 PortExtension->RootHubExtension = HubExtension;
4355
4356 PortExtension->PortNumber = Port;
4357 PortExtension->CurrentPowerState.DeviceState = PowerDeviceD0;
4358 PortExtension->IgnoringHwSerial = FALSE;
4359
4360 KeInitializeSpinLock(&PortExtension->PortTimeoutSpinLock);
4361
4362 InitializeListHead(&PortExtension->PortPowerList);
4363 KeInitializeSpinLock(&PortExtension->PortPowerListSpinLock);
4364
4365 PortExtension->PoRequestCounter = 0;
4366 PortExtension->PendingSystemPoRequest = 0;
4367 PortExtension->PendingDevicePoRequest = 0;
4368 PortExtension->StateBehindD2 = 0;
4369
4370 SerialNumberBuffer = NULL;
4371
4372 IsHsDevice = UsbPortStatus.Usb20PortStatus.HighSpeedDeviceAttached;
4373 IsLsDevice = UsbPortStatus.Usb20PortStatus.LowSpeedDeviceAttached;
4374
4375 if (IsLsDevice == 0)
4376 {
4377 if (IsHsDevice)
4378 {
4379 PortExtension->PortPdoFlags = USBHUB_PDO_FLAG_PORT_HIGH_SPEED;
4380 }
4381 }
4382 else
4383 {
4384 PortExtension->PortPdoFlags = USBHUB_PDO_FLAG_PORT_LOW_SPEED;
4385 }
4386
4387 /* Initialize PortExtension->InstanceID */
4388 RtlInitUnicodeString(&DestinationString, (PCWSTR)&PortExtension->InstanceID);
4389 DestinationString.MaximumLength = 4 * sizeof(WCHAR);
4390 Status = RtlIntegerToUnicodeString(Port, 10, &DestinationString);
4391
4392 DeviceObject->Flags |= DO_POWER_PAGABLE;
4393 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
4394
4395 if (!NT_SUCCESS(Status))
4396 {
4397 DPRINT1("USBH_CreateDevice: IoCreateDevice() failed - %lX\n", Status);
4398 goto ErrorExit;
4399 }
4400
4401 Status = USBD_CreateDeviceEx(HubExtension,
4402 &PortExtension->DeviceHandle,
4403 UsbPortStatus,
4404 Port);
4405
4406 if (!NT_SUCCESS(Status))
4407 {
4408 DPRINT1("USBH_CreateDevice: USBD_CreateDeviceEx() failed - %lX\n", Status);
4409 goto ErrorExit;
4410 }
4411
4412 Status = USBH_SyncResetPort(HubExtension, Port);
4413
4414 if (!NT_SUCCESS(Status))
4415 {
4416 DPRINT1("USBH_CreateDevice: USBH_SyncResetPort() failed - %lX\n", Status);
4417 goto ErrorExit;
4418 }
4419
4420 if (IsWait)
4421 {
4422 USBH_Wait(50);
4423 }
4424
4425 Status = USBD_InitializeDeviceEx(HubExtension,
4426 PortExtension->DeviceHandle,
4427 (PUCHAR)&PortExtension->DeviceDescriptor,
4428 sizeof(USB_DEVICE_DESCRIPTOR),
4429 (PUCHAR)&PortExtension->ConfigDescriptor,
4430 sizeof(USB_CONFIGURATION_DESCRIPTOR));
4431
4432 if (!NT_SUCCESS(Status))
4433 {
4434 DPRINT1("USBH_CreateDevice: USBD_InitializeDeviceEx() failed - %lX\n", Status);
4435 PortExtension->DeviceHandle = NULL;
4436 goto ErrorExit;
4437 }
4438
4439 DPRINT1("USBH_RegQueryDeviceIgnoreHWSerNumFlag UNIMPLEMENTED. FIXME\n");
4440 //Status = USBH_RegQueryDeviceIgnoreHWSerNumFlag(PortExtension->DeviceDescriptor.idVendor,
4441 // PortExtension->DeviceDescriptor.idProduct,
4442 // &IgnoringHwSerial);
4443
4444 if (TRUE)//Status == STATUS_OBJECT_NAME_NOT_FOUND)
4445 {
4446 IgnoringHwSerial = FALSE;
4447 }
4448
4449 if (IgnoringHwSerial)
4450 {
4451 PortExtension->IgnoringHwSerial = TRUE;
4452 }
4453
4454 if (PortExtension->DeviceDescriptor.iSerialNumber &&
4455 !PortExtension->IgnoringHwSerial)
4456 {
4457 InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber, NULL);
4458
4459 USBH_GetSerialNumberString(PortExtension->Common.SelfDevice,
4460 &SerialNumberBuffer,
4461 &PortExtension->SN_DescriptorLength,
4462 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
4463 PortExtension->DeviceDescriptor.iSerialNumber);
4464
4465 if (SerialNumberBuffer)
4466 {
4467 if (!USBH_ValidateSerialNumberString((PUSHORT)SerialNumberBuffer))
4468 {
4469 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG);
4470 SerialNumberBuffer = NULL;
4471 }
4472
4473 if (SerialNumberBuffer &&
4474 !USBH_CheckDeviceIDUnique(HubExtension,
4475 PortExtension->DeviceDescriptor.idVendor,
4476 PortExtension->DeviceDescriptor.idProduct,
4477 SerialNumberBuffer,
4478 PortExtension->SN_DescriptorLength))
4479 {
4480 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG);
4481 SerialNumberBuffer = NULL;
4482 }
4483 }
4484
4485 InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber,
4486 SerialNumberBuffer);
4487 }
4488
4489 Status = USBH_ProcessDeviceInformation(PortExtension);
4490
4491 USBH_PdoSetCapabilities(PortExtension);
4492
4493 if (NT_SUCCESS(Status))
4494 {
4495 goto Exit;
4496 }
4497
4498 ErrorExit:
4499
4500 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_INIT_PORT_FAILED;
4501
4502 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle,
4503 NULL);
4504
4505 if (DeviceHandle)
4506 {
4507 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0);
4508 }
4509
4510 SerialNumberBuffer = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber,
4511 NULL);
4512
4513 if (SerialNumberBuffer)
4514 {
4515 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG);
4516 }
4517
4518 Exit:
4519
4520 ASSERT(Port > 0);
4521 HubExtension->PortData[Port-1].DeviceObject = DeviceObject;
4522 return Status;
4523 }
4524
4525 NTSTATUS
4526 NTAPI
4527 USBH_ResetDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
4528 IN USHORT Port,
4529 IN BOOLEAN IsKeepDeviceData,
4530 IN BOOLEAN IsWait)
4531 {
4532 NTSTATUS Status;
4533 PUSBHUB_PORT_DATA PortData;
4534 PDEVICE_OBJECT PortDevice;
4535 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
4536 PVOID NewDeviceHandle;
4537 PVOID Handle;
4538 PVOID OldDeviceHandle;
4539 PUSB_DEVICE_HANDLE * DeviceHandle;
4540 USB_PORT_STATUS_AND_CHANGE PortStatus;
4541
4542 DPRINT("USBH_ResetDevice: HubExtension - %p, Port - %x, IsKeepDeviceData - %x, IsWait - %x\n",
4543 HubExtension,
4544 Port,
4545 IsKeepDeviceData,
4546 IsWait);
4547
4548 Status = USBH_SyncGetPortStatus(HubExtension,
4549 Port,
4550 &PortStatus,
4551 sizeof(USB_PORT_STATUS_AND_CHANGE));
4552
4553 if (!NT_SUCCESS(Status) ||
4554 !(PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus))
4555 {
4556 return STATUS_UNSUCCESSFUL;
4557 }
4558
4559 InterlockedIncrement(&HubExtension->PendingRequestCount);
4560
4561 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
4562 Executive,
4563 KernelMode,
4564 FALSE,
4565 NULL);
4566
4567 ASSERT(Port > 0);
4568 PortData = &HubExtension->PortData[Port-1];
4569
4570 PortDevice = PortData->DeviceObject;
4571
4572 if (!PortDevice)
4573 {
4574 Status = STATUS_INVALID_PARAMETER;
4575
4576 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
4577 LOW_REALTIME_PRIORITY,
4578 1,
4579 FALSE);
4580
4581 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
4582 {
4583 KeSetEvent(&HubExtension->PendingRequestEvent,
4584 EVENT_INCREMENT,
4585 FALSE);
4586 }
4587
4588 return Status;
4589 }
4590
4591 PortExtension = PortDevice->DeviceExtension;
4592 DeviceHandle = &PortExtension->DeviceHandle;
4593
4594 OldDeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle,
4595 NULL);
4596
4597 if (OldDeviceHandle)
4598 {
4599 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REMOVING_PORT_PDO))
4600 {
4601 Status = USBD_RemoveDeviceEx(HubExtension,
4602 OldDeviceHandle,
4603 IsKeepDeviceData);
4604
4605 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REMOVING_PORT_PDO;
4606 }
4607 }
4608 else
4609 {
4610 OldDeviceHandle = NULL;
4611 }
4612
4613 if (!NT_SUCCESS(Status))
4614 {
4615 goto ErrorExit;
4616 }
4617
4618 Status = USBH_SyncResetPort(HubExtension, Port);
4619
4620 if (!NT_SUCCESS(Status))
4621 {
4622 goto ErrorExit;
4623 }
4624
4625 Status = USBH_SyncGetPortStatus(HubExtension,
4626 Port,
4627 &PortStatus,
4628 sizeof(USB_PORT_STATUS_AND_CHANGE));
4629
4630 if (!NT_SUCCESS(Status))
4631 {
4632 goto ErrorExit;
4633 }
4634
4635 Status = USBD_CreateDeviceEx(HubExtension,
4636 DeviceHandle,
4637 PortStatus.PortStatus,
4638 Port);
4639
4640 if (!NT_SUCCESS(Status))
4641 {
4642 goto ErrorExit;
4643 }
4644
4645 Status = USBH_SyncResetPort(HubExtension, Port);
4646
4647 if (IsWait)
4648 {
4649 USBH_Wait(50);
4650 }
4651
4652 if (!NT_SUCCESS(Status))
4653 {
4654 goto ErrorExit;
4655 }
4656
4657 Status = USBD_InitializeDeviceEx(HubExtension,
4658 *DeviceHandle,
4659 &PortExtension->DeviceDescriptor.bLength,
4660 sizeof(PortExtension->DeviceDescriptor),
4661 &PortExtension->ConfigDescriptor.bLength,
4662 sizeof(PortExtension->ConfigDescriptor));
4663
4664 if (NT_SUCCESS(Status))
4665 {
4666 if (IsKeepDeviceData)
4667 {
4668 Status = USBD_RestoreDeviceEx(HubExtension,
4669 OldDeviceHandle,
4670 *DeviceHandle);
4671
4672 if (!NT_SUCCESS(Status))
4673 {
4674 Handle = InterlockedExchangePointer(DeviceHandle, NULL);
4675
4676 USBD_RemoveDeviceEx(HubExtension, Handle, 0);
4677 USBH_SyncDisablePort(HubExtension, Port);
4678
4679 Status = STATUS_NO_SUCH_DEVICE;
4680 }
4681 }
4682 else
4683 {
4684 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REMOVING_PORT_PDO;
4685 }
4686
4687 goto Exit;
4688 }
4689
4690 *DeviceHandle = NULL;
4691
4692 ErrorExit:
4693
4694 NewDeviceHandle = InterlockedExchangePointer(DeviceHandle,
4695 OldDeviceHandle);
4696
4697 if (NewDeviceHandle)
4698 {
4699 Status = USBD_RemoveDeviceEx(HubExtension, NewDeviceHandle, 0);
4700 }
4701
4702 Exit:
4703
4704 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
4705 LOW_REALTIME_PRIORITY,
4706 1,
4707 FALSE);
4708
4709 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
4710 {
4711 KeSetEvent(&HubExtension->PendingRequestEvent,
4712 EVENT_INCREMENT,
4713 FALSE);
4714 }
4715
4716 return Status;
4717 }
4718
4719 NTSTATUS
4720 NTAPI
4721 USBH_PdoDispatch(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
4722 IN PIRP Irp)
4723 {
4724 PIO_STACK_LOCATION IoStack;
4725 UCHAR MajorFunction;
4726 BOOLEAN ShouldCompleteIrp;
4727 ULONG ControlCode;
4728 NTSTATUS Status;
4729
4730 IoStack = IoGetCurrentIrpStackLocation(Irp);
4731 MajorFunction = IoStack->MajorFunction;
4732
4733 switch (MajorFunction)
4734 {
4735 case IRP_MJ_CREATE:
4736 case IRP_MJ_CLOSE:
4737 DPRINT("USBH_PdoDispatch: IRP_MJ_CREATE / IRP_MJ_CLOSE (%d)\n",
4738 MajorFunction);
4739 Status = STATUS_SUCCESS;
4740 USBH_CompleteIrp(Irp, Status);
4741 break;
4742
4743 case IRP_MJ_DEVICE_CONTROL:
4744 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
4745 DPRINT("USBH_PdoDispatch: IRP_MJ_DEVICE_CONTROL ControlCode - %x\n",
4746 ControlCode);
4747
4748 if (ControlCode == IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
4749 {
4750 Status = STATUS_NOT_SUPPORTED;
4751 USBH_CompleteIrp(Irp, Status);
4752 break;
4753 }
4754
4755 if (ControlCode == IOCTL_KS_PROPERTY)
4756 {
4757 DPRINT1("USBH_PdoDispatch: IOCTL_KS_PROPERTY FIXME\n");
4758 DbgBreakPoint();
4759 Status = STATUS_NOT_SUPPORTED;
4760 USBH_CompleteIrp(Irp, Status);
4761 break;
4762 }
4763
4764 Status = Irp->IoStatus.Status;
4765 USBH_CompleteIrp(Irp, Status);
4766 break;
4767
4768 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
4769 Status = USBH_PdoInternalControl(PortExtension, Irp);
4770 break;
4771
4772 case IRP_MJ_PNP:
4773 Status = USBH_PdoPnP(PortExtension,
4774 Irp,
4775 IoStack->MinorFunction,
4776 &ShouldCompleteIrp);
4777
4778 if (ShouldCompleteIrp)
4779 {
4780 USBH_CompleteIrp(Irp, Status);
4781 }
4782
4783 break;
4784
4785 case IRP_MJ_POWER:
4786 Status = USBH_PdoPower(PortExtension, Irp, IoStack->MinorFunction);
4787 break;
4788
4789 case IRP_MJ_SYSTEM_CONTROL:
4790 DPRINT1("USBH_PdoDispatch: USBH_SystemControl() UNIMPLEMENTED. FIXME\n");
4791 Status = STATUS_NOT_SUPPORTED;//USBH_PortSystemControl(PortExtension, Irp);
4792 break;
4793
4794 default:
4795 DPRINT("USBH_PdoDispatch: Unhandled MajorFunction - %d\n", MajorFunction);
4796 Status = Irp->IoStatus.Status;
4797 USBH_CompleteIrp(Irp, Status);
4798 break;
4799 }
4800
4801 return Status;
4802 }
4803
4804 NTSTATUS
4805 NTAPI
4806 USBH_FdoDispatch(IN PUSBHUB_FDO_EXTENSION HubExtension,
4807 IN PIRP Irp)
4808 {
4809 PIO_STACK_LOCATION IoStack;
4810 UCHAR MajorFunction;
4811 NTSTATUS Status;
4812
4813 IoStack = IoGetCurrentIrpStackLocation(Irp);
4814
4815 DPRINT("USBH_FdoDispatch: HubExtension - %p, Irp - %p, MajorFunction - %X\n",
4816 HubExtension,
4817 Irp,
4818 IoStack->MajorFunction);
4819
4820 MajorFunction = IoStack->MajorFunction;
4821
4822 switch (MajorFunction)
4823 {
4824 case IRP_MJ_CREATE:
4825 case IRP_MJ_CLOSE:
4826 Status = STATUS_SUCCESS;
4827 USBH_CompleteIrp(Irp, Status);
4828 break;
4829
4830 case IRP_MJ_DEVICE_CONTROL:
4831 Status = USBH_DeviceControl(HubExtension, Irp);
4832 break;
4833
4834 case IRP_MJ_PNP:
4835 Status = USBH_FdoPnP(HubExtension, Irp, IoStack->MinorFunction);
4836 break;
4837
4838 case IRP_MJ_POWER:
4839 Status = USBH_FdoPower(HubExtension, Irp, IoStack->MinorFunction);
4840 break;
4841
4842 case IRP_MJ_SYSTEM_CONTROL:
4843 DPRINT1("USBH_FdoDispatch: USBH_SystemControl() UNIMPLEMENTED. FIXME\n");
4844 /* fall through */
4845
4846 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
4847 default:
4848 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
4849 break;
4850 }
4851
4852 return Status;
4853 }
4854
4855 NTSTATUS
4856 NTAPI
4857 USBH_AddDevice(IN PDRIVER_OBJECT DriverObject,
4858 IN PDEVICE_OBJECT LowerPDO)
4859 {
4860 PDEVICE_OBJECT DeviceObject;
4861 NTSTATUS Status;
4862 PUSBHUB_FDO_EXTENSION HubExtension;
4863 PDEVICE_OBJECT LowerDevice;
4864
4865 DPRINT("USBH_AddDevice: DriverObject - %p, LowerPDO - %p\n",
4866 DriverObject,
4867 LowerPDO);
4868
4869 DeviceObject = NULL;
4870
4871 Status = IoCreateDevice(DriverObject,
4872 sizeof(USBHUB_FDO_EXTENSION),
4873 NULL,
4874 0x8600,
4875 FILE_AUTOGENERATED_DEVICE_NAME,
4876 FALSE,
4877 &DeviceObject);
4878
4879 if (!NT_SUCCESS(Status))
4880 {
4881 DPRINT1("USBH_AddDevice: IoCreateDevice() fail\n");
4882
4883 if (DeviceObject)
4884 {
4885 IoDeleteDevice(DeviceObject);
4886 }
4887
4888 return Status;
4889 }
4890
4891 DPRINT("USBH_AddDevice: DeviceObject - %p\n", DeviceObject);
4892
4893 HubExtension = DeviceObject->DeviceExtension;
4894 RtlZeroMemory(HubExtension, sizeof(USBHUB_FDO_EXTENSION));
4895
4896 HubExtension->Common.ExtensionType = USBH_EXTENSION_TYPE_HUB;
4897
4898 LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, LowerPDO);
4899
4900 if (!LowerDevice)
4901 {
4902 DPRINT1("USBH_AddDevice: IoAttachDeviceToDeviceStack() fail\n");
4903
4904 if (DeviceObject)
4905 {
4906 IoDeleteDevice(DeviceObject);
4907 }
4908
4909 return STATUS_UNSUCCESSFUL;
4910 }
4911
4912 DPRINT("USBH_AddDevice: LowerDevice - %p\n", LowerDevice);
4913
4914 HubExtension->Common.SelfDevice = DeviceObject;
4915
4916 HubExtension->LowerPDO = LowerPDO;
4917 HubExtension->LowerDevice = LowerDevice;
4918
4919 KeInitializeSemaphore(&HubExtension->IdleSemaphore, 1, 1);
4920
4921 DeviceObject->Flags |= DO_POWER_PAGABLE;
4922 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
4923
4924 DPRINT("USBH_AddDevice: call IoWMIRegistrationControl() UNIMPLEMENTED. FIXME\n");
4925
4926 return Status;
4927 }
4928
4929 VOID
4930 NTAPI
4931 USBH_DriverUnload(IN PDRIVER_OBJECT DriverObject)
4932 {
4933 DPRINT("USBH_DriverUnload: UNIMPLEMENTED\n");
4934
4935 if (GenericUSBDeviceString)
4936 {
4937 ExFreePool(GenericUSBDeviceString);
4938 GenericUSBDeviceString = NULL;
4939 }
4940 }
4941
4942 NTSTATUS
4943 NTAPI
4944 USBH_HubDispatch(IN PDEVICE_OBJECT DeviceObject,
4945 IN PIRP Irp)
4946 {
4947 PCOMMON_DEVICE_EXTENSION DeviceExtension;
4948 ULONG ExtensionType;
4949 NTSTATUS Status;
4950
4951
4952 DeviceExtension = DeviceObject->DeviceExtension;
4953 ExtensionType = DeviceExtension->ExtensionType;
4954
4955 if (ExtensionType == USBH_EXTENSION_TYPE_HUB)
4956 {
4957 DPRINT("USBH_HubDispatch: DeviceObject - %p, Irp - %p\n",
4958 DeviceObject,
4959 Irp);
4960
4961 Status = USBH_FdoDispatch((PUSBHUB_FDO_EXTENSION)DeviceExtension, Irp);
4962 }
4963 else if (ExtensionType == USBH_EXTENSION_TYPE_PORT)
4964 {
4965 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
4966 UCHAR MajorFunction = IoStack->MajorFunction;
4967 BOOLEAN IsDprint = TRUE;
4968
4969 if (MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)
4970 {
4971 ULONG ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
4972
4973 if (ControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
4974 {
4975 IsDprint = FALSE;
4976 }
4977 }
4978
4979 if (IsDprint)
4980 {
4981 DPRINT("USBH_HubDispatch: DeviceObject - %p, Irp - %p\n",
4982 DeviceObject,
4983 Irp);
4984 }
4985
4986 Status = USBH_PdoDispatch((PUSBHUB_PORT_PDO_EXTENSION)DeviceExtension, Irp);
4987 }
4988 else
4989 {
4990 DPRINT1("USBH_HubDispatch: Unknown ExtensionType - %x\n", ExtensionType);
4991 DbgBreakPoint();
4992 Status = STATUS_ASSERTION_FAILURE;
4993 }
4994
4995 return Status;
4996 }
4997
4998 NTSTATUS
4999 NTAPI
5000 USBH_RegQueryGenericUSBDeviceString(PVOID USBDeviceString)
5001 {
5002 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
5003
5004 DPRINT("USBH_RegQueryGenericUSBDeviceString ... \n");
5005
5006 RtlZeroMemory(QueryTable, sizeof(QueryTable));
5007
5008 QueryTable[0].QueryRoutine = USBH_GetConfigValue;
5009 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
5010 QueryTable[0].Name = L"GenericUSBDeviceString";
5011 QueryTable[0].EntryContext = USBDeviceString;
5012 QueryTable[0].DefaultType = REG_NONE;
5013 QueryTable[0].DefaultData = 0;
5014 QueryTable[0].DefaultLength = 0;
5015
5016 return RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
5017 L"usbflags",
5018 QueryTable,
5019 NULL,
5020 NULL);
5021 }
5022
5023 NTSTATUS
5024 NTAPI
5025 DriverEntry(IN PDRIVER_OBJECT DriverObject,
5026 IN PUNICODE_STRING RegistryPath)
5027 {
5028 DPRINT("USBHUB: DriverEntry - %wZ\n", RegistryPath);
5029
5030 DriverObject->DriverExtension->AddDevice = USBH_AddDevice;
5031 DriverObject->DriverUnload = USBH_DriverUnload;
5032
5033 DriverObject->MajorFunction[IRP_MJ_CREATE] = USBH_HubDispatch;
5034 DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBH_HubDispatch;
5035
5036 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBH_HubDispatch;
5037 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBH_HubDispatch;
5038
5039 DriverObject->MajorFunction[IRP_MJ_PNP] = USBH_HubDispatch;
5040 DriverObject->MajorFunction[IRP_MJ_POWER] = USBH_HubDispatch;
5041 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBH_HubDispatch;
5042
5043 USBH_RegQueryGenericUSBDeviceString(&GenericUSBDeviceString);
5044
5045 return STATUS_SUCCESS;
5046 }
5047