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