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