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