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