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