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