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