[USBEHCI_NEW]
[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 NOT IMPLEMENTED\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, DriverKey->DriverKeyName, &ResultLength);
286
287 //DPRINT1("Result %S\n", DriverKey->DriverKeyName);
288 }
289
290 //
291 // FIXME
292 //
293
294 //
295 // store result
296 //
297 DriverKey->ActualLength = ResultLength;
298 Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
299 Status = STATUS_BUFFER_OVERFLOW;
300 }
301 }
302 else
303 {
304 //
305 // buffer is certainly too small
306 //
307 Status = STATUS_BUFFER_OVERFLOW;
308 Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
309 }
310 }
311 }
312
313 //
314
315 Irp->IoStatus.Status = Status;
316 IoCompleteRequest(Irp, IO_NO_INCREMENT);
317
318 return Status;
319 }
320
321 NTSTATUS
322 CHCDController::HandlePnp(
323 IN PDEVICE_OBJECT DeviceObject,
324 IN PIRP Irp)
325 {
326 PIO_STACK_LOCATION IoStack;
327 PCOMMON_DEVICE_EXTENSION DeviceExtension;
328 PCM_RESOURCE_LIST RawResourceList;
329 PCM_RESOURCE_LIST TranslatedResourceList;
330 PDEVICE_RELATIONS DeviceRelations;
331 PDEVICE_CAPABILITIES DeviceCapabilities;
332 LPGUID Guid;
333 NTSTATUS Status;
334 ULONG Index;
335
336 DPRINT("HandlePnp\n");
337
338 //
339 // get device extension
340 //
341 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
342
343 //
344 // get current stack location
345 //
346 IoStack = IoGetCurrentIrpStackLocation(Irp);
347
348 switch(IoStack->MinorFunction)
349 {
350 case IRP_MN_START_DEVICE:
351 {
352 DPRINT1("IRP_MN_START FDO: %lu\n", DeviceExtension->IsFDO);
353
354 if (DeviceExtension->IsFDO)
355 {
356 //
357 // first start lower device object
358 //
359 Status = SyncForwardIrp(m_NextDeviceObject, Irp);
360
361 if (NT_SUCCESS(Status))
362 {
363 //
364 // operation succeeded, lets start the device
365 //
366 RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
367 TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
368
369 if (m_Hardware)
370 {
371 //
372 // start the hardware
373 //
374 Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList);
375 }
376 }
377
378 //
379 // HACK / FIXME: Windows XP SP3 fails to enumerate the PDO correctly, which
380 // causes the PDO device never to startup.
381 //
382 Status = SetDeviceInterface(TRUE);
383 }
384 else
385 {
386 //
387 // start the PDO device
388 //
389 ASSERT(0);
390
391 //
392 //FIXME create the parent root hub device
393 //
394
395 //
396 // register device interface
397 //
398 Status = SetDeviceInterface(TRUE);
399 }
400
401 DPRINT1("IRP_MN_START FDO: %lu Status %x\n", DeviceExtension->IsFDO, Status);
402
403 break;
404 }
405 case IRP_MN_QUERY_DEVICE_RELATIONS:
406 {
407 DPRINT1("IRP_MN_QUERY_DEVICE_RELATIONS Type %lx FDO: \n", IoStack->Parameters.QueryDeviceRelations.Type, DeviceExtension->IsFDO);
408
409 if (m_BusPDO == NULL)
410 {
411 //
412 // create bus PDO
413 //
414 Status = CreatePDO(m_DriverObject, &m_BusPDO);
415
416 if (!NT_SUCCESS(Status))
417 {
418 //
419 // failed to create bus device object
420 //
421 break;
422 }
423
424 //
425 // initialize extension
426 //
427 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_BusPDO->DeviceExtension;
428 DeviceExtension->IsFDO = FALSE;
429 DeviceExtension->IsHub = FALSE;
430 DeviceExtension->HcdController = (this);
431
432 //
433 // clear init flag
434 //
435 m_BusPDO->Flags &= ~DO_DEVICE_INITIALIZING;
436 }
437
438 if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
439 {
440 //
441 // allocate device relations
442 //
443 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
444
445 if (!DeviceRelations)
446 {
447 //
448 // no memory
449 //
450 Status = STATUS_INSUFFICIENT_RESOURCES;
451 break;
452 }
453
454 //
455 // init device relations
456 //
457 DeviceRelations->Count = 1;
458 DeviceRelations->Objects [0] = m_BusPDO;
459
460 ObReferenceObject(m_BusPDO);
461
462 //
463 // store result
464 //
465 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
466 Status = STATUS_SUCCESS;
467 }
468 break;
469 }
470
471 case IRP_MN_STOP_DEVICE:
472 {
473 DPRINT1("IRP_MN_STOP_DEVICE FDO: %lu\n", DeviceExtension->IsFDO);
474
475 if (m_Hardware)
476 {
477 //
478 // stop the hardware
479 //
480 Status = m_Hardware->PnpStop();
481 }
482 else
483 {
484 //
485 // fake success
486 //
487 Status = STATUS_SUCCESS;
488 }
489
490 if (NT_SUCCESS(Status))
491 {
492 //
493 // stop lower device
494 //
495 Status = SyncForwardIrp(m_NextDeviceObject, Irp);
496 }
497 break;
498 }
499 case IRP_MN_QUERY_CAPABILITIES:
500 {
501 DPRINT1("IRP_MN_QUERY_CAPABILITIES FDO: %lu\n", DeviceExtension->IsFDO);
502
503 if (DeviceExtension->IsFDO == FALSE)
504 {
505 DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
506
507 DeviceCapabilities->LockSupported = FALSE;
508 DeviceCapabilities->EjectSupported = FALSE;
509 DeviceCapabilities->Removable = FALSE;
510 DeviceCapabilities->DockDevice = FALSE;
511 DeviceCapabilities->UniqueID = FALSE;
512 DeviceCapabilities->SilentInstall = FALSE;
513 DeviceCapabilities->RawDeviceOK = FALSE;
514 DeviceCapabilities->SurpriseRemovalOK = FALSE;
515 DeviceCapabilities->Address = 0;
516 DeviceCapabilities->UINumber = 0;
517 DeviceCapabilities->DeviceD2 = 1;
518
519 /* FIXME */
520 DeviceCapabilities->HardwareDisabled = FALSE;
521 DeviceCapabilities->NoDisplayInUI = FALSE;
522 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
523 for (Index = 0; Index < PowerSystemMaximum; Index++)
524 DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
525 DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
526 DeviceCapabilities->D1Latency = 0;
527 DeviceCapabilities->D2Latency = 0;
528 DeviceCapabilities->D3Latency = 0;
529
530 Status = STATUS_SUCCESS;
531 }
532 else
533 {
534 //
535 // forward irp to next device object
536 //
537 IoSkipCurrentIrpStackLocation(Irp);
538 return IoCallDriver(m_NextDeviceObject, Irp);
539 }
540
541 break;
542 }
543 case IRP_MN_QUERY_INTERFACE:
544 {
545 DPRINT1("IRP_MN_QUERY_INTERFACE FDO %u\n", DeviceExtension->IsFDO);
546 //
547 // check if the device is FDO
548 //
549 if (DeviceExtension->IsFDO)
550 {
551 //
552 // just pass the irp to next device object
553 //
554 IoSkipCurrentIrpStackLocation(Irp);
555 return IoCallDriver(m_NextDeviceObject, Irp);
556 }
557
558 //
559 // handle device interface requests
560 //
561 Status = HandleQueryInterface(IoStack);
562 break;
563 }
564 case IRP_MN_QUERY_BUS_INFORMATION:
565 {
566 DPRINT1("IRP_MN_QUERY_BUS_INFORMATION FDO %lx\n", DeviceExtension->IsFDO);
567
568 if (DeviceExtension->IsFDO == FALSE)
569 {
570 //
571 // allocate buffer for bus guid
572 //
573 Guid = (LPGUID)ExAllocatePool(PagedPool, sizeof(GUID));
574 if (Guid)
575 {
576 //
577 // copy BUS guid
578 //
579 RtlMoveMemory(Guid, &GUID_BUS_TYPE_USB, sizeof(GUID));
580 Status = STATUS_SUCCESS;
581 Irp->IoStatus.Information = (ULONG_PTR)Guid;
582 }
583 }
584 break;
585 }
586 case IRP_MN_REMOVE_DEVICE:
587 {
588 DPRINT1("IRP_MN_REMOVE_DEVICE FDO: %lu\n", DeviceExtension->IsFDO);
589
590 if (DeviceExtension->IsFDO == FALSE)
591 {
592 //
593 // deactivate device interface for BUS PDO
594 //
595 SetDeviceInterface(FALSE);
596
597 //
598 // complete the request first
599 //
600 Irp->IoStatus.Status = STATUS_SUCCESS;
601 IoCompleteRequest(Irp, IO_NO_INCREMENT);
602
603 //
604 // now delete device
605 //
606 IoDeleteDevice(m_BusPDO);
607
608 //
609 // nullify pointer
610 //
611 m_BusPDO = 0;
612 return STATUS_SUCCESS;
613 }
614 else
615 {
616 //
617 // detach device from device stack
618 //
619 IoDetachDevice(m_NextDeviceObject);
620
621 //
622 // delete device
623 //
624 IoDeleteDevice(m_FunctionalDeviceObject);
625 }
626
627 Status = STATUS_SUCCESS;
628 break;
629 }
630 default:
631 {
632 if (DeviceExtension->IsFDO)
633 {
634 DPRINT1("HandlePnp> FDO Dispatch to lower device object %lu\n", IoStack->MinorFunction);
635
636 //
637 // forward irp to next device object
638 //
639 IoSkipCurrentIrpStackLocation(Irp);
640 return IoCallDriver(m_NextDeviceObject, Irp);
641 }
642 else
643 {
644 DPRINT1("UNHANDLED PDO Request %lu\n", IoStack->MinorFunction);
645 }
646 }
647 }
648
649 //
650 // store result and complete request
651 //
652 Irp->IoStatus.Status = Status;
653 IoCompleteRequest(Irp, IO_NO_INCREMENT);
654
655 return Status;
656 }
657
658 NTSTATUS
659 CHCDController::HandlePower(
660 IN PDEVICE_OBJECT DeviceObject,
661 IN PIRP Irp)
662 {
663 UNIMPLEMENTED
664
665 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
666 IoCompleteRequest(Irp, IO_NO_INCREMENT);
667
668 return STATUS_NOT_IMPLEMENTED;
669 }
670
671 NTSTATUS
672 CHCDController::HandleQueryInterface(
673 PIO_STACK_LOCATION IoStack)
674 {
675 UNICODE_STRING GuidBuffer;
676 NTSTATUS Status;
677
678 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
679 {
680 DPRINT1("HandleQueryInterface> UNIMPLEMENTED USB_BUS_INTERFACE_HUB_GUID Version %x\n", IoStack->Parameters.QueryInterface.Version);
681
682 }
683 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
684 {
685 DPRINT1("HandleQueryInterface> UNIMPLEMENTED USB_BUS_INTERFACE_USBDI_GUID Version %x\n", IoStack->Parameters.QueryInterface.Version);
686 }
687 else
688 {
689 //
690 // convert guid to string
691 //
692 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
693 if (NT_SUCCESS(Status))
694 {
695 //
696 // print interface
697 //
698 DPRINT1("HandleQueryInterface GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
699
700 //
701 // free guid buffer
702 //
703 RtlFreeUnicodeString(&GuidBuffer);
704 }
705 }
706 return STATUS_NOT_SUPPORTED;
707 }
708
709 NTSTATUS
710 CHCDController::CreateFDO(
711 PDRIVER_OBJECT DriverObject,
712 PDEVICE_OBJECT * OutDeviceObject)
713 {
714 WCHAR CharDeviceName[64];
715 NTSTATUS Status;
716 ULONG UsbDeviceNumber = 0;
717 UNICODE_STRING DeviceName;
718
719 while (TRUE)
720 {
721 //
722 // construct device name
723 //
724 swprintf(CharDeviceName, L"\\Device\\USBFDO-%d", UsbDeviceNumber);
725
726 //
727 // initialize device name
728 //
729 RtlInitUnicodeString(&DeviceName, CharDeviceName);
730
731 //
732 // create device
733 //
734 Status = IoCreateDevice(DriverObject,
735 sizeof(COMMON_DEVICE_EXTENSION),
736 &DeviceName,
737 FILE_DEVICE_CONTROLLER,
738 0,
739 FALSE,
740 OutDeviceObject);
741
742 //
743 // check for success
744 //
745 if (NT_SUCCESS(Status))
746 break;
747
748 //
749 // is there a device object with that same name
750 //
751 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
752 {
753 //
754 // Try the next name
755 //
756 UsbDeviceNumber++;
757 continue;
758 }
759
760 //
761 // bail out on other errors
762 //
763 if (!NT_SUCCESS(Status))
764 {
765 DPRINT1("CreateFDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
766 return Status;
767 }
768 }
769
770 //
771 // store FDO number
772 //
773 m_FDODeviceNumber = UsbDeviceNumber;
774
775 DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
776
777 /* done */
778 return Status;
779 }
780
781 NTSTATUS
782 CHCDController::SetDeviceInterface(
783 BOOLEAN Enable)
784 {
785 NTSTATUS Status;
786 WCHAR LinkName[32];
787 WCHAR FDOName[32];
788 UNICODE_STRING Link, FDO;
789
790 if (Enable)
791 {
792 //
793 // register device interface
794 //
795 Status = IoRegisterDeviceInterface(m_PhysicalDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
796
797 if (NT_SUCCESS(Status))
798 {
799 //
800 // now enable the device interface
801 //
802 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
803
804 //
805 // enable interface
806 //
807 m_InterfaceEnabled = TRUE;
808 }
809
810 //
811 // create legacy link
812 //
813 swprintf(LinkName, L"\\DosDevices\\HCD%d", m_PDODeviceNumber);
814 swprintf(FDOName, L"\\Device\\USBFDO-%d", m_FDODeviceNumber);
815 RtlInitUnicodeString(&Link, LinkName);
816 RtlInitUnicodeString(&FDO, FDOName);
817
818 //
819 // create symbolic link
820 //
821 Status = IoCreateSymbolicLink(&Link, &FDO);
822
823 if (!NT_SUCCESS(Status))
824 {
825 //
826 // FIXME: handle me
827 //
828 ASSERT(0);
829 }
830 }
831 else if (m_InterfaceEnabled)
832 {
833 //
834 // disable device interface
835 //
836 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
837
838 if (NT_SUCCESS(Status))
839 {
840 //
841 // now delete interface string
842 //
843 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
844 }
845
846 //
847 // disable interface
848 //
849 m_InterfaceEnabled = FALSE;
850
851 }
852
853 //
854 // done
855 //
856 return Status;
857 }
858
859 NTSTATUS
860 CHCDController::CreatePDO(
861 PDRIVER_OBJECT DriverObject,
862 PDEVICE_OBJECT * OutDeviceObject)
863 {
864 WCHAR CharDeviceName[64];
865 NTSTATUS Status;
866 ULONG UsbDeviceNumber = 0;
867 UNICODE_STRING DeviceName;
868
869 while (TRUE)
870 {
871 //
872 // construct device name
873 //
874 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
875
876 //
877 // initialize device name
878 //
879 RtlInitUnicodeString(&DeviceName, CharDeviceName);
880
881 //
882 // create device
883 //
884 Status = IoCreateDevice(DriverObject,
885 sizeof(COMMON_DEVICE_EXTENSION),
886 &DeviceName,
887 FILE_DEVICE_CONTROLLER,
888 0,
889 FALSE,
890 OutDeviceObject);
891
892 /* check for success */
893 if (NT_SUCCESS(Status))
894 break;
895
896 //
897 // is there a device object with that same name
898 //
899 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
900 {
901 //
902 // Try the next name
903 //
904 UsbDeviceNumber++;
905 continue;
906 }
907
908 //
909 // bail out on other errors
910 //
911 if (!NT_SUCCESS(Status))
912 {
913 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
914 return Status;
915 }
916 }
917
918 //
919 // store PDO number
920 //
921 m_PDODeviceNumber = UsbDeviceNumber;
922
923 DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
924
925 /* done */
926 return Status;
927 }
928
929 NTSTATUS
930 CreateHCDController(
931 PHCDCONTROLLER *OutHcdController)
932 {
933 PHCDCONTROLLER This;
934
935 //
936 // allocate controller
937 //
938 This = new(NonPagedPool, 0) CHCDController(0);
939 if (!This)
940 {
941 //
942 // failed to allocate
943 //
944 return STATUS_INSUFFICIENT_RESOURCES;
945 }
946
947 //
948 // add reference count
949 //
950 This->AddRef();
951
952 //
953 // return result
954 //
955 *OutHcdController = (PHCDCONTROLLER)This;
956
957 //
958 // done
959 //
960 return STATUS_SUCCESS;
961 }