f0be1430fce722a34974c44c0131d7b9cf51743a
[reactos.git] / drivers / usb / usbehci_new / hcd_controller.cpp
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbehci/hcd_controller.cpp
5 * PURPOSE: USB EHCI device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #define INITGUID
12 #include "usbehci.h"
13
14 class CHCDController : public IHCDController
15 {
16 public:
17 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
18
19 STDMETHODIMP_(ULONG) AddRef()
20 {
21 InterlockedIncrement(&m_Ref);
22 return m_Ref;
23 }
24 STDMETHODIMP_(ULONG) Release()
25 {
26 InterlockedDecrement(&m_Ref);
27
28 if (!m_Ref)
29 {
30 delete this;
31 return 0;
32 }
33 return m_Ref;
34 }
35
36 // interface functions
37 NTSTATUS Initialize(IN PROOTHDCCONTROLLER RootHCDController, IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
38 NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
39 NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
40 NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
41
42 // local functions
43 NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
44 NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
45 NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack);
46 NTSTATUS SetDeviceInterface(BOOLEAN bEnable);
47
48 // constructor / destructor
49 CHCDController(IUnknown *OuterUnknown){}
50 virtual ~CHCDController(){}
51
52 protected:
53 LONG m_Ref;
54 PROOTHDCCONTROLLER m_RootController;
55 PDRIVER_OBJECT m_DriverObject;
56 PDEVICE_OBJECT m_PhysicalDeviceObject;
57 PDEVICE_OBJECT m_FunctionalDeviceObject;
58 PDEVICE_OBJECT m_NextDeviceObject;
59 PUSBHARDWAREDEVICE m_Hardware;
60 PDEVICE_OBJECT m_BusPDO;
61 UNICODE_STRING m_HubDeviceInterfaceString;
62 BOOLEAN m_InterfaceEnabled;
63 ULONG m_PDODeviceNumber;
64 ULONG m_FDODeviceNumber;
65 };
66
67 //=================================================================================================
68 // COM
69 //
70 NTSTATUS
71 STDMETHODCALLTYPE
72 CHCDController::QueryInterface(
73 IN REFIID refiid,
74 OUT PVOID* Output)
75 {
76 UNICODE_STRING GuidString;
77
78 if (IsEqualGUIDAligned(refiid, IID_IUnknown))
79 {
80 *Output = PVOID(PUNKNOWN(this));
81 PUNKNOWN(*Output)->AddRef();
82 return STATUS_SUCCESS;
83 }
84
85 return STATUS_UNSUCCESSFUL;
86 }
87
88 //-------------------------------------------------------------------------------------------------
89 NTSTATUS
90 CHCDController::Initialize(
91 IN PROOTHDCCONTROLLER RootHCDController,
92 IN PDRIVER_OBJECT DriverObject,
93 IN PDEVICE_OBJECT PhysicalDeviceObject)
94 {
95 NTSTATUS Status;
96 PCOMMON_DEVICE_EXTENSION DeviceExtension;
97
98 //
99 // create usb hardware
100 //
101 Status = CreateUSBHardware(&m_Hardware);
102 if (!NT_SUCCESS(Status))
103 {
104 //
105 // failed to create hardware object
106 //
107 DPRINT1("Failed to create hardware object\n");
108 return STATUS_INSUFFICIENT_RESOURCES;
109 }
110
111 //
112 // initialize members
113 //
114 m_DriverObject = DriverObject;
115 m_PhysicalDeviceObject = PhysicalDeviceObject;
116 m_RootController = RootHCDController;
117
118 //
119 // create FDO
120 //
121 Status = CreateFDO(m_DriverObject, &m_FunctionalDeviceObject);
122 if (!NT_SUCCESS(Status))
123 {
124 //
125 // failed to create PDO
126 //
127 return Status;
128 }
129
130 //
131 // now attach to device stack
132 //
133 m_NextDeviceObject = IoAttachDeviceToDeviceStack(m_FunctionalDeviceObject, m_PhysicalDeviceObject);
134 if (!m_NextDeviceObject)
135 {
136 //
137 // failed to attach to device stack
138 //
139 IoDeleteDevice(m_FunctionalDeviceObject);
140 m_FunctionalDeviceObject = 0;
141
142 return STATUS_NO_SUCH_DEVICE;
143 }
144
145 //
146 // initialize hardware object
147 //
148 Status = m_Hardware->Initialize(m_DriverObject, m_FunctionalDeviceObject, m_PhysicalDeviceObject, m_NextDeviceObject);
149 if (!NT_SUCCESS(Status))
150 {
151 DPRINT1("Failed to initialize hardware object %x\n", Status);
152
153 //
154 // failed to initialize hardware object, detach from device stack
155 //
156 IoDetachDevice(m_NextDeviceObject);
157
158 //
159 // now delete the device
160 //
161 IoDeleteDevice(m_FunctionalDeviceObject);
162
163 //
164 // nullify pointers :)
165 //
166 m_FunctionalDeviceObject = 0;
167 m_NextDeviceObject = 0;
168
169 return Status;
170 }
171
172
173 //
174 // set device flags
175 //
176 m_FunctionalDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
177
178
179 //
180 // get device extension
181 //
182 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_FunctionalDeviceObject->DeviceExtension;
183 PC_ASSERT(DeviceExtension);
184
185 //
186 // initialize device extension
187 //
188 DeviceExtension->IsFDO = TRUE;
189 DeviceExtension->IsHub = FALSE;
190 DeviceExtension->HcdController = PHCDCONTROLLER(this);
191
192 //
193 // device is initialized
194 //
195 m_FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
196
197
198 //
199 // is there a root controller
200 //
201 if (m_RootController)
202 {
203 //
204 // add reference
205 //
206 m_RootController->AddRef();
207
208 //
209 // register with controller
210 //
211 m_RootController->RegisterHCD(this);
212 }
213
214
215 //
216 // done
217 //
218 return STATUS_SUCCESS;
219 }
220
221 //-------------------------------------------------------------------------------------------------
222 NTSTATUS
223 CHCDController::HandleDeviceControl(
224 IN PDEVICE_OBJECT DeviceObject,
225 IN PIRP Irp)
226 {
227 PIO_STACK_LOCATION IoStack;
228 PCOMMON_DEVICE_EXTENSION DeviceExtension;
229 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
230 PUSB_HCD_DRIVERKEY_NAME DriverKey;
231 ULONG ResultLength;
232
233 //
234 // get current stack location
235 //
236 IoStack = IoGetCurrentIrpStackLocation(Irp);
237
238 //
239 // get device extension
240 //
241 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
242
243
244 DPRINT1("HandleDeviceControl>Type: FDO %u IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n",
245 DeviceExtension->IsFDO,
246 IoStack->Parameters.DeviceIoControl.IoControlCode,
247 IoStack->Parameters.DeviceIoControl.InputBufferLength,
248 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
249
250 //
251 // get device type
252 //
253 if (DeviceExtension->IsFDO)
254 {
255 //
256 // perform ioctl for FDO
257 //
258 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_HCD_DRIVERKEY_NAME)
259 {
260 //
261 // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
262 //
263 if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME))
264 {
265 //
266 // get device property size
267 //
268 Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, 0, NULL, &ResultLength);
269
270 DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer;
271
272 //
273 // check result
274 //
275 if (Status == STATUS_BUFFER_TOO_SMALL)
276 {
277 //
278 // does the caller provide enough buffer space
279 //
280 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= ResultLength)
281 {
282 //
283 // it does
284 //
285 Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength);
286
287 if (NT_SUCCESS(Status))
288 {
289 //
290 // informal debug print
291 //
292 DPRINT1("Result %S\n", DriverKey->DriverKeyName);
293 }
294 }
295
296 //
297 // store result
298 //
299 DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR);
300 Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
301 Status = STATUS_SUCCESS;
302 }
303 }
304 else
305 {
306 //
307 // buffer is certainly too small
308 //
309 Status = STATUS_BUFFER_OVERFLOW;
310 Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
311 }
312 }
313 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_ROOT_HUB_NAME)
314 {
315 DPRINT1("IOCTL_USB_GET_ROOT_HUB_NAME is not implemented yet\n");
316 }
317 }
318 else
319 {
320 //
321 // the PDO does not support any device IOCTLs
322 //
323 Status = STATUS_SUCCESS;
324 }
325
326 //
327 // complete the request
328 //
329 Irp->IoStatus.Status = Status;
330 IoCompleteRequest(Irp, IO_NO_INCREMENT);
331
332 //
333 // done
334 //
335 return Status;
336 }
337
338 NTSTATUS
339 CHCDController::HandlePnp(
340 IN PDEVICE_OBJECT DeviceObject,
341 IN PIRP Irp)
342 {
343 PIO_STACK_LOCATION IoStack;
344 PCOMMON_DEVICE_EXTENSION DeviceExtension;
345 PCM_RESOURCE_LIST RawResourceList;
346 PCM_RESOURCE_LIST TranslatedResourceList;
347 PDEVICE_RELATIONS DeviceRelations;
348 PDEVICE_CAPABILITIES DeviceCapabilities;
349 LPGUID Guid;
350 NTSTATUS Status;
351 ULONG Index;
352
353 DPRINT("HandlePnp\n");
354
355 //
356 // get device extension
357 //
358 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
359
360 //
361 // get current stack location
362 //
363 IoStack = IoGetCurrentIrpStackLocation(Irp);
364
365 switch(IoStack->MinorFunction)
366 {
367 case IRP_MN_START_DEVICE:
368 {
369 DPRINT1("IRP_MN_START FDO: %lu\n", DeviceExtension->IsFDO);
370
371 if (DeviceExtension->IsFDO)
372 {
373 //
374 // first start lower device object
375 //
376 Status = SyncForwardIrp(m_NextDeviceObject, Irp);
377
378 if (NT_SUCCESS(Status))
379 {
380 //
381 // operation succeeded, lets start the device
382 //
383 RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
384 TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
385
386 if (m_Hardware)
387 {
388 //
389 // start the hardware
390 //
391 Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList);
392 }
393 }
394
395 //
396 // HACK / FIXME: Windows XP SP3 fails to enumerate the PDO correctly, which
397 // causes the PDO device never to startup.
398 //
399 Status = SetDeviceInterface(TRUE);
400 }
401 else
402 {
403 //
404 // start the PDO device
405 //
406 ASSERT(0);
407
408 //
409 //FIXME create the parent root hub device
410 //
411
412 //
413 // register device interface
414 //
415 Status = SetDeviceInterface(TRUE);
416 }
417
418 DPRINT1("IRP_MN_START FDO: %lu Status %x\n", DeviceExtension->IsFDO, Status);
419
420 break;
421 }
422 case IRP_MN_QUERY_DEVICE_RELATIONS:
423 {
424 DPRINT1("IRP_MN_QUERY_DEVICE_RELATIONS Type %lx FDO: \n", IoStack->Parameters.QueryDeviceRelations.Type, DeviceExtension->IsFDO);
425
426 if (m_BusPDO == NULL)
427 {
428 //
429 // create bus PDO
430 //
431 Status = CreatePDO(m_DriverObject, &m_BusPDO);
432
433 if (!NT_SUCCESS(Status))
434 {
435 //
436 // failed to create bus device object
437 //
438 break;
439 }
440
441 //
442 // initialize extension
443 //
444 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_BusPDO->DeviceExtension;
445 DeviceExtension->IsFDO = FALSE;
446 DeviceExtension->IsHub = FALSE;
447 DeviceExtension->HcdController = (this);
448
449 //
450 // clear init flag
451 //
452 m_BusPDO->Flags &= ~DO_DEVICE_INITIALIZING;
453 }
454
455 if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
456 {
457 //
458 // allocate device relations
459 //
460 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
461
462 if (!DeviceRelations)
463 {
464 //
465 // no memory
466 //
467 Status = STATUS_INSUFFICIENT_RESOURCES;
468 break;
469 }
470
471 //
472 // init device relations
473 //
474 DeviceRelations->Count = 1;
475 DeviceRelations->Objects [0] = m_BusPDO;
476
477 ObReferenceObject(m_BusPDO);
478
479 //
480 // store result
481 //
482 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
483 Status = STATUS_SUCCESS;
484 }
485 break;
486 }
487
488 case IRP_MN_STOP_DEVICE:
489 {
490 DPRINT1("IRP_MN_STOP_DEVICE FDO: %lu\n", DeviceExtension->IsFDO);
491
492 if (m_Hardware)
493 {
494 //
495 // stop the hardware
496 //
497 Status = m_Hardware->PnpStop();
498 }
499 else
500 {
501 //
502 // fake success
503 //
504 Status = STATUS_SUCCESS;
505 }
506
507 if (NT_SUCCESS(Status))
508 {
509 //
510 // stop lower device
511 //
512 Status = SyncForwardIrp(m_NextDeviceObject, Irp);
513 }
514 break;
515 }
516 case IRP_MN_QUERY_CAPABILITIES:
517 {
518 DPRINT1("IRP_MN_QUERY_CAPABILITIES FDO: %lu\n", DeviceExtension->IsFDO);
519
520 if (DeviceExtension->IsFDO == FALSE)
521 {
522 DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
523
524 DeviceCapabilities->LockSupported = FALSE;
525 DeviceCapabilities->EjectSupported = FALSE;
526 DeviceCapabilities->Removable = FALSE;
527 DeviceCapabilities->DockDevice = FALSE;
528 DeviceCapabilities->UniqueID = FALSE;
529 DeviceCapabilities->SilentInstall = FALSE;
530 DeviceCapabilities->RawDeviceOK = FALSE;
531 DeviceCapabilities->SurpriseRemovalOK = FALSE;
532 DeviceCapabilities->Address = 0;
533 DeviceCapabilities->UINumber = 0;
534 DeviceCapabilities->DeviceD2 = 1;
535
536 /* FIXME */
537 DeviceCapabilities->HardwareDisabled = FALSE;
538 DeviceCapabilities->NoDisplayInUI = FALSE;
539 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
540 for (Index = 0; Index < PowerSystemMaximum; Index++)
541 DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
542 DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
543 DeviceCapabilities->D1Latency = 0;
544 DeviceCapabilities->D2Latency = 0;
545 DeviceCapabilities->D3Latency = 0;
546
547 Status = STATUS_SUCCESS;
548 }
549 else
550 {
551 //
552 // forward irp to next device object
553 //
554 IoSkipCurrentIrpStackLocation(Irp);
555 return IoCallDriver(m_NextDeviceObject, Irp);
556 }
557
558 break;
559 }
560 case IRP_MN_QUERY_INTERFACE:
561 {
562 DPRINT1("IRP_MN_QUERY_INTERFACE FDO %u\n", DeviceExtension->IsFDO);
563 //
564 // check if the device is FDO
565 //
566 if (DeviceExtension->IsFDO)
567 {
568 //
569 // just pass the irp to next device object
570 //
571 IoSkipCurrentIrpStackLocation(Irp);
572 return IoCallDriver(m_NextDeviceObject, Irp);
573 }
574
575 //
576 // handle device interface requests
577 //
578 Status = HandleQueryInterface(IoStack);
579 break;
580 }
581 case IRP_MN_QUERY_BUS_INFORMATION:
582 {
583 DPRINT1("IRP_MN_QUERY_BUS_INFORMATION FDO %lx\n", DeviceExtension->IsFDO);
584
585 if (DeviceExtension->IsFDO == FALSE)
586 {
587 //
588 // allocate buffer for bus guid
589 //
590 Guid = (LPGUID)ExAllocatePool(PagedPool, sizeof(GUID));
591 if (Guid)
592 {
593 //
594 // copy BUS guid
595 //
596 RtlMoveMemory(Guid, &GUID_BUS_TYPE_USB, sizeof(GUID));
597 Status = STATUS_SUCCESS;
598 Irp->IoStatus.Information = (ULONG_PTR)Guid;
599 }
600 }
601 break;
602 }
603 case IRP_MN_REMOVE_DEVICE:
604 {
605 DPRINT1("IRP_MN_REMOVE_DEVICE FDO: %lu\n", DeviceExtension->IsFDO);
606
607 if (DeviceExtension->IsFDO == FALSE)
608 {
609 //
610 // deactivate device interface for BUS PDO
611 //
612 SetDeviceInterface(FALSE);
613
614 //
615 // complete the request first
616 //
617 Irp->IoStatus.Status = STATUS_SUCCESS;
618 IoCompleteRequest(Irp, IO_NO_INCREMENT);
619
620 //
621 // now delete device
622 //
623 IoDeleteDevice(m_BusPDO);
624
625 //
626 // nullify pointer
627 //
628 m_BusPDO = 0;
629 return STATUS_SUCCESS;
630 }
631 else
632 {
633 //
634 // detach device from device stack
635 //
636 IoDetachDevice(m_NextDeviceObject);
637
638 //
639 // delete device
640 //
641 IoDeleteDevice(m_FunctionalDeviceObject);
642 }
643
644 Status = STATUS_SUCCESS;
645 break;
646 }
647 default:
648 {
649 if (DeviceExtension->IsFDO)
650 {
651 DPRINT1("HandlePnp> FDO Dispatch to lower device object %lu\n", IoStack->MinorFunction);
652
653 //
654 // forward irp to next device object
655 //
656 IoSkipCurrentIrpStackLocation(Irp);
657 return IoCallDriver(m_NextDeviceObject, Irp);
658 }
659 else
660 {
661 DPRINT1("UNHANDLED PDO Request %lu\n", IoStack->MinorFunction);
662 }
663 }
664 }
665
666 //
667 // store result and complete request
668 //
669 Irp->IoStatus.Status = Status;
670 IoCompleteRequest(Irp, IO_NO_INCREMENT);
671
672 return Status;
673 }
674
675 NTSTATUS
676 CHCDController::HandlePower(
677 IN PDEVICE_OBJECT DeviceObject,
678 IN PIRP Irp)
679 {
680 UNIMPLEMENTED
681
682 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
683 IoCompleteRequest(Irp, IO_NO_INCREMENT);
684
685 return STATUS_NOT_IMPLEMENTED;
686 }
687
688 NTSTATUS
689 CHCDController::HandleQueryInterface(
690 PIO_STACK_LOCATION IoStack)
691 {
692 UNICODE_STRING GuidBuffer;
693 NTSTATUS Status;
694
695 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
696 {
697 DPRINT1("HandleQueryInterface> UNIMPLEMENTED USB_BUS_INTERFACE_HUB_GUID Version %x\n", IoStack->Parameters.QueryInterface.Version);
698
699 }
700 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
701 {
702 DPRINT1("HandleQueryInterface> UNIMPLEMENTED USB_BUS_INTERFACE_USBDI_GUID Version %x\n", IoStack->Parameters.QueryInterface.Version);
703 }
704 else
705 {
706 //
707 // convert guid to string
708 //
709 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
710 if (NT_SUCCESS(Status))
711 {
712 //
713 // print interface
714 //
715 DPRINT1("HandleQueryInterface GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
716
717 //
718 // free guid buffer
719 //
720 RtlFreeUnicodeString(&GuidBuffer);
721 }
722 }
723 return STATUS_NOT_SUPPORTED;
724 }
725
726 NTSTATUS
727 CHCDController::CreateFDO(
728 PDRIVER_OBJECT DriverObject,
729 PDEVICE_OBJECT * OutDeviceObject)
730 {
731 WCHAR CharDeviceName[64];
732 NTSTATUS Status;
733 ULONG UsbDeviceNumber = 0;
734 UNICODE_STRING DeviceName;
735
736 while (TRUE)
737 {
738 //
739 // construct device name
740 //
741 swprintf(CharDeviceName, L"\\Device\\USBFDO-%d", UsbDeviceNumber);
742
743 //
744 // initialize device name
745 //
746 RtlInitUnicodeString(&DeviceName, CharDeviceName);
747
748 //
749 // create device
750 //
751 Status = IoCreateDevice(DriverObject,
752 sizeof(COMMON_DEVICE_EXTENSION),
753 &DeviceName,
754 FILE_DEVICE_CONTROLLER,
755 0,
756 FALSE,
757 OutDeviceObject);
758
759 //
760 // check for success
761 //
762 if (NT_SUCCESS(Status))
763 break;
764
765 //
766 // is there a device object with that same name
767 //
768 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
769 {
770 //
771 // Try the next name
772 //
773 UsbDeviceNumber++;
774 continue;
775 }
776
777 //
778 // bail out on other errors
779 //
780 if (!NT_SUCCESS(Status))
781 {
782 DPRINT1("CreateFDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
783 return Status;
784 }
785 }
786
787 //
788 // store FDO number
789 //
790 m_FDODeviceNumber = UsbDeviceNumber;
791
792 DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
793
794 /* done */
795 return Status;
796 }
797
798 NTSTATUS
799 CHCDController::SetDeviceInterface(
800 BOOLEAN Enable)
801 {
802 NTSTATUS Status;
803 WCHAR LinkName[32];
804 WCHAR FDOName[32];
805 UNICODE_STRING Link, FDO;
806
807 if (Enable)
808 {
809 //
810 // register device interface
811 //
812 Status = IoRegisterDeviceInterface(m_PhysicalDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
813
814 if (NT_SUCCESS(Status))
815 {
816 //
817 // now enable the device interface
818 //
819 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
820
821 //
822 // enable interface
823 //
824 m_InterfaceEnabled = TRUE;
825 }
826
827 //
828 // create legacy link
829 //
830 swprintf(LinkName, L"\\DosDevices\\HCD%d", m_PDODeviceNumber);
831 swprintf(FDOName, L"\\Device\\USBFDO-%d", m_FDODeviceNumber);
832 RtlInitUnicodeString(&Link, LinkName);
833 RtlInitUnicodeString(&FDO, FDOName);
834
835 //
836 // create symbolic link
837 //
838 Status = IoCreateSymbolicLink(&Link, &FDO);
839
840 if (!NT_SUCCESS(Status))
841 {
842 //
843 // FIXME: handle me
844 //
845 ASSERT(0);
846 }
847 }
848 else if (m_InterfaceEnabled)
849 {
850 //
851 // disable device interface
852 //
853 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
854
855 if (NT_SUCCESS(Status))
856 {
857 //
858 // now delete interface string
859 //
860 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
861 }
862
863 //
864 // disable interface
865 //
866 m_InterfaceEnabled = FALSE;
867
868 }
869
870 //
871 // done
872 //
873 return Status;
874 }
875
876 NTSTATUS
877 CHCDController::CreatePDO(
878 PDRIVER_OBJECT DriverObject,
879 PDEVICE_OBJECT * OutDeviceObject)
880 {
881 WCHAR CharDeviceName[64];
882 NTSTATUS Status;
883 ULONG UsbDeviceNumber = 0;
884 UNICODE_STRING DeviceName;
885
886 while (TRUE)
887 {
888 //
889 // construct device name
890 //
891 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
892
893 //
894 // initialize device name
895 //
896 RtlInitUnicodeString(&DeviceName, CharDeviceName);
897
898 //
899 // create device
900 //
901 Status = IoCreateDevice(DriverObject,
902 sizeof(COMMON_DEVICE_EXTENSION),
903 &DeviceName,
904 FILE_DEVICE_CONTROLLER,
905 0,
906 FALSE,
907 OutDeviceObject);
908
909 /* check for success */
910 if (NT_SUCCESS(Status))
911 break;
912
913 //
914 // is there a device object with that same name
915 //
916 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
917 {
918 //
919 // Try the next name
920 //
921 UsbDeviceNumber++;
922 continue;
923 }
924
925 //
926 // bail out on other errors
927 //
928 if (!NT_SUCCESS(Status))
929 {
930 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
931 return Status;
932 }
933 }
934
935 //
936 // store PDO number
937 //
938 m_PDODeviceNumber = UsbDeviceNumber;
939
940 DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
941
942 /* done */
943 return Status;
944 }
945
946 NTSTATUS
947 CreateHCDController(
948 PHCDCONTROLLER *OutHcdController)
949 {
950 PHCDCONTROLLER This;
951
952 //
953 // allocate controller
954 //
955 This = new(NonPagedPool, TAG_USBEHCI) CHCDController(0);
956 if (!This)
957 {
958 //
959 // failed to allocate
960 //
961 return STATUS_INSUFFICIENT_RESOURCES;
962 }
963
964 //
965 // add reference count
966 //
967 This->AddRef();
968
969 //
970 // return result
971 //
972 *OutHcdController = (PHCDCONTROLLER)This;
973
974 //
975 // done
976 //
977 return STATUS_SUCCESS;
978 }