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