[USBHUB]
[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 ULONG
808 IsCompositeDevice(
809 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
810 {
811 if (DeviceDescriptor->bDeviceClass == 0)
812 {
813 //
814 // composite device
815 //
816 return TRUE;
817 }
818
819 if (DeviceDescriptor->bDeviceClass == 0xEF &&
820 DeviceDescriptor->bDeviceSubClass == 0x02 &&
821 DeviceDescriptor->bDeviceProtocol == 0x01)
822 {
823 //
824 // USB-IF association descriptor
825 //
826 return TRUE;
827 }
828
829 //
830 // not a composite device
831 //
832 return FALSE;
833 }
834
835 NTSTATUS
836 CreateDeviceIds(
837 PDEVICE_OBJECT UsbChildDeviceObject)
838 {
839 NTSTATUS Status = STATUS_SUCCESS;
840 ULONG Index;
841 PWCHAR BufferPtr;
842 WCHAR Buffer[100];
843 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
844 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
845
846 //
847 // get child device extension
848 //
849 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
850
851 //
852 // Initialize the CompatibleIds String
853 //
854 UsbChildExtension->usCompatibleIds.Length = 144; //FIXME
855 UsbChildExtension->usCompatibleIds.MaximumLength = UsbChildExtension->usCompatibleIds.Length;
856
857 //
858 // allocate mem for compatible id string
859 //
860 BufferPtr = ExAllocatePoolWithTag(NonPagedPool,
861 UsbChildExtension->usCompatibleIds.Length,
862 USB_HUB_TAG);
863 if (!BufferPtr)
864 {
865 DPRINT1("Failed to allocate memory\n");
866 return STATUS_INSUFFICIENT_RESOURCES;
867 }
868
869 RtlZeroMemory(BufferPtr, UsbChildExtension->usCompatibleIds.Length);
870 Index = 0;
871
872 //
873 // get device descriptor
874 //
875 DeviceDescriptor = &UsbChildExtension->DeviceDesc;
876
877 //
878 // Construct the CompatibleIds
879 //
880 if (IsCompositeDevice(DeviceDescriptor))
881 {
882 Index += swprintf(&BufferPtr[Index],
883 L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
884 DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1;
885 Index += swprintf(&BufferPtr[Index],
886 L"USB\\DevClass_%02x&SubClass_%02x",
887 DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1;
888 Index += swprintf(&BufferPtr[Index],
889 L"USB\\DevClass_%02x",
890 DeviceDescriptor->bDeviceClass) + 1;
891 Index += swprintf(&BufferPtr[Index],
892 L"USB\\COMPOSITE") + 1;
893 }
894 else
895 {
896 Index += swprintf(&BufferPtr[Index],
897 L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
898 DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1;
899 Index += swprintf(&BufferPtr[Index],
900 L"USB\\Class_%02x&SubClass_%02x",
901 DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1;
902 Index += swprintf(&BufferPtr[Index],
903 L"USB\\Class_%02x",
904 DeviceDescriptor->bDeviceClass) + 1;
905 }
906
907 BufferPtr[Index] = UNICODE_NULL;
908 UsbChildExtension->usCompatibleIds.Buffer = BufferPtr;
909 DPRINT1("usCompatibleIds %wZ\n", &UsbChildExtension->usCompatibleIds);
910
911 //
912 // Initialize the DeviceId String
913 //
914 UsbChildExtension->usDeviceId.Length = 44;
915 UsbChildExtension->usDeviceId.MaximumLength = UsbChildExtension->usDeviceId.Length;
916 BufferPtr = ExAllocatePoolWithTag(NonPagedPool,
917 UsbChildExtension->usDeviceId.Length,
918 USB_HUB_TAG);
919 if (!BufferPtr)
920 {
921 DPRINT1("Failed to allocate memory\n");
922 Status = STATUS_INSUFFICIENT_RESOURCES;
923 goto Cleanup;
924 }
925
926 //
927 // Construct DeviceId
928 //
929 swprintf(BufferPtr, L"USB\\Vid_%04x&Pid_%04x\0", UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct);
930 UsbChildExtension->usDeviceId.Buffer = BufferPtr;
931 DPRINT1("usDeviceId %wZ\n", &UsbChildExtension->usDeviceId);
932
933 //
934 // Initialize the HardwareId String
935 //
936 UsbChildExtension->usHardwareIds.Length = 110;
937 UsbChildExtension->usHardwareIds.MaximumLength = UsbChildExtension->usHardwareIds.Length;
938 BufferPtr = ExAllocatePoolWithTag(NonPagedPool, UsbChildExtension->usHardwareIds.Length, USB_HUB_TAG);
939 if (!BufferPtr)
940 {
941 DPRINT1("Failed to allocate memory\n");
942 Status = STATUS_INSUFFICIENT_RESOURCES;
943 goto Cleanup;
944 }
945
946 RtlZeroMemory(BufferPtr, UsbChildExtension->usHardwareIds.Length);
947
948 //
949 // Consturct HardwareIds
950 //
951 Index = 0;
952 Index += swprintf(&BufferPtr[Index],
953 L"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
954 UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct, UsbChildExtension->DeviceDesc.bcdDevice) + 1;
955 Index += swprintf(&BufferPtr[Index],
956 L"USB\\Vid_%04x&Pid_%04x",
957 UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1;
958 BufferPtr[Index] = UNICODE_NULL;
959 UsbChildExtension->usHardwareIds.Buffer = BufferPtr;
960 DPRINT1("usHardWareIds %wZ\n", &UsbChildExtension->usHardwareIds);
961
962 //
963 // FIXME: Handle Lang ids
964 //
965
966 //
967 // Get the product string if obe provided
968 //
969 if (UsbChildExtension->DeviceDesc.iProduct)
970 {
971 Status = GetUsbStringDescriptor(UsbChildDeviceObject,
972 UsbChildExtension->DeviceDesc.iProduct,
973 0,
974 (PVOID*)&UsbChildExtension->usTextDescription.Buffer,
975 &UsbChildExtension->usTextDescription.Length);
976 if (!NT_SUCCESS(Status))
977 {
978 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status);
979 goto Cleanup;
980 }
981
982 UsbChildExtension->usTextDescription.MaximumLength = UsbChildExtension->usTextDescription.Length;
983 DPRINT1("Usb TextDescription %wZ\n", &UsbChildExtension->usTextDescription);
984 }
985
986 //
987 // Get the Serial Number string if obe provided
988 //
989 if (UsbChildExtension->DeviceDesc.iSerialNumber)
990 {
991 Status = GetUsbStringDescriptor(UsbChildDeviceObject,
992 UsbChildExtension->DeviceDesc.iSerialNumber,
993 0,
994 (PVOID*)&UsbChildExtension->usInstanceId.Buffer,
995 &UsbChildExtension->usInstanceId.Length);
996 if (!NT_SUCCESS(Status))
997 {
998 DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status);
999 goto Cleanup;
1000 }
1001
1002 UsbChildExtension->usInstanceId.MaximumLength = UsbChildExtension->usInstanceId.Length;
1003 DPRINT1("Usb InstanceId %wZ\n", &UsbChildExtension->usInstanceId);
1004 }
1005 else
1006 {
1007 //
1008 // the device did not provide a serial number, lets create a pseudo instance id
1009 //
1010 Index = swprintf(Buffer, L"0&%04d", UsbChildExtension->PortNumber) + 1;
1011 UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
1012 if (UsbChildExtension->usInstanceId.Buffer == NULL)
1013 {
1014 DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
1015 Status = STATUS_INSUFFICIENT_RESOURCES;
1016 goto Cleanup;
1017 }
1018
1019 //
1020 // copy instance id
1021 //
1022 RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
1023 UsbChildExtension->usInstanceId.Length = UsbChildExtension->usDeviceId.MaximumLength = Index * sizeof(WCHAR);
1024
1025 DPRINT1("usDeviceId %wZ\n", &UsbChildExtension->usInstanceId);
1026 }
1027
1028
1029 return Status;
1030
1031 Cleanup:
1032 //
1033 // Free Memory
1034 //
1035 if (UsbChildExtension->usCompatibleIds.Buffer)
1036 ExFreePool(UsbChildExtension->usCompatibleIds.Buffer);
1037 if (UsbChildExtension->usDeviceId.Buffer)
1038 ExFreePool(UsbChildExtension->usDeviceId.Buffer);
1039 if (UsbChildExtension->usHardwareIds.Buffer)
1040 ExFreePool(UsbChildExtension->usHardwareIds.Buffer);
1041 if (UsbChildExtension->usTextDescription.Buffer)
1042 ExFreePool(UsbChildExtension->usTextDescription.Buffer);
1043 if (UsbChildExtension->usInstanceId.Buffer)
1044 ExFreePool(UsbChildExtension->usInstanceId.Buffer);
1045
1046 return Status;
1047 }
1048
1049 NTSTATUS
1050 DestroyUsbChildDeviceObject(
1051 IN PDEVICE_OBJECT UsbHubDeviceObject,
1052 IN LONG PortId)
1053 {
1054 PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbHubDeviceObject->DeviceExtension;
1055 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = NULL;
1056 PDEVICE_OBJECT ChildDeviceObject = NULL;
1057 ULONG Index = 0;
1058
1059 DPRINT1("Removing device on port %d (Child index: %d)\n", PortId, Index);
1060
1061 for (Index = 0; Index < USB_MAXCHILDREN; Index++)
1062 {
1063 if (HubDeviceExtension->ChildDeviceObject[Index])
1064 {
1065 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension;
1066
1067 /* Check if it matches the port ID */
1068 if (UsbChildExtension->PortNumber == PortId)
1069 {
1070 /* We found it */
1071 ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[Index];
1072 break;
1073 }
1074 }
1075 }
1076
1077 /* Fail the request if the device doesn't exist */
1078 if (!ChildDeviceObject)
1079 {
1080 DPRINT1("Removal request for non-existant device!\n");
1081 return STATUS_UNSUCCESSFUL;
1082 }
1083
1084 /* Remove the device from the table */
1085 HubDeviceExtension->ChildDeviceObject[Index] = NULL;
1086
1087 /* Invalidate device relations for the root hub */
1088 IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations);
1089
1090 /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
1091 return STATUS_SUCCESS;
1092 }
1093
1094 NTSTATUS
1095 CreateUsbChildDeviceObject(
1096 IN PDEVICE_OBJECT UsbHubDeviceObject,
1097 IN LONG PortId,
1098 OUT PDEVICE_OBJECT *UsbChildDeviceObject)
1099 {
1100 NTSTATUS Status;
1101 PDEVICE_OBJECT RootHubDeviceObject, NewChildDeviceObject;
1102 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1103 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
1104 PUSB_BUS_INTERFACE_HUB_V5 HubInterface;
1105 ULONG ChildDeviceCount, UsbDeviceNumber = 0;
1106 WCHAR CharDeviceName[64];
1107 UNICODE_STRING DeviceName;
1108 ULONG ConfigDescSize, DeviceDescSize;
1109 PVOID HubInterfaceBusContext;
1110 USB_CONFIGURATION_DESCRIPTOR ConfigDesc;
1111
1112 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbHubDeviceObject->DeviceExtension;
1113 HubInterface = &HubDeviceExtension->HubInterface;
1114 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
1115 HubInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext;
1116 //
1117 // Find an empty slot in the child device array
1118 //
1119 for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++)
1120 {
1121 if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL)
1122 {
1123 DPRINT1("Found unused entry at %d\n", ChildDeviceCount);
1124 break;
1125 }
1126 }
1127
1128 //
1129 // Check if the limit has been reached for maximum usb devices
1130 //
1131 if (ChildDeviceCount == USB_MAXCHILDREN)
1132 {
1133 DPRINT1("USBHUB: Too many child devices!\n");
1134 return STATUS_UNSUCCESSFUL;
1135 }
1136
1137 while (TRUE)
1138 {
1139 //
1140 // Create a Device Name
1141 //
1142 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
1143
1144 //
1145 // Initialize UnicodeString
1146 //
1147 RtlInitUnicodeString(&DeviceName, CharDeviceName);
1148
1149 //
1150 // Create a DeviceObject
1151 //
1152 Status = IoCreateDevice(UsbHubDeviceObject->DriverObject,
1153 sizeof(HUB_CHILDDEVICE_EXTENSION),
1154 NULL,
1155 FILE_DEVICE_CONTROLLER,
1156 FILE_AUTOGENERATED_DEVICE_NAME,
1157 FALSE,
1158 &NewChildDeviceObject);
1159
1160 //
1161 // Check if the name is already in use
1162 //
1163 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
1164 {
1165 //
1166 // Try next name
1167 //
1168 UsbDeviceNumber++;
1169 continue;
1170 }
1171
1172 //
1173 // Check for other errors
1174 //
1175 if (!NT_SUCCESS(Status))
1176 {
1177 DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status);
1178 return Status;
1179 }
1180
1181 DPRINT1("USBHUB: Created Device %x\n", NewChildDeviceObject);
1182 break;
1183 }
1184
1185 NewChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
1186
1187 //
1188 // Assign the device extensions
1189 //
1190 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)NewChildDeviceObject->DeviceExtension;
1191 RtlZeroMemory(UsbChildExtension, sizeof(HUB_CHILDDEVICE_EXTENSION));
1192 UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject;
1193 UsbChildExtension->PortNumber = PortId;
1194
1195 //
1196 // Create the UsbDeviceObject
1197 //
1198 Status = HubInterface->CreateUsbDevice(HubInterfaceBusContext,
1199 (PVOID)&UsbChildExtension->UsbDeviceHandle,
1200 HubDeviceExtension->RootHubHandle,
1201 0x501, //hack
1202 PortId);
1203 if (!NT_SUCCESS(Status))
1204 {
1205 DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status);
1206 goto Cleanup;
1207 }
1208
1209 //
1210 // Initialize UsbDevice
1211 //
1212 Status = HubInterface->InitializeUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle);
1213 if (!NT_SUCCESS(Status))
1214 {
1215 DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status);
1216 goto Cleanup;
1217 }
1218
1219 DPRINT1("Usb Device Handle %x\n", UsbChildExtension->UsbDeviceHandle);
1220
1221 ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
1222 DeviceDescSize = sizeof(USB_DEVICE_DESCRIPTOR);
1223
1224 //
1225 // Get the descriptors
1226 //
1227 Status = HubInterface->GetUsbDescriptors(HubInterfaceBusContext,
1228 UsbChildExtension->UsbDeviceHandle,
1229 (PUCHAR)&UsbChildExtension->DeviceDesc,
1230 &DeviceDescSize,
1231 (PUCHAR)&ConfigDesc,
1232 &ConfigDescSize);
1233 if (!NT_SUCCESS(Status))
1234 {
1235 DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status);
1236 goto Cleanup;
1237 }
1238
1239 DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc);
1240 DumpConfigurationDescriptor(&ConfigDesc);
1241
1242 //
1243 // FIXME: Support more than one configuration and one interface?
1244 //
1245 if (UsbChildExtension->DeviceDesc.bNumConfigurations > 1)
1246 {
1247 DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
1248 }
1249
1250 if (ConfigDesc.bNumInterfaces > 1)
1251 {
1252 DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
1253 }
1254
1255 ConfigDescSize = ConfigDesc.wTotalLength;
1256
1257 //
1258 // Allocate memory for the first full descriptor, including interfaces and endpoints.
1259 //
1260 UsbChildExtension->FullConfigDesc = ExAllocatePoolWithTag(PagedPool, ConfigDescSize, USB_HUB_TAG);
1261
1262 //
1263 // Retrieve the full configuration descriptor
1264 //
1265 Status = GetUsbDeviceDescriptor(NewChildDeviceObject,
1266 USB_CONFIGURATION_DESCRIPTOR_TYPE,
1267 0,
1268 0,
1269 UsbChildExtension->FullConfigDesc,
1270 ConfigDescSize);
1271
1272 if (!NT_SUCCESS(Status))
1273 {
1274 DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status);
1275 goto Cleanup;
1276 }
1277
1278 DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
1279
1280 //
1281 // Construct all the strings that will described the device to PNP
1282 //
1283 Status = CreateDeviceIds(NewChildDeviceObject);
1284 if (!NT_SUCCESS(Status))
1285 {
1286 DPRINT1("Failed to create strings needed to describe device to PNP.\n");
1287 goto Cleanup;
1288 }
1289
1290 HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject;
1291
1292 IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations);
1293 return STATUS_SUCCESS;
1294
1295 Cleanup:
1296
1297 //
1298 // Remove the usb device if it was created
1299 //
1300 if (UsbChildExtension->UsbDeviceHandle)
1301 HubInterface->RemoveUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle, 0);
1302
1303 //
1304 // Free full configuration descriptor if one was allocated
1305 //
1306 if (UsbChildExtension->FullConfigDesc)
1307 ExFreePool(UsbChildExtension->FullConfigDesc);
1308
1309 //
1310 // Delete the device object
1311 //
1312 IoDeleteDevice(NewChildDeviceObject);
1313 return Status;
1314 }
1315
1316 NTSTATUS
1317 USBHUB_FdoQueryBusRelations(
1318 IN PDEVICE_OBJECT DeviceObject,
1319 OUT PDEVICE_RELATIONS* pDeviceRelations)
1320 {
1321 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1322 PDEVICE_RELATIONS DeviceRelations;
1323 ULONG i;
1324 ULONG Children = 0;
1325 ULONG NeededSize;
1326
1327 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1328
1329 //
1330 // Count the number of children
1331 //
1332 for (i = 0; i < USB_MAXCHILDREN; i++)
1333 {
1334
1335 if (HubDeviceExtension->ChildDeviceObject[i] == NULL)
1336 {
1337 continue;
1338 }
1339 Children++;
1340 }
1341
1342 NeededSize = sizeof(DEVICE_RELATIONS);
1343 if (Children > 1)
1344 NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT);
1345
1346 //
1347 // Allocate DeviceRelations
1348 //
1349 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool,
1350 NeededSize);
1351
1352 if (!DeviceRelations)
1353 return STATUS_INSUFFICIENT_RESOURCES;
1354 DeviceRelations->Count = Children;
1355 Children = 0;
1356
1357 //
1358 // Fill in return structure
1359 //
1360 for (i = 0; i < USB_MAXCHILDREN; i++)
1361 {
1362 if (HubDeviceExtension->ChildDeviceObject[i])
1363 {
1364 ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]);
1365 HubDeviceExtension->ChildDeviceObject[i]->Flags &= ~DO_DEVICE_INITIALIZING;
1366 DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i];
1367 }
1368 }
1369
1370 ASSERT(Children == DeviceRelations->Count);
1371 *pDeviceRelations = DeviceRelations;
1372
1373 return STATUS_SUCCESS;
1374 }
1375
1376 VOID
1377 NTAPI
1378 RootHubInitCallbackFunction(
1379 PVOID Context)
1380 {
1381 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
1382
1383 DPRINT1("Sending the initial SCE Request %x\n", DeviceObject);
1384
1385 //
1386 // Send the first SCE Request
1387 //
1388 QueryStatusChangeEndpoint(DeviceObject);
1389 }
1390
1391 NTSTATUS
1392 USBHUB_FdoHandlePnp(
1393 IN PDEVICE_OBJECT DeviceObject,
1394 IN PIRP Irp)
1395 {
1396 PIO_STACK_LOCATION Stack;
1397 NTSTATUS Status = STATUS_SUCCESS;
1398 ULONG_PTR Information = 0;
1399 PHUB_DEVICE_EXTENSION HubDeviceExtension;
1400 PDEVICE_OBJECT RootHubDeviceObject;
1401 PVOID HubInterfaceBusContext , UsbDInterfaceBusContext;
1402
1403 HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
1404
1405 Stack = IoGetCurrentIrpStackLocation(Irp);
1406
1407 switch (Stack->MinorFunction)
1408 {
1409 case IRP_MN_START_DEVICE:
1410 {
1411 PURB Urb;
1412 PUSB_INTERFACE_DESCRIPTOR Pid;
1413 ULONG Result = 0, PortId;
1414 USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
1415 PURB ConfigUrb = NULL;
1416 ULONG HubStatus;
1417
1418 DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1419
1420 //
1421 // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
1422 //
1423 Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG);
1424 RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY));
1425
1426 //
1427 // Get the Root Hub Pdo
1428 //
1429 SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
1430 IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
1431 &HubDeviceExtension->RootHubPhysicalDeviceObject,
1432 &HubDeviceExtension->RootHubFunctionalDeviceObject);
1433
1434 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
1435 ASSERT(HubDeviceExtension->RootHubPhysicalDeviceObject);
1436 ASSERT(HubDeviceExtension->RootHubFunctionalDeviceObject);
1437 DPRINT1("RootPdo %x, RootFdo %x\n",
1438 HubDeviceExtension->RootHubPhysicalDeviceObject,
1439 HubDeviceExtension->RootHubFunctionalDeviceObject);
1440
1441 //
1442 // Send the StartDevice to RootHub
1443 //
1444 Status = ForwardIrpAndWait(RootHubDeviceObject, Irp);
1445
1446 if (!NT_SUCCESS(Status))
1447 {
1448 DPRINT1("Failed to start the RootHub PDO\n");
1449 ASSERT(FALSE);
1450 }
1451
1452 //
1453 // Get the current number of hubs
1454 //
1455 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1456 IOCTL_INTERNAL_USB_GET_HUB_COUNT,
1457 &HubDeviceExtension->NumberOfHubs, NULL);
1458
1459 //
1460 // Get the Hub Interface
1461 //
1462 Status = QueryInterface(RootHubDeviceObject,
1463 USB_BUS_INTERFACE_HUB_GUID,
1464 sizeof(USB_BUS_INTERFACE_HUB_V5),
1465 5,
1466 (PVOID)&HubDeviceExtension->HubInterface);
1467
1468 if (!NT_SUCCESS(Status))
1469 {
1470 DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
1471 return STATUS_UNSUCCESSFUL;
1472 }
1473
1474 HubInterfaceBusContext = HubDeviceExtension->HubInterface.BusContext;
1475
1476 //
1477 // Get the USBDI Interface
1478 //
1479 Status = QueryInterface(RootHubDeviceObject,
1480 USB_BUS_INTERFACE_USBDI_GUID,
1481 sizeof(USB_BUS_INTERFACE_USBDI_V2),
1482 2,
1483 (PVOID)&HubDeviceExtension->UsbDInterface);
1484
1485 if (!NT_SUCCESS(Status))
1486 {
1487 DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status);
1488 return Status;
1489 }
1490
1491 UsbDInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext;
1492
1493 //
1494 // Get Root Hub Device Handle
1495 //
1496 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1497 IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
1498 &HubDeviceExtension->RootHubHandle,
1499 NULL);
1500
1501 if (!NT_SUCCESS(Status))
1502 {
1503 DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status);
1504 return Status;
1505 }
1506
1507 //
1508 // Get Hub Device Information
1509 //
1510 Status = HubDeviceExtension->HubInterface.QueryDeviceInformation(HubInterfaceBusContext,
1511 HubDeviceExtension->RootHubHandle,
1512 &HubDeviceExtension->DeviceInformation,
1513 sizeof(USB_DEVICE_INFORMATION_0),
1514 &Result);
1515
1516 DPRINT1("Status %x, Result 0x%08lx\n", Status, Result);
1517 DPRINT1("InformationLevel %x\n", HubDeviceExtension->DeviceInformation.InformationLevel);
1518 DPRINT1("ActualLength %x\n", HubDeviceExtension->DeviceInformation.ActualLength);
1519 DPRINT1("PortNumber %x\n", HubDeviceExtension->DeviceInformation.PortNumber);
1520 DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension->DeviceInformation.DeviceDescriptor);
1521 DPRINT1("HubAddress %x\n", HubDeviceExtension->DeviceInformation.HubAddress);
1522 DPRINT1("NumberofPipes %x\n", HubDeviceExtension->DeviceInformation.NumberOfOpenPipes);
1523
1524 //
1525 // Get Root Hubs Device Descriptor
1526 //
1527 UsbBuildGetDescriptorRequest(Urb,
1528 sizeof(Urb->UrbControlDescriptorRequest),
1529 USB_DEVICE_DESCRIPTOR_TYPE,
1530 0,
1531 0,
1532 &HubDeviceExtension->HubDeviceDescriptor,
1533 NULL,
1534 sizeof(USB_DEVICE_DESCRIPTOR),
1535 NULL);
1536
1537 Urb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle;
1538
1539 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1540 IOCTL_INTERNAL_USB_SUBMIT_URB,
1541 Urb,
1542 NULL);
1543
1544 if (!NT_SUCCESS(Status))
1545 {
1546 DPRINT1("Failed to get HubDeviceDescriptor!\n");
1547 }
1548
1549 DumpDeviceDescriptor(&HubDeviceExtension->HubDeviceDescriptor);
1550
1551 //
1552 // Get Root Hubs Configuration Descriptor
1553 //
1554 UsbBuildGetDescriptorRequest(Urb,
1555 sizeof(Urb->UrbControlDescriptorRequest),
1556 USB_CONFIGURATION_DESCRIPTOR_TYPE,
1557 0,
1558 0,
1559 &HubDeviceExtension->HubConfigDescriptor,
1560 NULL,
1561 sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
1562 NULL);
1563
1564 DPRINT1("RootHub Handle %x\n", HubDeviceExtension->RootHubHandle);
1565 Urb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle;
1566
1567 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1568 IOCTL_INTERNAL_USB_SUBMIT_URB,
1569 Urb,
1570 NULL);
1571
1572 if (!NT_SUCCESS(Status))
1573 {
1574 DPRINT1("Failed to get RootHub Configuration with status %x\n", Status);
1575 ASSERT(FALSE);
1576 }
1577 ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength);
1578
1579 DumpConfigurationDescriptor(&HubDeviceExtension->HubConfigDescriptor);
1580
1581 Status = HubDeviceExtension->HubInterface.GetExtendedHubInformation(HubInterfaceBusContext,
1582 RootHubDeviceObject,
1583 &HubDeviceExtension->UsbExtHubInfo,
1584 sizeof(USB_EXTHUB_INFORMATION_0),
1585 &Result);
1586 if (!NT_SUCCESS(Status))
1587 {
1588 DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
1589 ASSERT(FALSE);
1590 }
1591
1592 DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
1593
1594 //
1595 // Get the Hub Descriptor
1596 //
1597 UsbBuildVendorRequest(Urb,
1598 URB_FUNCTION_CLASS_DEVICE,
1599 sizeof(Urb->UrbControlVendorClassRequest),
1600 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
1601 0,
1602 USB_REQUEST_GET_DESCRIPTOR,
1603 USB_DEVICE_CLASS_RESERVED,
1604 0,
1605 &HubDeviceExtension->HubDescriptor,
1606 NULL,
1607 sizeof(USB_HUB_DESCRIPTOR),
1608 NULL);
1609
1610 Urb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle;
1611
1612 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1613 IOCTL_INTERNAL_USB_SUBMIT_URB,
1614 Urb,
1615 NULL);
1616
1617 DPRINT1("bDescriptorType %x\n", HubDeviceExtension->HubDescriptor.bDescriptorType);
1618
1619 if (!NT_SUCCESS(Status))
1620 {
1621 DPRINT1("Failed to get Hub Descriptor!\n");
1622 ExFreePool(Urb);
1623 return STATUS_UNSUCCESSFUL;
1624 }
1625
1626 HubStatus = 0;
1627 UsbBuildGetStatusRequest(Urb,
1628 URB_FUNCTION_GET_STATUS_FROM_DEVICE,
1629 0,
1630 &HubStatus,
1631 0,
1632 NULL);
1633 Urb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle;
1634
1635 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1636 IOCTL_INTERNAL_USB_SUBMIT_URB,
1637 Urb,
1638 NULL);
1639 if (!NT_SUCCESS(Status))
1640 {
1641 DPRINT1("Failed to get Hub Status!\n");
1642 ExFreePool(Urb);
1643 return STATUS_UNSUCCESSFUL;
1644 }
1645
1646 DPRINT1("HubStatus %x\n", HubStatus);
1647
1648 //
1649 // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
1650 //
1651 HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool,
1652 sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
1653 USB_HUB_TAG);
1654
1655 //
1656 // Get the first Configuration Descriptor
1657 //
1658 Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor,
1659 &HubDeviceExtension->HubConfigDescriptor,
1660 -1, -1, -1, -1, -1);
1661
1662 ASSERT(Pid != NULL);
1663
1664 InterfaceList[0].InterfaceDescriptor = Pid;
1665 ConfigUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor,
1666 (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
1667 ASSERT(ConfigUrb != NULL);
1668
1669 Status = SubmitRequestToRootHub(RootHubDeviceObject,
1670 IOCTL_INTERNAL_USB_SUBMIT_URB,
1671 ConfigUrb,
1672 NULL);
1673
1674 HubDeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle;
1675 HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
1676 DPRINT1("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle);
1677
1678 //
1679 // check if function is available
1680 //
1681 if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed)
1682 {
1683 //
1684 // is it high speed bus
1685 //
1686 if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed(HubInterfaceBusContext))
1687 {
1688 //
1689 // initialize usb 2.0 hub
1690 //
1691 Status = HubDeviceExtension->HubInterface.Initialize20Hub(HubInterfaceBusContext,
1692 HubDeviceExtension->RootHubHandle, 1);
1693 DPRINT1("Status %x\n", Status);
1694
1695 //
1696 // FIXME handle error
1697 //
1698 ASSERT(Status == STATUS_SUCCESS);
1699 }
1700 }
1701
1702 ExFreePool(ConfigUrb);
1703
1704 //
1705 // Enable power on all ports
1706 //
1707
1708 DPRINT1("Enabling PortPower on all ports!\n");
1709
1710 for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
1711 {
1712 Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_POWER);
1713 if (!NT_SUCCESS(Status))
1714 DPRINT1("Failed to power on port %d\n", PortId);
1715
1716 Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION);
1717 if (!NT_SUCCESS(Status))
1718 DPRINT1("Failed to power on port %d\n", PortId);
1719 }
1720
1721 DPRINT1("RootHubInitNotification %x\n", HubDeviceExtension->HubInterface.RootHubInitNotification);
1722
1723 //
1724 // init roo hub notification
1725 //
1726 if (HubDeviceExtension->HubInterface.RootHubInitNotification)
1727 {
1728 Status = HubDeviceExtension->HubInterface.RootHubInitNotification(HubInterfaceBusContext,
1729 DeviceObject,
1730 RootHubInitCallbackFunction);
1731 if (!NT_SUCCESS(Status))
1732 {
1733 DPRINT1("Failed to set callback\n");
1734 }
1735 }
1736 else
1737 {
1738 //
1739 // Send the first SCE Request
1740 //
1741 QueryStatusChangeEndpoint(DeviceObject);
1742 }
1743
1744 ExFreePool(Urb);
1745 break;
1746 }
1747
1748 case IRP_MN_QUERY_DEVICE_RELATIONS:
1749 {
1750 switch (Stack->Parameters.QueryDeviceRelations.Type)
1751 {
1752 case BusRelations:
1753 {
1754 PDEVICE_RELATIONS DeviceRelations = NULL;
1755 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
1756
1757 Status = USBHUB_FdoQueryBusRelations(DeviceObject, &DeviceRelations);
1758
1759 Information = (ULONG_PTR)DeviceRelations;
1760 break;
1761 }
1762 case RemovalRelations:
1763 {
1764 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
1765 return ForwardIrpAndForget(DeviceObject, Irp);
1766 }
1767 default:
1768 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
1769 Stack->Parameters.QueryDeviceRelations.Type);
1770 return ForwardIrpAndForget(DeviceObject, Irp);
1771 }
1772 break;
1773 }
1774 case IRP_MN_QUERY_BUS_INFORMATION:
1775 {
1776 DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n");
1777 break;
1778 }
1779 case IRP_MN_QUERY_ID:
1780 {
1781 DPRINT1("IRP_MN_QUERY_ID\n");
1782 break;
1783 }
1784 case IRP_MN_QUERY_CAPABILITIES:
1785 {
1786 DPRINT1("IRP_MN_QUERY_CAPABILITIES\n");
1787 break;
1788 }
1789 default:
1790 {
1791 DPRINT1(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction);
1792 return ForwardIrpAndForget(DeviceObject, Irp);
1793 }
1794 }
1795
1796 Irp->IoStatus.Information = Information;
1797 Irp->IoStatus.Status = Status;
1798 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1799 return Status;
1800 }
1801
1802 NTSTATUS
1803 USBHUB_FdoHandleDeviceControl(
1804 IN PDEVICE_OBJECT DeviceObject,
1805 IN PIRP Irp)
1806 {
1807 DPRINT1("FdoHandleDeviceControl\n");
1808 UNIMPLEMENTED
1809 return STATUS_NOT_IMPLEMENTED;
1810 }
1811