65c529ccbe8b4162377e8faab04682b57a3094aa
[reactos.git] / reactos / drivers / usb / usbhub / fdo.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
5 * PURPOSE: Handle FDO
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #define INITGUID
12 #include "usbhub.h"
13
14 NTSTATUS
15 QueryStatusChangeEndpoint(
16 IN PDEVICE_OBJECT DeviceObject);
17
18 NTSTATUS
19 CreateUsbChildDeviceObject(
20 IN PDEVICE_OBJECT UsbHubDeviceObject,
21 IN LONG PortId,
22 OUT PDEVICE_OBJECT *UsbChildDeviceObject,
23 IN ULONG PortStatus);
24
25 NTSTATUS
26 DestroyUsbChildDeviceObject(
27 IN PDEVICE_OBJECT UsbHubDeviceObject,
28 IN LONG PortId);
29
30
31 NTSTATUS
32 GetPortStatusAndChange(
33 IN PDEVICE_OBJECT RootHubDeviceObject,
34 IN ULONG PortId,
35 OUT PPORT_STATUS_CHANGE StatusChange)
36 {
37 NTSTATUS Status;
38 PURB Urb;
39
40 //
41 // Allocate URB
42 //
43 Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
44 if (!Urb)
45 {
46 DPRINT1("Failed to allocate memory for URB!\n");
47 return STATUS_INSUFFICIENT_RESOURCES;
48 }
49
50 //
51 // Zero it
52 //
53 RtlZeroMemory(Urb, sizeof(URB));
54
55 //
56 // Initialize URB for getting Port Status
57 //
58 UsbBuildVendorRequest(Urb,
59 URB_FUNCTION_CLASS_OTHER,
60 sizeof(Urb->UrbControlVendorClassRequest),
61 USBD_TRANSFER_DIRECTION_OUT,
62 0,
63 USB_REQUEST_GET_STATUS,
64 0,
65 PortId,
66 StatusChange,
67 0,
68 sizeof(PORT_STATUS_CHANGE),
69 0);
70
71 // FIXME: support usb hubs
72 Urb->UrbHeader.UsbdDeviceHandle = NULL;
73
74
75 //
76 // Query the Root Hub
77 //
78 Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
79
80 //
81 // Free URB
82 //
83 ExFreePool(Urb);
84
85 return Status;
86 }
87
88 NTSTATUS
89 SetPortFeature(
90 IN PDEVICE_OBJECT RootHubDeviceObject,
91 IN ULONG PortId,
92 IN ULONG Feature)
93 {
94 NTSTATUS Status;
95 PURB Urb;
96
97 //
98 // Allocate URB
99 //
100 Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
101 if (!Urb)
102 {
103 DPRINT1("Failed to allocate memory for URB!\n");
104 return STATUS_INSUFFICIENT_RESOURCES;
105 }
106
107 //
108 // Zero it
109 //
110 RtlZeroMemory(Urb, sizeof(URB));
111
112 //
113 // Initialize URB for Clearing Port Reset
114 //
115 UsbBuildVendorRequest(Urb,
116 URB_FUNCTION_CLASS_OTHER,
117 sizeof(Urb->UrbControlVendorClassRequest),
118 USBD_TRANSFER_DIRECTION_IN,
119 0,
120 USB_REQUEST_SET_FEATURE,
121 Feature,
122 PortId,
123 NULL,
124 0,
125 0,
126 0);
127
128 // FIXME support usbhubs
129 Urb->UrbHeader.UsbdDeviceHandle = NULL;
130
131 //
132 // Query the Root Hub
133 //
134 Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
135
136 //
137 // Free URB
138 //
139 ExFreePool(Urb);
140
141 return Status;
142 }
143
144 NTSTATUS
145 ClearPortFeature(
146 IN PDEVICE_OBJECT RootHubDeviceObject,
147 IN ULONG PortId,
148 IN ULONG Feature)
149 {
150 NTSTATUS Status;
151 PURB Urb;
152
153 //
154 // Allocate a URB
155 //
156 Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
157 if (!Urb)
158 {
159 DPRINT1("Failed to allocate memory for URB!\n");
160 return STATUS_INSUFFICIENT_RESOURCES;
161 }
162
163 //
164 // Zero it
165 //
166 RtlZeroMemory(Urb, sizeof(URB));
167
168 //
169 // Initialize URB for Clearing Port Reset
170 //
171 UsbBuildVendorRequest(Urb,
172 URB_FUNCTION_CLASS_OTHER,
173 sizeof(Urb->UrbControlVendorClassRequest),
174 USBD_TRANSFER_DIRECTION_IN,
175 0,
176 USB_REQUEST_CLEAR_FEATURE,
177 Feature,
178 PortId,
179 NULL,
180 0,
181 0,
182 0);
183
184 // FIXME: support usb hubs
185 Urb->UrbHeader.UsbdDeviceHandle = NULL;
186
187 //
188 // Query the Root Hub
189 //
190 Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
191
192 //
193 // Free URB
194 //
195 ExFreePool(Urb);
196
197 return Status;
198 }
199
200 VOID NTAPI
201 DeviceStatusChangeThread(
202 IN PVOID Context)
203 {
204 NTSTATUS Status;
205 PDEVICE_OBJECT DeviceObject, RootHubDeviceObject;
206 PHUB_DEVICE_EXTENSION HubDeviceExtension;
207 PWORK_ITEM_DATA WorkItemData;
208 PORT_STATUS_CHANGE PortStatus;
209 LONG PortId;
210 BOOLEAN SignalResetComplete = FALSE;
211
212 DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context);
213
214 WorkItemData = (PWORK_ITEM_DATA)Context;
215 DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context;
216 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
217 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
218 //
219 // Loop all ports
220 //
221 for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
222 {
223 //
224 // Get Port Status
225 //
226 Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
227 if (!NT_SUCCESS(Status))
228 {
229 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status);
230 // FIXME: Do we really want to halt further SCE requests?
231 return;
232 }
233
234 DPRINT1("Port %d Status %x\n", PortId, PortStatus.Status);
235 DPRINT1("Port %d Change %x\n", PortId, PortStatus.Change);
236
237
238 //
239 // Check for new device connection
240 //
241 if (PortStatus.Change & USB_PORT_STATUS_CONNECT)
242 {
243 //
244 // Clear Port Connect
245 //
246 Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION);
247 if (!NT_SUCCESS(Status))
248 {
249 DPRINT1("Failed to clear connection change for port %d\n", PortId);
250 continue;
251 }
252
253 //
254 // Is this a connect or disconnect?
255 //
256 if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT))
257 {
258 DPRINT1("Device disconnected from port %d\n", PortId);
259
260 Status = DestroyUsbChildDeviceObject(DeviceObject, PortId);
261 if (!NT_SUCCESS(Status))
262 {
263 DPRINT1("Failed to delete child device object after disconnect\n");
264 continue;
265 }
266 }
267 else
268 {
269 DPRINT1("Device connected from port %d\n", PortId);
270
271 // No SCE completion done for clearing C_PORT_CONNECT
272
273 //
274 // Reset Port
275 //
276 Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET);
277 if (!NT_SUCCESS(Status))
278 {
279 DPRINT1("Failed to reset port %d\n", PortId);
280 SignalResetComplete = TRUE;
281 continue;
282 }
283 }
284 }
285 else if (PortStatus.Change & USB_PORT_STATUS_ENABLE)
286 {
287 //
288 // Clear Enable
289 //
290 Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_ENABLE);
291 if (!NT_SUCCESS(Status))
292 {
293 DPRINT1("Failed to clear enable change on port %d\n", PortId);
294 continue;
295 }
296 }
297 else if (PortStatus.Change & USB_PORT_STATUS_RESET)
298 {
299 //
300 // Request event signalling later
301 //
302 SignalResetComplete = TRUE;
303
304 //
305 // Clear Reset
306 //
307 Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_RESET);
308 if (!NT_SUCCESS(Status))
309 {
310 DPRINT1("Failed to clear reset change on port %d\n", PortId);
311 continue;
312 }
313
314 //
315 // Get Port Status
316 //
317 Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
318 if (!NT_SUCCESS(Status))
319 {
320 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status);
321 // FIXME: Do we really want to halt further SCE requests?
322 return;
323 }
324
325 DPRINT1("Port %d Status %x\n", PortId, PortStatus.Status);
326 DPRINT1("Port %d Change %x\n", PortId, PortStatus.Change);
327
328 //
329 // Check that reset was cleared
330 //
331 if(PortStatus.Change & USB_PORT_STATUS_RESET)
332 {
333 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
334 continue;
335 }
336
337 //
338 // Check if the device is still connected
339 //
340 if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT))
341 {
342 DPRINT1("Device has been disconnected\n");
343 continue;
344 }
345
346 //
347 // Make sure its Connected and Enabled
348 //
349 if (!(PortStatus.Status & (USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE)))
350 {
351 DPRINT1("Usb Device is not connected and enabled!\n");
352 //
353 // Attempt another reset
354 //
355 Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET);
356 if (!NT_SUCCESS(Status))
357 {
358 DPRINT1("Failed to reset port %d\n", PortId);
359 }
360 continue;
361 }
362
363 //
364 // This is a new device
365 //
366 Status = CreateUsbChildDeviceObject(DeviceObject, PortId, NULL, PortStatus.Status);
367 }
368 }
369
370 ExFreePool(WorkItemData);
371
372 //
373 // Send another SCE Request
374 //
375 DPRINT("Sending another SCE!\n");
376 QueryStatusChangeEndpoint(DeviceObject);
377
378 //
379 // Check if a reset event was satisfied
380 //
381 if (SignalResetComplete)
382 {
383 //
384 // Signal anyone waiting on it
385 //
386 KeSetEvent(&HubDeviceExtension->ResetComplete, IO_NO_INCREMENT, FALSE);
387 }
388 }
389
390 NTSTATUS
391 NTAPI
392 StatusChangeEndpointCompletion(
393 IN PDEVICE_OBJECT DeviceObject,
394 IN PIRP Irp,
395 IN PVOID Context)
396 {
397 PDEVICE_OBJECT RealDeviceObject;
398 PHUB_DEVICE_EXTENSION HubDeviceExtension;
399 PWORK_ITEM_DATA WorkItemData;
400
401 RealDeviceObject = (PDEVICE_OBJECT)Context;
402 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)RealDeviceObject->DeviceExtension;
403
404 //
405 // NOTE: USBPORT frees this IRP
406 //
407 DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp, HubDeviceExtension->PendingSCEIrp);
408 //IoFreeIrp(Irp);
409
410 //
411 // Create and initialize work item data
412 //
413 WorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_ITEM_DATA), USB_HUB_TAG);
414 if (!WorkItemData)
415 {
416 DPRINT1("Failed to allocate memory!n");
417 return STATUS_INSUFFICIENT_RESOURCES;
418 }
419 WorkItemData->Context = RealDeviceObject;
420
421 DPRINT("Queuing work item\n");
422
423 //
424 // Queue the work item to handle initializing the device
425 //
426 ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData);
427 ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
428
429 //
430 // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
431 //
432 return STATUS_MORE_PROCESSING_REQUIRED;
433 }
434
435 NTSTATUS
436 QueryStatusChangeEndpoint(
437 IN PDEVICE_OBJECT DeviceObject)
438 {
439 NTSTATUS Status;
440 PDEVICE_OBJECT RootHubDeviceObject;
441 PIO_STACK_LOCATION Stack;
442 PHUB_DEVICE_EXTENSION HubDeviceExtension;
443 PURB PendingSCEUrb;
444
445 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
446 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
447
448 //
449 // Allocate a URB
450 //
451 PendingSCEUrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
452
453 //
454 // Initialize URB for Status Change Endpoint request
455 //
456 UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb,
457 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
458 HubDeviceExtension->PipeHandle,
459 HubDeviceExtension->PortStatusChange,
460 NULL,
461 sizeof(USHORT) * 2 * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
462 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
463 NULL);
464
465 // Set the device handle
466 PendingSCEUrb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
467
468 //
469 // Allocate an Irp
470 //
471 HubDeviceExtension->PendingSCEIrp = ExAllocatePoolWithTag(NonPagedPool,
472 IoSizeOfIrp(RootHubDeviceObject->StackSize),
473 USB_HUB_TAG);
474 /*
475 HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
476 FALSE);
477 */
478 DPRINT("Allocated IRP %x\n", HubDeviceExtension->PendingSCEIrp);
479
480 if (!HubDeviceExtension->PendingSCEIrp)
481 {
482 DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
483 return STATUS_INSUFFICIENT_RESOURCES;
484 }
485
486 //
487 // Initialize the IRP
488 //
489 IoInitializeIrp(HubDeviceExtension->PendingSCEIrp,
490 IoSizeOfIrp(RootHubDeviceObject->StackSize),
491 RootHubDeviceObject->StackSize);
492
493 HubDeviceExtension->PendingSCEIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
494 HubDeviceExtension->PendingSCEIrp->IoStatus.Information = 0;
495 HubDeviceExtension->PendingSCEIrp->Flags = 0;
496 HubDeviceExtension->PendingSCEIrp->UserBuffer = NULL;
497
498 //
499 // Get the Next Stack Location and Initialize it
500 //
501 Stack = IoGetNextIrpStackLocation(HubDeviceExtension->PendingSCEIrp);
502 Stack->DeviceObject = DeviceObject;
503 Stack->Parameters.Others.Argument1 = PendingSCEUrb;
504 Stack->Parameters.Others.Argument2 = NULL;
505 Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
506 Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
507
508 //
509 // Set the completion routine for when device is connected to root hub
510 //
511 IoSetCompletionRoutine(HubDeviceExtension->PendingSCEIrp,
512 StatusChangeEndpointCompletion,
513 DeviceObject,
514 TRUE,
515 TRUE,
516 TRUE);
517
518 //
519 // Send to RootHub
520 //
521 DPRINT("DeviceObject is %x\n", DeviceObject);
522 DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp);
523 Status = IoCallDriver(RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp);
524
525 return STATUS_PENDING;
526 }
527
528 NTSTATUS
529 QueryInterface(
530 IN PDEVICE_OBJECT DeviceObject,
531 IN CONST GUID InterfaceType,
532 IN LONG Size,
533 IN LONG Version,
534 OUT PVOID Interface)
535 {
536 KEVENT Event;
537 PIRP Irp;
538 IO_STATUS_BLOCK IoStatus;
539 NTSTATUS Status;
540 PIO_STACK_LOCATION Stack = NULL;
541
542 //
543 // Initialize the Event used to wait for Irp completion
544 //
545 KeInitializeEvent(&Event, NotificationEvent, FALSE);
546
547 //
548 // Build Control Request
549 //
550 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
551 DeviceObject,
552 NULL,
553 0,
554 NULL,
555 &Event,
556 &IoStatus);
557
558 //
559 // Get Next Stack Location and Initialize it.
560 //
561 Stack = IoGetNextIrpStackLocation(Irp);
562 Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
563 Stack->Parameters.QueryInterface.InterfaceType= &InterfaceType;//USB_BUS_INTERFACE_HUB_GUID;
564 Stack->Parameters.QueryInterface.Size = Size;
565 Stack->Parameters.QueryInterface.Version = Version;
566 Stack->Parameters.QueryInterface.Interface = Interface;
567 Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
568
569 Status = IoCallDriver(DeviceObject, Irp);
570
571 if (Status == STATUS_PENDING)
572 {
573 DPRINT("Operation pending\n");
574 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
575 Status = IoStatus.Status;
576 }
577
578 return Status;
579 }
580
581 NTSTATUS
582 GetUsbDeviceDescriptor(
583 IN PDEVICE_OBJECT ChildDeviceObject,
584 IN UCHAR DescriptorType,
585 IN UCHAR Index,
586 IN USHORT LangId,
587 OUT PVOID TransferBuffer,
588 IN ULONG TransferBufferLength)
589 {
590 NTSTATUS Status;
591 PDEVICE_OBJECT RootHubDeviceObject;
592 PURB Urb;
593 PHUB_DEVICE_EXTENSION HubDeviceExtension;
594 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
595
596 //
597 // Get the Hubs Device Extension
598 //
599 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension;
600 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
601 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
602
603 //
604 // Allocate a URB
605 //
606 Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
607 if (!Urb)
608 {
609 DPRINT1("Failed to allocate memory for URB!\n");
610 return STATUS_INSUFFICIENT_RESOURCES;
611 }
612
613 //
614 // Zero it
615 //
616 RtlZeroMemory(Urb, sizeof(URB));
617
618 //
619 // Initialize URB for getting device descriptor
620 //
621 UsbBuildGetDescriptorRequest(Urb,
622 sizeof(Urb->UrbControlDescriptorRequest),
623 DescriptorType,
624 Index,
625 LangId,
626 TransferBuffer,
627 NULL,
628 TransferBufferLength,
629 NULL);
630
631 //
632 // Set the device handle
633 //
634 Urb->UrbHeader.UsbdDeviceHandle = (PVOID)ChildDeviceExtension->UsbDeviceHandle;
635
636 //
637 // Query the Root Hub
638 //
639 Status = SubmitRequestToRootHub(RootHubDeviceObject,
640 IOCTL_INTERNAL_USB_SUBMIT_URB,
641 Urb,
642 NULL);
643
644 return Status;
645 }
646
647 NTSTATUS
648 GetUsbStringDescriptor(
649 IN PDEVICE_OBJECT ChildDeviceObject,
650 IN UCHAR Index,
651 IN USHORT LangId,
652 OUT PVOID *TransferBuffer,
653 OUT USHORT *Size)
654 {
655 NTSTATUS Status;
656 PUSB_STRING_DESCRIPTOR StringDesc = NULL;
657 ULONG SizeNeeded;
658 LPWSTR Buffer;
659
660 StringDesc = ExAllocatePoolWithTag(NonPagedPool,
661 sizeof(USB_STRING_DESCRIPTOR),
662 USB_HUB_TAG);
663 if (!StringDesc)
664 {
665 DPRINT1("Failed to allocate buffer for string!\n");
666 return STATUS_INSUFFICIENT_RESOURCES;
667 }
668
669 //
670 // Get the index string descriptor length
671 // FIXME: Implement LangIds
672 //
673 Status = GetUsbDeviceDescriptor(ChildDeviceObject,
674 USB_STRING_DESCRIPTOR_TYPE,
675 Index,
676 0x0409,
677 StringDesc,
678 sizeof(USB_STRING_DESCRIPTOR));
679 if (!NT_SUCCESS(Status))
680 {
681 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status);
682 ExFreePool(StringDesc);
683 return Status;
684 }
685 DPRINT1("StringDesc->bLength %d\n", StringDesc->bLength);
686
687 //
688 // Did we get something more than the length of the first two fields of structure?
689 //
690 if (StringDesc->bLength == 2)
691 {
692 DPRINT1("USB Device Error!\n");
693 ExFreePool(StringDesc);
694 return STATUS_DEVICE_DATA_ERROR;
695 }
696 SizeNeeded = StringDesc->bLength + sizeof(WCHAR);
697
698 //
699 // Free String
700 //
701 ExFreePool(StringDesc);
702
703 //
704 // Recreate with appropriate size
705 //
706 StringDesc = ExAllocatePoolWithTag(NonPagedPool,
707 SizeNeeded,
708 USB_HUB_TAG);
709 if (!StringDesc)
710 {
711 DPRINT1("Failed to allocate buffer for string!\n");
712 return STATUS_INSUFFICIENT_RESOURCES;
713 }
714
715 RtlZeroMemory(StringDesc, SizeNeeded);
716
717 //
718 // Get the string
719 //
720 Status = GetUsbDeviceDescriptor(ChildDeviceObject,
721 USB_STRING_DESCRIPTOR_TYPE,
722 Index,
723 0x0409,
724 StringDesc,
725 SizeNeeded);
726 if (!NT_SUCCESS(Status))
727 {
728 DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status);
729 ExFreePool(StringDesc);
730 return Status;
731 }
732
733 //
734 // Allocate Buffer to return
735 //
736 Buffer = ExAllocatePoolWithTag(NonPagedPool,
737 SizeNeeded,
738 USB_HUB_TAG);
739 if (!Buffer)
740 {
741 DPRINT1("Failed to allocate buffer for string!\n");
742 ExFreePool(StringDesc);
743 return STATUS_INSUFFICIENT_RESOURCES;
744 }
745
746 RtlZeroMemory(Buffer, SizeNeeded);
747
748 //
749 // Copy the string to destination
750 //
751 RtlCopyMemory(Buffer, StringDesc->bString, SizeNeeded - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString));
752 *Size = SizeNeeded;
753 *TransferBuffer = Buffer;
754
755 ExFreePool(StringDesc);
756
757 return STATUS_SUCCESS;
758 }
759
760 ULONG
761 IsCompositeDevice(
762 IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
763 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
764 {
765 if (DeviceDescriptor->bNumConfigurations != 1)
766 {
767 //
768 // composite device must have only one configuration
769 //
770 DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
771 return FALSE;
772 }
773
774 if (ConfigurationDescriptor->bNumInterfaces < 2)
775 {
776 //
777 // composite device must have multiple interfaces
778 //
779 DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
780 return FALSE;
781 }
782
783 if (DeviceDescriptor->bDeviceClass == 0)
784 {
785 //
786 // composite device
787 //
788 ASSERT(DeviceDescriptor->bDeviceSubClass == 0);
789 ASSERT(DeviceDescriptor->bDeviceProtocol == 0);
790 DPRINT1("IsCompositeDevice: TRUE\n");
791 return TRUE;
792 }
793
794 if (DeviceDescriptor->bDeviceClass == 0xEF &&
795 DeviceDescriptor->bDeviceSubClass == 0x02 &&
796 DeviceDescriptor->bDeviceProtocol == 0x01)
797 {
798 //
799 // USB-IF association descriptor
800 //
801 DPRINT1("IsCompositeDevice: TRUE\n");
802 return TRUE;
803 }
804
805 DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol);
806
807 //
808 // not a composite device
809 //
810 return FALSE;
811 }
812
813 NTSTATUS
814 CreateDeviceIds(
815 PDEVICE_OBJECT UsbChildDeviceObject)
816 {
817 NTSTATUS Status = STATUS_SUCCESS;
818 ULONG Index = 0;
819 LPWSTR DeviceString;
820 WCHAR Buffer[200];
821 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
822 PHUB_DEVICE_EXTENSION HubDeviceExtension;
823 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
824 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
825 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
826
827 //
828 // get child device extension
829 //
830 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
831
832 // get hub device extension
833 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbChildExtension->ParentDeviceObject->DeviceExtension;
834
835 //
836 // get device descriptor
837 //
838 DeviceDescriptor = &UsbChildExtension->DeviceDesc;
839
840 //
841 // get configuration descriptor
842 //
843 ConfigurationDescriptor = UsbChildExtension->FullConfigDesc;
844
845 //
846 // use first interface descriptor available
847 //
848 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, 0, -1, -1, -1, -1);
849 ASSERT(InterfaceDescriptor);
850
851 //
852 // Construct the CompatibleIds
853 //
854 if (IsCompositeDevice(DeviceDescriptor, ConfigurationDescriptor))
855 {
856 //
857 // sanity checks
858 //
859 ASSERT(DeviceDescriptor->bNumConfigurations == 1);
860 ASSERT(ConfigurationDescriptor->bNumInterfaces > 1);
861 Index += swprintf(&Buffer[Index],
862 L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
863 DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1;
864 Index += swprintf(&Buffer[Index],
865 L"USB\\DevClass_%02x&SubClass_%02x",
866 DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1;
867 Index += swprintf(&Buffer[Index],
868 L"USB\\DevClass_%02x",
869 DeviceDescriptor->bDeviceClass) + 1;
870 Index += swprintf(&Buffer[Index],
871 L"USB\\COMPOSITE") + 1;
872 }
873 else
874 {
875 //
876 // FIXME: support multiple configurations
877 //
878 ASSERT(DeviceDescriptor->bNumConfigurations == 1);
879
880 if (DeviceDescriptor->bDeviceClass == 0)
881 {
882 Index += swprintf(&Buffer[Index],
883 L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
884 InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass, InterfaceDescriptor->bInterfaceProtocol) + 1;
885 Index += swprintf(&Buffer[Index],
886 L"USB\\Class_%02x&SubClass_%02x",
887 InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass) + 1;
888 Index += swprintf(&Buffer[Index],
889 L"USB\\Class_%02x",
890 InterfaceDescriptor->bInterfaceClass) + 1;
891 }
892 else
893 {
894 Index += swprintf(&Buffer[Index],
895 L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
896 DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1;
897 Index += swprintf(&Buffer[Index],
898 L"USB\\Class_%02x&SubClass_%02x",
899 DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1;
900 Index += swprintf(&Buffer[Index],
901 L"USB\\Class_%02x",
902 DeviceDescriptor->bDeviceClass) + 1;
903 }
904 }
905
906 //
907 // now allocate the buffer
908 //
909 DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR));
910 if (!DeviceString)
911 {
912 //
913 // no memory
914 //
915 return STATUS_INSUFFICIENT_RESOURCES;
916 }
917
918 //
919 // copy buffer
920 //
921 RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
922 DeviceString[Index] = UNICODE_NULL;
923 UsbChildExtension->usCompatibleIds.Buffer = DeviceString;
924 UsbChildExtension->usCompatibleIds.Length = Index * sizeof(WCHAR);
925 UsbChildExtension->usCompatibleIds.MaximumLength = (Index + 1) * sizeof(WCHAR);
926 DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension->usCompatibleIds);
927
928 //
929 // Construct DeviceId string
930 //
931 Index = swprintf(Buffer, L"USB\\Vid_%04x&Pid_%04x", UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1;
932
933 //
934 // now allocate the buffer
935 //
936 DeviceString = ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
937 if (!DeviceString)
938 {
939 //
940 // no memory
941 //
942 return STATUS_INSUFFICIENT_RESOURCES;
943 }
944
945 //
946 // copy buffer
947 //
948 RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
949 UsbChildExtension->usDeviceId.Buffer = DeviceString;
950 UsbChildExtension->usDeviceId.Length = (Index-1) * sizeof(WCHAR);
951 UsbChildExtension->usDeviceId.MaximumLength = Index * sizeof(WCHAR);
952 DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usDeviceId);
953
954 //
955 // Construct HardwareIds
956 //
957 Index = 0;
958 Index += swprintf(&Buffer[Index],
959 L"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
960 UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct, UsbChildExtension->DeviceDesc.bcdDevice) + 1;
961 Index += swprintf(&Buffer[Index],
962 L"USB\\Vid_%04x&Pid_%04x",
963 UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1;
964
965 //
966 // now allocate the buffer
967 //
968 DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR));
969 if (!DeviceString)
970 {
971 //
972 // no memory
973 //
974 return STATUS_INSUFFICIENT_RESOURCES;
975 }
976
977 //
978 // copy buffer
979 //
980 RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
981 DeviceString[Index] = UNICODE_NULL;
982 UsbChildExtension->usHardwareIds.Buffer = DeviceString;
983 UsbChildExtension->usHardwareIds.Length = (Index + 1) * sizeof(WCHAR);
984 UsbChildExtension->usHardwareIds.MaximumLength = (Index + 1) * sizeof(WCHAR);
985 DPRINT("usHardWareIds %wZ\n", &UsbChildExtension->usHardwareIds);
986
987 //
988 // FIXME: Handle Lang ids
989 //
990
991 //
992 // Get the product string if obe provided
993 //
994 if (UsbChildExtension->DeviceDesc.iProduct)
995 {
996 Status = GetUsbStringDescriptor(UsbChildDeviceObject,
997 UsbChildExtension->DeviceDesc.iProduct,
998 0,
999 (PVOID*)&UsbChildExtension->usTextDescription.Buffer,
1000 &UsbChildExtension->usTextDescription.Length);
1001 if (!NT_SUCCESS(Status))
1002 {
1003 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status);
1004 RtlInitUnicodeString(&UsbChildExtension->usTextDescription, L"USB Device"); // FIXME NON-NLS
1005 }
1006 else
1007 {
1008 UsbChildExtension->usTextDescription.MaximumLength = UsbChildExtension->usTextDescription.Length;
1009 DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension->usTextDescription);
1010 }
1011 }
1012
1013 //
1014 // Get the Serial Number string if obe provided
1015 //
1016 if (UsbChildExtension->DeviceDesc.iSerialNumber)
1017 {
1018 LPWSTR SerialBuffer = NULL;
1019
1020 Status = GetUsbStringDescriptor(UsbChildDeviceObject,
1021 UsbChildExtension->DeviceDesc.iSerialNumber,
1022 0,
1023 (PVOID*)&SerialBuffer,
1024 &UsbChildExtension->usInstanceId.Length);
1025 if (!NT_SUCCESS(Status))
1026 {
1027 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status);
1028 return Status;
1029 }
1030
1031 // construct instance id buffer
1032 Index = swprintf(Buffer, L"%04d&%s", HubDeviceExtension->InstanceCount, SerialBuffer) + 1;
1033 UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
1034 if (UsbChildExtension->usInstanceId.Buffer == NULL)
1035 {
1036 DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
1037 Status = STATUS_INSUFFICIENT_RESOURCES;
1038 return Status;
1039 }
1040
1041 //
1042 // copy instance id
1043 //
1044 RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
1045 UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR);
1046 ExFreePool(SerialBuffer);
1047
1048 DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension->usInstanceId, HubDeviceExtension->InstanceCount);
1049 }
1050 else
1051 {
1052 //
1053 // the device did not provide a serial number, lets create a pseudo instance id
1054 //
1055 Index = swprintf(Buffer, L"%04d&%04d", HubDeviceExtension->InstanceCount, UsbChildExtension->PortNumber) + 1;
1056 UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
1057 if (UsbChildExtension->usInstanceId.Buffer == NULL)
1058 {
1059 DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
1060 Status = STATUS_INSUFFICIENT_RESOURCES;
1061 return Status;
1062 }
1063
1064 //
1065 // copy instance id
1066 //
1067 RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
1068 UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR);
1069
1070 DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usInstanceId);
1071 }
1072
1073 return STATUS_SUCCESS;
1074 }
1075
1076 NTSTATUS
1077 DestroyUsbChildDeviceObject(
1078 IN PDEVICE_OBJECT UsbHubDeviceObject,
1079 IN LONG PortId)
1080 {
1081 PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbHubDeviceObject->DeviceExtension;
1082 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = NULL;
1083 PDEVICE_OBJECT ChildDeviceObject = NULL;
1084 ULONG Index = 0;
1085
1086 DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index);
1087
1088 for (Index = 0; Index < USB_MAXCHILDREN; Index++)
1089 {
1090 if (HubDeviceExtension->ChildDeviceObject[Index])
1091 {
1092 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension;
1093
1094 /* Check if it matches the port ID */
1095 if (UsbChildExtension->PortNumber == PortId)
1096 {
1097 /* We found it */
1098 ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[Index];
1099 break;
1100 }
1101 }
1102 }
1103
1104 /* Fail the request if the device doesn't exist */
1105 if (!ChildDeviceObject)
1106 {
1107 DPRINT1("Removal request for non-existant device!\n");
1108 return STATUS_UNSUCCESSFUL;
1109 }
1110
1111 /* Remove the device from the table */
1112 HubDeviceExtension->ChildDeviceObject[Index] = NULL;
1113
1114 /* Invalidate device relations for the root hub */
1115 IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations);
1116
1117 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1118 return STATUS_SUCCESS;
1119 }
1120
1121 NTSTATUS
1122 CreateUsbChildDeviceObject(
1123 IN PDEVICE_OBJECT UsbHubDeviceObject,
1124 IN LONG PortId,
1125 OUT PDEVICE_OBJECT *UsbChildDeviceObject,
1126 IN ULONG PortStatus)
1127 {
1128 NTSTATUS Status;
1129 PDEVICE_OBJECT RootHubDeviceObject, NewChildDeviceObject;
1130 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1131 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
1132 PUSB_BUS_INTERFACE_HUB_V5 HubInterface;
1133 ULONG ChildDeviceCount, UsbDeviceNumber = 0;
1134 WCHAR CharDeviceName[64];
1135 UNICODE_STRING DeviceName;
1136 ULONG ConfigDescSize, DeviceDescSize;
1137 PVOID HubInterfaceBusContext;
1138 USB_CONFIGURATION_DESCRIPTOR ConfigDesc;
1139
1140 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbHubDeviceObject->DeviceExtension;
1141 HubInterface = &HubDeviceExtension->HubInterface;
1142 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
1143 HubInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext;
1144 //
1145 // Find an empty slot in the child device array
1146 //
1147 for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++)
1148 {
1149 if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL)
1150 {
1151 DPRINT("Found unused entry at %d\n", ChildDeviceCount);
1152 break;
1153 }
1154 }
1155
1156 //
1157 // Check if the limit has been reached for maximum usb devices
1158 //
1159 if (ChildDeviceCount == USB_MAXCHILDREN)
1160 {
1161 DPRINT1("USBHUB: Too many child devices!\n");
1162 return STATUS_UNSUCCESSFUL;
1163 }
1164
1165 while (TRUE)
1166 {
1167 //
1168 // Create a Device Name
1169 //
1170 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
1171
1172 //
1173 // Initialize UnicodeString
1174 //
1175 RtlInitUnicodeString(&DeviceName, CharDeviceName);
1176
1177 //
1178 // Create a DeviceObject
1179 //
1180 Status = IoCreateDevice(UsbHubDeviceObject->DriverObject,
1181 sizeof(HUB_CHILDDEVICE_EXTENSION),
1182 NULL,
1183 FILE_DEVICE_CONTROLLER,
1184 FILE_AUTOGENERATED_DEVICE_NAME,
1185 FALSE,
1186 &NewChildDeviceObject);
1187
1188 //
1189 // Check if the name is already in use
1190 //
1191 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
1192 {
1193 //
1194 // Try next name
1195 //
1196 UsbDeviceNumber++;
1197 continue;
1198 }
1199
1200 //
1201 // Check for other errors
1202 //
1203 if (!NT_SUCCESS(Status))
1204 {
1205 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status);
1206 return Status;
1207 }
1208
1209 DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject);
1210 break;
1211 }
1212
1213 NewChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
1214
1215 //
1216 // Assign the device extensions
1217 //
1218 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)NewChildDeviceObject->DeviceExtension;
1219 RtlZeroMemory(UsbChildExtension, sizeof(HUB_CHILDDEVICE_EXTENSION));
1220 UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject;
1221 UsbChildExtension->PortNumber = PortId;
1222
1223 // copy device interface
1224 RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
1225
1226
1227 //
1228 // Create the UsbDeviceObject
1229 //
1230 Status = HubInterface->CreateUsbDevice(HubInterfaceBusContext,
1231 (PVOID)&UsbChildExtension->UsbDeviceHandle,
1232 HubDeviceExtension->RootHubHandle,
1233 PortStatus,
1234 PortId);
1235 if (!NT_SUCCESS(Status))
1236 {
1237 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status);
1238 goto Cleanup;
1239 }
1240
1241 // copy device interface
1242 RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
1243
1244 // FIXME replace buscontext
1245 UsbChildExtension->DeviceInterface.BusContext = UsbChildExtension->UsbDeviceHandle;
1246
1247 //
1248 // Initialize UsbDevice
1249 //
1250 Status = HubInterface->InitializeUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle);
1251 if (!NT_SUCCESS(Status))
1252 {
1253 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status);
1254 goto Cleanup;
1255 }
1256
1257 DPRINT("Usb Device Handle %x\n", UsbChildExtension->UsbDeviceHandle);
1258
1259 ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
1260 DeviceDescSize = sizeof(USB_DEVICE_DESCRIPTOR);
1261
1262 //
1263 // Get the descriptors
1264 //
1265 Status = HubInterface->GetUsbDescriptors(HubInterfaceBusContext,
1266 UsbChildExtension->UsbDeviceHandle,
1267 (PUCHAR)&UsbChildExtension->DeviceDesc,
1268 &DeviceDescSize,
1269 (PUCHAR)&ConfigDesc,
1270 &ConfigDescSize);
1271 if (!NT_SUCCESS(Status))
1272 {
1273 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status);
1274 goto Cleanup;
1275 }
1276
1277 DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc);
1278 DumpConfigurationDescriptor(&ConfigDesc);
1279
1280 //
1281 // FIXME: Support more than one configuration and one interface?
1282 //
1283 if (UsbChildExtension->DeviceDesc.bNumConfigurations > 1)
1284 {
1285 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1286 }
1287
1288 if (ConfigDesc.bNumInterfaces > 1)
1289 {
1290 DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
1291 }
1292
1293 ConfigDescSize = ConfigDesc.wTotalLength;
1294
1295 //
1296 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1297 //
1298 UsbChildExtension->FullConfigDesc = ExAllocatePoolWithTag(PagedPool, ConfigDescSize, USB_HUB_TAG);
1299
1300 //
1301 // Retrieve the full configuration descriptor
1302 //
1303 Status = GetUsbDeviceDescriptor(NewChildDeviceObject,
1304 USB_CONFIGURATION_DESCRIPTOR_TYPE,
1305 0,
1306 0,
1307 UsbChildExtension->FullConfigDesc,
1308 ConfigDescSize);
1309
1310 if (!NT_SUCCESS(Status))
1311 {
1312 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status);
1313 goto Cleanup;
1314 }
1315
1316 //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1317
1318 //
1319 // Construct all the strings that will described the device to PNP
1320 //
1321 Status = CreateDeviceIds(NewChildDeviceObject);
1322 if (!NT_SUCCESS(Status))
1323 {
1324 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1325 goto Cleanup;
1326 }
1327
1328 HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject;
1329 HubDeviceExtension->InstanceCount++;
1330
1331 IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations);
1332 return STATUS_SUCCESS;
1333
1334 Cleanup:
1335
1336 //
1337 // Remove the usb device if it was created
1338 //
1339 if (UsbChildExtension->UsbDeviceHandle)
1340 HubInterface->RemoveUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle, 0);
1341
1342 //
1343 // Free full configuration descriptor if one was allocated
1344 //
1345 if (UsbChildExtension->FullConfigDesc)
1346 ExFreePool(UsbChildExtension->FullConfigDesc);
1347
1348 //
1349 // Delete the device object
1350 //
1351 IoDeleteDevice(NewChildDeviceObject);
1352 return Status;
1353 }
1354
1355 NTSTATUS
1356 USBHUB_FdoQueryBusRelations(
1357 IN PDEVICE_OBJECT DeviceObject,
1358 OUT PDEVICE_RELATIONS* pDeviceRelations)
1359 {
1360 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1361 PDEVICE_RELATIONS DeviceRelations;
1362 ULONG i;
1363 ULONG Children = 0;
1364 ULONG NeededSize;
1365
1366 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1367
1368 //
1369 // Count the number of children
1370 //
1371 for (i = 0; i < USB_MAXCHILDREN; i++)
1372 {
1373
1374 if (HubDeviceExtension->ChildDeviceObject[i] == NULL)
1375 {
1376 continue;
1377 }
1378 Children++;
1379 }
1380
1381 NeededSize = sizeof(DEVICE_RELATIONS);
1382 if (Children > 1)
1383 NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT);
1384
1385 //
1386 // Allocate DeviceRelations
1387 //
1388 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool,
1389 NeededSize);
1390
1391 if (!DeviceRelations)
1392 return STATUS_INSUFFICIENT_RESOURCES;
1393 DeviceRelations->Count = Children;
1394 Children = 0;
1395
1396 //
1397 // Fill in return structure
1398 //
1399 for (i = 0; i < USB_MAXCHILDREN; i++)
1400 {
1401 if (HubDeviceExtension->ChildDeviceObject[i])
1402 {
1403 ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]);
1404 HubDeviceExtension->ChildDeviceObject[i]->Flags &= ~DO_DEVICE_INITIALIZING;
1405 DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i];
1406 }
1407 }
1408
1409 ASSERT(Children == DeviceRelations->Count);
1410 *pDeviceRelations = DeviceRelations;
1411
1412 return STATUS_SUCCESS;
1413 }
1414
1415 VOID
1416 NTAPI
1417 RootHubInitCallbackFunction(
1418 PVOID Context)
1419 {
1420 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
1421 NTSTATUS Status;
1422 ULONG PortId;
1423 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1424 PORT_STATUS_CHANGE StatusChange;
1425
1426 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
1427
1428 DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject);
1429
1430 //
1431 // Send the first SCE Request
1432 //
1433 QueryStatusChangeEndpoint(DeviceObject);
1434
1435 for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
1436 {
1437 //
1438 // get port status
1439 //
1440 Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange);
1441 if (NT_SUCCESS(Status))
1442 {
1443 //
1444 // is there a device connected
1445 //
1446 if (StatusChange.Status & USB_PORT_STATUS_CONNECT)
1447 {
1448 //
1449 // reset port
1450 //
1451 Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
1452 if (!NT_SUCCESS(Status))
1453 {
1454 DPRINT1("Failed to reset on port %d\n", PortId);
1455 }
1456 else
1457 {
1458 //
1459 // wait for the reset to be handled since we want to enumerate synchronously
1460 //
1461 KeWaitForSingleObject(&HubDeviceExtension->ResetComplete,
1462 Executive,
1463 KernelMode,
1464 FALSE,
1465 NULL);
1466 KeClearEvent(&HubDeviceExtension->ResetComplete);
1467 }
1468 }
1469 }
1470 }
1471 }
1472
1473 BOOLEAN
1474 USBHUB_IsRootHubFDO(
1475 IN PDEVICE_OBJECT DeviceObject)
1476 {
1477 NTSTATUS Status;
1478 PDEVICE_OBJECT RootHubPhysicalDeviceObject = NULL;
1479 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1480
1481 // get hub device extension
1482 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
1483
1484 // Get the Root Hub Pdo
1485 Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
1486 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
1487 &RootHubPhysicalDeviceObject,
1488 NULL);
1489
1490 // FIXME handle error
1491 ASSERT(NT_SUCCESS(Status));
1492
1493 // physical device object is only obtained for root hubs
1494 return (RootHubPhysicalDeviceObject != NULL);
1495 }
1496
1497
1498 NTSTATUS
1499 USBHUB_FdoStartDevice(
1500 IN PDEVICE_OBJECT DeviceObject,
1501 IN PIRP Irp)
1502 {
1503 PURB Urb;
1504 PUSB_INTERFACE_DESCRIPTOR Pid;
1505 ULONG Result = 0, PortId;
1506 USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
1507 PURB ConfigUrb = NULL;
1508 ULONG HubStatus;
1509 PIO_STACK_LOCATION Stack;
1510 NTSTATUS Status = STATUS_SUCCESS;
1511 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1512 PDEVICE_OBJECT RootHubDeviceObject;
1513 PVOID HubInterfaceBusContext , UsbDInterfaceBusContext;
1514 PORT_STATUS_CHANGE StatusChange;
1515
1516 // get current stack location
1517 Stack = IoGetCurrentIrpStackLocation(Irp);
1518
1519 // get hub device extension
1520 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
1521
1522 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1523
1524 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1525 Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG);
1526 if (!Urb)
1527 {
1528 // no memory
1529 return STATUS_INSUFFICIENT_RESOURCES;
1530 }
1531
1532 // zero urb
1533 RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY));
1534
1535 // Get the Root Hub Pdo
1536 Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
1537 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
1538 &HubDeviceExtension->RootHubPhysicalDeviceObject,
1539 &HubDeviceExtension->RootHubFunctionalDeviceObject);
1540 if (!NT_SUCCESS(Status))
1541 {
1542 // failed to obtain hub pdo
1543 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status);
1544 ExFreePool(Urb);
1545 return Status;
1546 }
1547
1548 // sanity checks
1549 ASSERT(HubDeviceExtension->RootHubPhysicalDeviceObject);
1550 ASSERT(HubDeviceExtension->RootHubFunctionalDeviceObject);
1551
1552 // get roothub
1553 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
1554
1555 // Send the StartDevice to RootHub
1556 Status = ForwardIrpAndWait(RootHubDeviceObject, Irp);
1557
1558 if (!NT_SUCCESS(Status))
1559 {
1560 // failed to start pdo
1561 DPRINT1("Failed to start the RootHub PDO\n");
1562 ExFreePool(Urb);
1563 return Status;
1564 }
1565
1566 // Get the current number of hubs
1567 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1568 IOCTL_INTERNAL_USB_GET_HUB_COUNT,
1569 &HubDeviceExtension->NumberOfHubs, NULL);
1570 if (!NT_SUCCESS(Status))
1571 {
1572 // failed to get number of hubs
1573 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status);
1574 ExFreePool(Urb);
1575 return Status;
1576 }
1577
1578 // Get the Hub Interface
1579 Status = QueryInterface(RootHubDeviceObject,
1580 USB_BUS_INTERFACE_HUB_GUID,
1581 sizeof(USB_BUS_INTERFACE_HUB_V5),
1582 USB_BUSIF_HUB_VERSION_5,
1583 (PVOID)&HubDeviceExtension->HubInterface);
1584
1585 if (!NT_SUCCESS(Status))
1586 {
1587 // failed to get root hub interface
1588 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
1589 ExFreePool(Urb);
1590 return Status;
1591 }
1592
1593 HubInterfaceBusContext = HubDeviceExtension->HubInterface.BusContext;
1594
1595 // Get the USBDI Interface
1596 Status = QueryInterface(RootHubDeviceObject,
1597 USB_BUS_INTERFACE_USBDI_GUID,
1598 sizeof(USB_BUS_INTERFACE_USBDI_V2),
1599 USB_BUSIF_USBDI_VERSION_2,
1600 (PVOID)&HubDeviceExtension->UsbDInterface);
1601
1602 if (!NT_SUCCESS(Status))
1603 {
1604 // failed to get usbdi interface
1605 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status);
1606 ExFreePool(Urb);
1607 return Status;
1608 }
1609
1610 UsbDInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext;
1611
1612 // Get Root Hub Device Handle
1613 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1614 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
1615 &HubDeviceExtension->RootHubHandle,
1616 NULL);
1617
1618 if (!NT_SUCCESS(Status))
1619 {
1620 // failed
1621 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status);
1622 ExFreePool(Urb);
1623 return Status;
1624 }
1625
1626 //
1627 // Get Hub Device Information
1628 //
1629 Status = HubDeviceExtension->HubInterface.QueryDeviceInformation(HubInterfaceBusContext,
1630 HubDeviceExtension->RootHubHandle,
1631 &HubDeviceExtension->DeviceInformation,
1632 sizeof(USB_DEVICE_INFORMATION_0),
1633 &Result);
1634
1635 DPRINT1("Status %x, Result 0x%08lx\n", Status, Result);
1636 DPRINT1("InformationLevel %x\n", HubDeviceExtension->DeviceInformation.InformationLevel);
1637 DPRINT1("ActualLength %x\n", HubDeviceExtension->DeviceInformation.ActualLength);
1638 DPRINT1("PortNumber %x\n", HubDeviceExtension->DeviceInformation.PortNumber);
1639 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension->DeviceInformation.DeviceDescriptor);
1640 DPRINT1("HubAddress %x\n", HubDeviceExtension->DeviceInformation.HubAddress);
1641 DPRINT1("NumberofPipes %x\n", HubDeviceExtension->DeviceInformation.NumberOfOpenPipes);
1642
1643 // Get Root Hubs Device Descriptor
1644 UsbBuildGetDescriptorRequest(Urb,
1645 sizeof(Urb->UrbControlDescriptorRequest),
1646 USB_DEVICE_DESCRIPTOR_TYPE,
1647 0,
1648 0,
1649 &HubDeviceExtension->HubDeviceDescriptor,
1650 NULL,
1651 sizeof(USB_DEVICE_DESCRIPTOR),
1652 NULL);
1653
1654 // set device handle
1655 Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
1656
1657 // get hub device descriptor
1658 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1659 IOCTL_INTERNAL_USB_SUBMIT_URB,
1660 Urb,
1661 NULL);
1662
1663 if (!NT_SUCCESS(Status))
1664 {
1665 // failed to get device descriptor of hub
1666 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1667 ExFreePool(Urb);
1668 return Status;
1669 }
1670
1671 // build configuration request
1672 UsbBuildGetDescriptorRequest(Urb,
1673 sizeof(Urb->UrbControlDescriptorRequest),
1674 USB_CONFIGURATION_DESCRIPTOR_TYPE,
1675 0,
1676 0,
1677 &HubDeviceExtension->HubConfigDescriptor,
1678 NULL,
1679 sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
1680 NULL);
1681
1682 // set device handle
1683 Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
1684
1685 // request configuration descriptor
1686 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1687 IOCTL_INTERNAL_USB_SUBMIT_URB,
1688 Urb,
1689 NULL);
1690
1691 if (!NT_SUCCESS(Status))
1692 {
1693 // failed to get configuration descriptor
1694 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status);
1695 ExFreePool(Urb);
1696 return Status;
1697 }
1698
1699 // sanity checks
1700 ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength == sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR));
1701 ASSERT(HubDeviceExtension->HubConfigDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE);
1702 ASSERT(HubDeviceExtension->HubConfigDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
1703 ASSERT(HubDeviceExtension->HubConfigDescriptor.bNumInterfaces == 1);
1704 ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
1705 ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
1706 ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bNumEndpoints == 1);
1707 ASSERT(HubDeviceExtension->HubEndPointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);
1708 ASSERT(HubDeviceExtension->HubEndPointDescriptor.bLength == sizeof(USB_ENDPOINT_DESCRIPTOR));
1709 ASSERT(HubDeviceExtension->HubEndPointDescriptor.bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT);
1710 ASSERT(HubDeviceExtension->HubEndPointDescriptor.bEndpointAddress == 0x81); // interrupt in
1711
1712 // get hub information
1713 Status = HubDeviceExtension->HubInterface.GetExtendedHubInformation(HubInterfaceBusContext,
1714 RootHubDeviceObject,
1715 &HubDeviceExtension->UsbExtHubInfo,
1716 sizeof(USB_EXTHUB_INFORMATION_0),
1717 &Result);
1718 if (!NT_SUCCESS(Status))
1719 {
1720 // failed to get hub information
1721 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1722 ExFreePool(Urb);
1723 return Status;
1724 }
1725
1726 if (!HubDeviceExtension->UsbExtHubInfo.NumberOfPorts)
1727 {
1728 // bogus port driver
1729 DPRINT1("Failed to retrieve the number of ports\n");
1730 ExFreePool(Urb);
1731 return STATUS_UNSUCCESSFUL;
1732 }
1733
1734 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
1735
1736 // Build hub descriptor request
1737 UsbBuildVendorRequest(Urb,
1738 URB_FUNCTION_CLASS_DEVICE,
1739 sizeof(Urb->UrbControlVendorClassRequest),
1740 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
1741 0,
1742 USB_REQUEST_GET_DESCRIPTOR,
1743 USB_DEVICE_CLASS_RESERVED,
1744 0,
1745 &HubDeviceExtension->HubDescriptor,
1746 NULL,
1747 sizeof(USB_HUB_DESCRIPTOR),
1748 NULL);
1749
1750 // set device handle
1751 Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
1752
1753 // send request
1754 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1755 IOCTL_INTERNAL_USB_SUBMIT_URB,
1756 Urb,
1757 NULL);
1758
1759 if (!NT_SUCCESS(Status))
1760 {
1761 DPRINT1("Failed to get Hub Descriptor!\n");
1762 ExFreePool(Urb);
1763 return STATUS_UNSUCCESSFUL;
1764 }
1765
1766 // sanity checks
1767 ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR));
1768 ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts == HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
1769 ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29);
1770
1771 // build get status request
1772 HubStatus = 0;
1773 UsbBuildGetStatusRequest(Urb,
1774 URB_FUNCTION_GET_STATUS_FROM_DEVICE,
1775 0,
1776 &HubStatus,
1777 0,
1778 NULL);
1779 // set device handle
1780 Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
1781
1782 // send request
1783 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1784 IOCTL_INTERNAL_USB_SUBMIT_URB,
1785 Urb,
1786 NULL);
1787 if (!NT_SUCCESS(Status))
1788 {
1789 // failed to get hub status
1790 DPRINT1("Failed to get Hub Status!\n");
1791 ExFreePool(Urb);
1792 return STATUS_UNSUCCESSFUL;
1793 }
1794
1795 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1796 HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool,
1797 sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
1798 USB_HUB_TAG);
1799
1800 // Get the first Configuration Descriptor
1801 Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor,
1802 &HubDeviceExtension->HubConfigDescriptor,
1803 -1, -1, -1, -1, -1);
1804 if (Pid == NULL)
1805 {
1806 // failed parse hub descriptor
1807 DPRINT1("Failed to parse configuration descriptor\n");
1808 ExFreePool(Urb);
1809 return STATUS_UNSUCCESSFUL;
1810 }
1811
1812 // create configuration request
1813 InterfaceList[0].InterfaceDescriptor = Pid;
1814 ConfigUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor,
1815 (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
1816 if (ConfigUrb == NULL)
1817 {
1818 // failed to build urb
1819 DPRINT1("Failed to allocate urb\n");
1820 ExFreePool(Urb);
1821 return STATUS_INSUFFICIENT_RESOURCES;
1822 }
1823
1824 // send request
1825 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1826 IOCTL_INTERNAL_USB_SUBMIT_URB,
1827 ConfigUrb,
1828 NULL);
1829 if (!NT_SUCCESS(Status))
1830 {
1831 // failed to select configuration
1832 DPRINT1("Failed to select configuration with %x\n", Status);
1833 ExFreePool(Urb);
1834 ExFreePool(ConfigUrb);
1835 return Status;
1836 }
1837
1838 // store configuration & pipe handle
1839 HubDeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle;
1840 HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
1841 DPRINT("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle);
1842
1843 FDO_QueryInterface(DeviceObject, &HubDeviceExtension->DeviceInterface);
1844
1845
1846 // free urb
1847 ExFreePool(ConfigUrb);
1848
1849 // check if function is available
1850 if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed)
1851 {
1852 // is it high speed bus
1853 if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed(HubInterfaceBusContext))
1854 {
1855 // initialize usb 2.0 hub
1856 Status = HubDeviceExtension->HubInterface.Initialize20Hub(HubInterfaceBusContext,
1857 HubDeviceExtension->RootHubHandle, 1);
1858 DPRINT("Status %x\n", Status);
1859
1860 // FIXME handle error
1861 ASSERT(Status == STATUS_SUCCESS);
1862 }
1863 }
1864
1865
1866 // Enable power on all ports
1867 DPRINT("Enabling PortPower on all ports!\n");
1868 for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
1869 {
1870 Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_POWER);
1871 if (!NT_SUCCESS(Status))
1872 DPRINT1("Failed to power on port %d\n", PortId);
1873
1874 Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION);
1875 if (!NT_SUCCESS(Status))
1876 DPRINT1("Failed to power on port %d\n", PortId);
1877 }
1878
1879 // init root hub notification
1880 if (HubDeviceExtension->HubInterface.RootHubInitNotification)
1881 {
1882 Status = HubDeviceExtension->HubInterface.RootHubInitNotification(HubInterfaceBusContext,
1883 DeviceObject,
1884 RootHubInitCallbackFunction);
1885 if (!NT_SUCCESS(Status))
1886 {
1887 DPRINT1("Failed to set callback\n");
1888 ExFreePool(Urb);
1889 return Status;
1890 }
1891 }
1892 else
1893 {
1894 // Send the first SCE Request
1895 QueryStatusChangeEndpoint(DeviceObject);
1896
1897 //
1898 // reset ports
1899 //
1900 for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
1901 {
1902 //
1903 // get port status
1904 //
1905 Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange);
1906 if (NT_SUCCESS(Status))
1907 {
1908 //
1909 // is there a device connected
1910 //
1911 if (StatusChange.Status & USB_PORT_STATUS_CONNECT)
1912 {
1913 //
1914 // reset port
1915 //
1916 Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
1917 if (!NT_SUCCESS(Status))
1918 {
1919 DPRINT1("Failed to reset on port %d\n", PortId);
1920 }
1921 else
1922 {
1923 //
1924 // wait for the reset to be handled since we want to enumerate synchronously
1925 //
1926 KeWaitForSingleObject(&HubDeviceExtension->ResetComplete,
1927 Executive,
1928 KernelMode,
1929 FALSE,
1930 NULL);
1931 KeClearEvent(&HubDeviceExtension->ResetComplete);
1932 }
1933 }
1934 }
1935 }
1936 }
1937
1938 // free urb
1939 ExFreePool(Urb);
1940
1941 // done
1942 return Status;
1943 }
1944
1945 NTSTATUS
1946 USBHUB_FdoHandlePnp(
1947 IN PDEVICE_OBJECT DeviceObject,
1948 IN PIRP Irp)
1949 {
1950 PIO_STACK_LOCATION Stack;
1951 NTSTATUS Status = STATUS_SUCCESS;
1952 ULONG_PTR Information = 0;
1953 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1954
1955 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
1956
1957 Stack = IoGetCurrentIrpStackLocation(Irp);
1958
1959 switch (Stack->MinorFunction)
1960 {
1961 case IRP_MN_START_DEVICE:
1962 {
1963 if (USBHUB_IsRootHubFDO(DeviceObject))
1964 {
1965 // start root hub fdo
1966 Status = USBHUB_FdoStartDevice(DeviceObject, Irp);
1967 }
1968 else
1969 {
1970 Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp);
1971 }
1972 break;
1973 }
1974
1975 case IRP_MN_QUERY_DEVICE_RELATIONS:
1976 {
1977 switch (Stack->Parameters.QueryDeviceRelations.Type)
1978 {
1979 case BusRelations:
1980 {
1981 PDEVICE_RELATIONS DeviceRelations = NULL;
1982 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1983
1984 Status = USBHUB_FdoQueryBusRelations(DeviceObject, &DeviceRelations);
1985
1986 Information = (ULONG_PTR)DeviceRelations;
1987 break;
1988 }
1989 case RemovalRelations:
1990 {
1991 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1992 return ForwardIrpAndForget(DeviceObject, Irp);
1993 }
1994 default:
1995 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1996 Stack->Parameters.QueryDeviceRelations.Type);
1997 return ForwardIrpAndForget(DeviceObject, Irp);
1998 }
1999 break;
2000 }
2001 case IRP_MN_QUERY_REMOVE_DEVICE:
2002 case IRP_MN_QUERY_STOP_DEVICE:
2003 {
2004 Irp->IoStatus.Status = STATUS_SUCCESS;
2005 return ForwardIrpAndForget(DeviceObject, Irp);
2006 }
2007 case IRP_MN_REMOVE_DEVICE:
2008 {
2009 Irp->IoStatus.Status = STATUS_SUCCESS;
2010 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2011
2012 IoDetachDevice(HubDeviceExtension->LowerDeviceObject);
2013 IoDeleteDevice(DeviceObject);
2014
2015 return STATUS_SUCCESS;
2016 }
2017 case IRP_MN_QUERY_BUS_INFORMATION:
2018 {
2019 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
2020 break;
2021 }
2022 case IRP_MN_QUERY_ID:
2023 {
2024 DPRINT("IRP_MN_QUERY_ID\n");
2025 break;
2026 }
2027 case IRP_MN_QUERY_CAPABILITIES:
2028 {
2029 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
2030 break;
2031 }
2032 default:
2033 {
2034 DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction);
2035 return ForwardIrpAndForget(DeviceObject, Irp);
2036 }
2037 }
2038
2039 Irp->IoStatus.Information = Information;
2040 Irp->IoStatus.Status = Status;
2041 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2042 return Status;
2043 }
2044
2045 NTSTATUS
2046 USBHUB_FdoHandleDeviceControl(
2047 IN PDEVICE_OBJECT DeviceObject,
2048 IN PIRP Irp)
2049 {
2050 DPRINT1("FdoHandleDeviceControl\n");
2051 UNIMPLEMENTED
2052 return STATUS_NOT_IMPLEMENTED;
2053 }
2054