[USBEHCI_NEW]
[reactos.git] / drivers / usb / usbehci_new / hub_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/hub_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 CHubController : public IHubController,
15 public IDispatchIrp
16 {
17 public:
18 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
19
20 STDMETHODIMP_(ULONG) AddRef()
21 {
22 InterlockedIncrement(&m_Ref);
23 return m_Ref;
24 }
25 STDMETHODIMP_(ULONG) Release()
26 {
27 InterlockedDecrement(&m_Ref);
28
29 if (!m_Ref)
30 {
31 delete this;
32 return 0;
33 }
34 return m_Ref;
35 }
36
37 // IHubController interface functions
38 virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject, IN PHCDCONTROLLER Controller, IN PUSBHARDWAREDEVICE Device, IN BOOLEAN IsRootHubDevice, IN ULONG DeviceAddress);
39
40 // IDispatchIrp interface functions
41 virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
42 virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
43 virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
44
45 // local functions
46 NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack);
47 NTSTATUS SetDeviceInterface(BOOLEAN bEnable);
48 NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
49 NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject);
50
51 // constructor / destructor
52 CHubController(IUnknown *OuterUnknown){}
53 virtual ~CHubController(){}
54
55 protected:
56 LONG m_Ref;
57 PHCDCONTROLLER m_Controller;
58 PUSBHARDWAREDEVICE m_Hardware;
59 BOOLEAN m_IsRootHubDevice;
60 ULONG m_DeviceAddress;
61 ULONG m_PDODeviceNumber;
62 BOOLEAN m_InterfaceEnabled;
63 UNICODE_STRING m_HubDeviceInterfaceString;
64 PDEVICE_OBJECT m_HubControllerDeviceObject;
65 PDRIVER_OBJECT m_DriverObject;
66 };
67
68 //----------------------------------------------------------------------------------------
69 NTSTATUS
70 STDMETHODCALLTYPE
71 CHubController::QueryInterface(
72 IN REFIID refiid,
73 OUT PVOID* Output)
74 {
75 return STATUS_UNSUCCESSFUL;
76 }
77 //----------------------------------------------------------------------------------------
78 NTSTATUS
79 CHubController::Initialize(
80 IN PDRIVER_OBJECT DriverObject,
81 IN PHCDCONTROLLER Controller,
82 IN PUSBHARDWAREDEVICE Device,
83 IN BOOLEAN IsRootHubDevice,
84 IN ULONG DeviceAddress)
85 {
86 NTSTATUS Status;
87 PCOMMON_DEVICE_EXTENSION DeviceExtension;
88
89 DPRINT1("CHubController::Initialize\n");
90
91 //
92 // initialize members
93 //
94 m_Controller = Controller;
95 m_Hardware = Device;
96 m_IsRootHubDevice = IsRootHubDevice;
97 m_DeviceAddress = DeviceAddress;
98 m_DriverObject = DriverObject;
99
100 //
101 // create PDO
102 //
103 Status = CreatePDO(m_DriverObject, &m_HubControllerDeviceObject);
104 if (!NT_SUCCESS(Status))
105 {
106 //
107 // failed to create hub device object
108 //
109 return Status;
110 }
111
112 //
113 // get device extension
114 //
115 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_HubControllerDeviceObject->DeviceExtension;
116
117 //
118 // initialize device extension
119 //
120 DeviceExtension->IsFDO = FALSE;
121 DeviceExtension->IsHub = TRUE; //FIXME
122 DeviceExtension->Dispatcher = PDISPATCHIRP(this);
123
124 //
125 // clear init flag
126 //
127 m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
128
129
130 return STATUS_SUCCESS;
131 }
132
133 //-----------------------------------------------------------------------------------------
134 NTSTATUS
135 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject)
136 {
137 //
138 // store controller object
139 //
140 *HubDeviceObject = m_HubControllerDeviceObject;
141
142 return STATUS_SUCCESS;
143 }
144 //-----------------------------------------------------------------------------------------
145 NTSTATUS
146 CHubController::HandlePnp(
147 IN PDEVICE_OBJECT DeviceObject,
148 IN OUT PIRP Irp)
149 {
150 PIO_STACK_LOCATION IoStack;
151 PCOMMON_DEVICE_EXTENSION DeviceExtension;
152 PDEVICE_CAPABILITIES DeviceCapabilities;
153 PPNP_BUS_INFORMATION BusInformation;
154 NTSTATUS Status;
155 ULONG Index = 0, Length;
156 USHORT VendorID, DeviceID;
157 ULONG HiSpeed, NumPorts;
158 WCHAR Buffer[300];
159 LPWSTR DeviceName;
160
161 //
162 // get device extension
163 //
164 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
165
166 //
167 // sanity check
168 //
169 ASSERT(DeviceExtension->IsFDO == FALSE);
170
171 //
172 // get current stack location
173 //
174 IoStack = IoGetCurrentIrpStackLocation(Irp);
175
176 switch(IoStack->MinorFunction)
177 {
178 case IRP_MN_START_DEVICE:
179 {
180 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
181 //
182 // register device interface
183 //
184 Status = SetDeviceInterface(TRUE);
185 break;
186 }
187 case IRP_MN_QUERY_ID:
188 {
189 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack->Parameters.QueryId.IdType);
190
191 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
192 {
193 if (m_Hardware)
194 {
195 //
196 // query device id
197 //
198 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
199
200 HiSpeed = TRUE;
201
202 if (HiSpeed)
203 {
204 //
205 // USB 2.0 hub
206 //
207 swprintf(Buffer, L"USB\\ROOT_HUB20");
208 }
209 else
210 {
211 //
212 // USB 1.1 hub
213 //
214 swprintf(Buffer, L"USB\\ROOT_HUB");
215 }
216
217 DPRINT1("Name %S\n", Buffer);
218
219 //
220 // calculate length
221 //
222 Length = (wcslen(Buffer) + 1);
223
224 //
225 // allocate buffer
226 //
227 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_USBEHCI);
228
229 if (!DeviceName)
230 {
231 //
232 // no memory
233 //
234 Status = STATUS_INSUFFICIENT_RESOURCES;
235 break;
236 }
237
238 //
239 // copy device name
240 //
241 wcscpy(DeviceName, Buffer);
242
243 //
244 // store result
245 //
246 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
247 Status = STATUS_SUCCESS;
248 break;
249 }
250 Status = STATUS_UNSUCCESSFUL;
251 PC_ASSERT(0);
252 break;
253 }
254
255 if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
256 {
257 if (m_Hardware)
258 {
259 //
260 // query device id
261 //
262 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
263
264 HiSpeed = TRUE;
265
266 if (!NT_SUCCESS(Status))
267 {
268 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status);
269 VendorID = 0x8086;
270 DeviceID = 0x3A37;
271 }
272
273 if (HiSpeed)
274 {
275 //
276 // USB 2.0 hub
277 //
278 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
279 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID, DeviceID) + 1;
280 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
281 }
282 else
283 {
284 //
285 // USB 1.1 hub
286 //
287 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
288 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID, DeviceID) + 1;
289 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB") + 1;
290 }
291
292 Buffer[Index] = UNICODE_NULL;
293 Index++;
294
295
296 DPRINT1("Name %S\n", Buffer);
297
298 //
299 // allocate buffer
300 //
301 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Index * sizeof(WCHAR), TAG_USBEHCI);
302
303 if (!DeviceName)
304 {
305 //
306 // no memory
307 //
308 Status = STATUS_INSUFFICIENT_RESOURCES;
309 break;
310 }
311
312 //
313 // copy device name
314 //
315 RtlMoveMemory(DeviceName, Buffer, Index * sizeof(WCHAR));
316
317 //
318 // store result
319 //
320 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
321 Status = STATUS_SUCCESS;
322 break;
323 }
324 }
325 Status = STATUS_SUCCESS;
326 break;
327 }
328 case IRP_MN_QUERY_CAPABILITIES:
329 {
330 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
331
332 DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
333
334 DeviceCapabilities->LockSupported = FALSE;
335 DeviceCapabilities->EjectSupported = FALSE;
336 DeviceCapabilities->Removable = FALSE;
337 DeviceCapabilities->DockDevice = FALSE;
338 DeviceCapabilities->UniqueID = FALSE;
339 DeviceCapabilities->SilentInstall = FALSE;
340 DeviceCapabilities->RawDeviceOK = FALSE;
341 DeviceCapabilities->SurpriseRemovalOK = FALSE;
342 DeviceCapabilities->Address = 0;
343 DeviceCapabilities->UINumber = 0;
344 DeviceCapabilities->DeviceD2 = 1;
345
346 /* FIXME */
347 DeviceCapabilities->HardwareDisabled = FALSE;
348 DeviceCapabilities->NoDisplayInUI = FALSE;
349 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
350 for (Index = 0; Index < PowerSystemMaximum; Index++)
351 DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
352 DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
353 DeviceCapabilities->D1Latency = 0;
354 DeviceCapabilities->D2Latency = 0;
355 DeviceCapabilities->D3Latency = 0;
356
357 Status = STATUS_SUCCESS;
358 break;
359 }
360 case IRP_MN_QUERY_INTERFACE:
361 {
362 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
363
364 //
365 // handle device interface requests
366 //
367 Status = HandleQueryInterface(IoStack);
368 break;
369 }
370 case IRP_MN_REMOVE_DEVICE:
371 {
372 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
373
374 //
375 // deactivate device interface for BUS PDO
376 //
377 SetDeviceInterface(FALSE);
378
379 //
380 // complete the request first
381 //
382 Irp->IoStatus.Status = STATUS_SUCCESS;
383 IoCompleteRequest(Irp, IO_NO_INCREMENT);
384
385 //
386 // now delete device
387 //
388 IoDeleteDevice(m_HubControllerDeviceObject);
389
390 //
391 // nullify pointer
392 //
393 m_HubControllerDeviceObject = 0;
394
395 //
396 // done
397 //
398 return STATUS_SUCCESS;
399 }
400 case IRP_MN_QUERY_BUS_INFORMATION:
401 {
402 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
403
404 //
405 // allocate buffer for bus information
406 //
407 BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
408 if (BusInformation)
409 {
410 //
411 // copy BUS guid
412 //
413 RtlMoveMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_USB, sizeof(GUID));
414
415 //
416 // set bus type
417 //
418 BusInformation->LegacyBusType = PNPBus;
419 BusInformation->BusNumber = 0;
420
421 Status = STATUS_SUCCESS;
422 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
423 }
424 else
425 {
426 //
427 // no memory
428 //
429 Status = STATUS_INSUFFICIENT_RESOURCES;
430 }
431 break;
432 }
433 case IRP_MN_STOP_DEVICE:
434 {
435 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
436 //
437 // stop device
438 //
439 Status = STATUS_SUCCESS;
440 break;
441 }
442 default:
443 {
444 DPRINT1("CHubController::HandlePnp Unhandeled %x\n", IoStack->MinorFunction);
445 Status = Irp->IoStatus.Status;
446 break;
447 }
448 }
449
450 //
451 // complete request
452 //
453 Irp->IoStatus.Status = Status;
454 IoCompleteRequest(Irp, IO_NO_INCREMENT);
455
456 //
457 // done
458 //
459 return Status;
460 }
461
462 //-----------------------------------------------------------------------------------------
463 NTSTATUS
464 CHubController::HandlePower(
465 IN PDEVICE_OBJECT DeviceObject,
466 IN OUT PIRP Irp)
467 {
468 UNIMPLEMENTED
469 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
470 IoCompleteRequest(Irp, IO_NO_INCREMENT);
471 return STATUS_NOT_IMPLEMENTED;
472 }
473
474 //-----------------------------------------------------------------------------------------
475 NTSTATUS
476 CHubController::HandleDeviceControl(
477 IN PDEVICE_OBJECT DeviceObject,
478 IN OUT PIRP Irp)
479 {
480 PIO_STACK_LOCATION IoStack;
481 PCOMMON_DEVICE_EXTENSION DeviceExtension;
482 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
483
484 //
485 // get current stack location
486 //
487 IoStack = IoGetCurrentIrpStackLocation(Irp);
488
489 //
490 // get device extension
491 //
492 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
493
494
495 DPRINT1("HandleDeviceControl>Type: FDO %u IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n",
496 DeviceExtension->IsFDO,
497 IoStack->Parameters.DeviceIoControl.IoControlCode,
498 IoStack->Parameters.DeviceIoControl.InputBufferLength,
499 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
500
501 //
502 // determine which request should be performed
503 //
504 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
505 {
506 case IOCTL_INTERNAL_USB_SUBMIT_URB:
507 {
508 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB UNIMPLEMENTED\n");
509
510 //
511 // request completed
512 //
513 Status = STATUS_NOT_IMPLEMENTED;
514 break;
515 }
516 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
517 {
518 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
519
520 if (IoStack->Parameters.Others.Argument1)
521 {
522 //
523 // store object as device handle
524 //
525 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
526 Status = STATUS_SUCCESS;
527 }
528 else
529 {
530 //
531 // mis-behaving hub driver
532 //
533 Status = STATUS_INVALID_DEVICE_REQUEST;
534 }
535
536 //
537 // request completed
538 //
539 break;
540 }
541 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
542 {
543 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
544
545 //
546 // this is the first request send, it delivers the PDO to the caller
547 //
548 if (IoStack->Parameters.Others.Argument1)
549 {
550 //
551 // store root hub pdo object
552 //
553 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
554 }
555
556 if (IoStack->Parameters.Others.Argument2)
557 {
558 //
559 // documentation claims to deliver the hcd controller object, although it is wrong
560 //
561 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
562 }
563
564 //
565 // request completed
566 //
567 Status = STATUS_SUCCESS;
568 break;
569 }
570 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
571 {
572 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
573
574 //
575 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
576 // requests this ioctl to deliver the number of presents.
577
578 if (IoStack->Parameters.Others.Argument1)
579 {
580 //
581 // FIXME / verify: there is only one hub
582 //
583 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
584 }
585
586 //
587 // request completed
588 //
589 Status = STATUS_SUCCESS;
590 Irp->IoStatus.Information = sizeof(ULONG);
591 break;
592 }
593 }
594
595 Irp->IoStatus.Status = Status;
596 IoCompleteRequest(Irp, IO_NO_INCREMENT);
597 return Status;
598 }
599
600 //=================================================================================================
601 //
602 // Generic Interface functions
603 //
604 VOID
605 USB_BUSIFFN
606 USBI_InterfaceReference(
607 PVOID BusContext)
608 {
609 CHubController * Controller = (CHubController*)BusContext;
610
611 DPRINT1("USBH_InterfaceReference\n");
612
613 //
614 // add reference
615 //
616 Controller->AddRef();
617 }
618
619 VOID
620 USB_BUSIFFN
621 USBI_InterfaceDereference(
622 PVOID BusContext)
623 {
624 CHubController * Controller = (CHubController*)BusContext;
625
626 DPRINT1("USBH_InterfaceDereference\n");
627
628 //
629 // release
630 //
631 Controller->Release();
632 }
633 //=================================================================================================
634 //
635 // USB Hub Interface functions
636 //
637 NTSTATUS
638 USB_BUSIFFN
639 USBHI_CreateUsbDevice(
640 PVOID BusContext,
641 PUSB_DEVICE_HANDLE *NewDevice,
642 PUSB_DEVICE_HANDLE HubDeviceHandle,
643 USHORT PortStatus,
644 USHORT PortNumber)
645 {
646 UNIMPLEMENTED
647 return STATUS_NOT_IMPLEMENTED;
648 }
649
650 NTSTATUS
651 USB_BUSIFFN
652 USBHI_InitializeUsbDevice(
653 PVOID BusContext,
654 PUSB_DEVICE_HANDLE DeviceHandle)
655 {
656 UNIMPLEMENTED
657 return STATUS_NOT_IMPLEMENTED;
658 }
659
660 NTSTATUS
661 USB_BUSIFFN
662 USBHI_GetUsbDescriptors(
663 PVOID BusContext,
664 PUSB_DEVICE_HANDLE DeviceHandle,
665 PUCHAR DeviceDescriptorBuffer,
666 PULONG DeviceDescriptorBufferLength,
667 PUCHAR ConfigDescriptorBuffer,
668 PULONG ConfigDescriptorBufferLength)
669 {
670 UNIMPLEMENTED
671 return STATUS_NOT_IMPLEMENTED;
672 }
673
674 NTSTATUS
675 USB_BUSIFFN
676 USBHI_RemoveUsbDevice(
677 PVOID BusContext,
678 PUSB_DEVICE_HANDLE DeviceHandle,
679 ULONG Flags)
680 {
681 UNIMPLEMENTED
682 return STATUS_NOT_IMPLEMENTED;
683 }
684
685 NTSTATUS
686 USB_BUSIFFN
687 USBHI_RestoreUsbDevice(
688 PVOID BusContext,
689 PUSB_DEVICE_HANDLE OldDeviceHandle,
690 PUSB_DEVICE_HANDLE NewDeviceHandle)
691 {
692 UNIMPLEMENTED
693 return STATUS_NOT_IMPLEMENTED;
694 }
695
696 NTSTATUS
697 USB_BUSIFFN
698 USBHI_GetPortHackFlags(
699 PVOID BusContext,
700 PULONG Flags)
701 {
702 UNIMPLEMENTED
703 return STATUS_NOT_IMPLEMENTED;
704 }
705
706 NTSTATUS
707 USB_BUSIFFN
708 USBHI_QueryDeviceInformation(
709 PVOID BusContext,
710 PUSB_DEVICE_HANDLE DeviceHandle,
711 PVOID DeviceInformationBuffer,
712 ULONG DeviceInformationBufferLength,
713 PULONG LengthReturned)
714 {
715 UNIMPLEMENTED
716 return STATUS_NOT_IMPLEMENTED;
717 }
718
719 NTSTATUS
720 USB_BUSIFFN
721 USBHI_GetControllerInformation(
722 PVOID BusContext,
723 PVOID ControllerInformationBuffer,
724 ULONG ControllerInformationBufferLength,
725 PULONG LengthReturned)
726 {
727 UNIMPLEMENTED
728 return STATUS_NOT_IMPLEMENTED;
729 }
730
731 NTSTATUS
732 USB_BUSIFFN
733 USBHI_ControllerSelectiveSuspend(
734 PVOID BusContext,
735 BOOLEAN Enable)
736 {
737 UNIMPLEMENTED
738 return STATUS_NOT_IMPLEMENTED;
739 }
740
741 NTSTATUS
742 USB_BUSIFFN
743 USBHI_GetExtendedHubInformation(
744 PVOID BusContext,
745 PDEVICE_OBJECT HubPhysicalDeviceObject,
746 PVOID HubInformationBuffer,
747 ULONG HubInformationBufferLength,
748 PULONG LengthReturned)
749 {
750 UNIMPLEMENTED
751 return STATUS_NOT_IMPLEMENTED;
752 }
753
754 NTSTATUS
755 USB_BUSIFFN
756 USBHI_GetRootHubSymbolicName(
757 PVOID BusContext,
758 PVOID HubSymNameBuffer,
759 ULONG HubSymNameBufferLength,
760 PULONG HubSymNameActualLength)
761 {
762 UNIMPLEMENTED
763 return STATUS_NOT_IMPLEMENTED;
764 }
765
766 PVOID
767 USB_BUSIFFN
768 USBHI_GetDeviceBusContext(
769 PVOID HubBusContext,
770 PVOID DeviceHandle)
771 {
772 UNIMPLEMENTED
773 return NULL;
774 }
775
776 NTSTATUS
777 USB_BUSIFFN
778 USBHI_Initialize20Hub(
779 PVOID BusContext,
780 PUSB_DEVICE_HANDLE HubDeviceHandle,
781 ULONG TtCount)
782 {
783 UNIMPLEMENTED
784 return STATUS_NOT_IMPLEMENTED;
785 }
786
787 NTSTATUS
788 USB_BUSIFFN
789 USBHI_RootHubInitNotification(
790 PVOID BusContext,
791 PVOID CallbackContext,
792 PRH_INIT_CALLBACK CallbackRoutine)
793 {
794 UNIMPLEMENTED
795 return STATUS_NOT_IMPLEMENTED;
796 }
797
798 VOID
799 USB_BUSIFFN
800 USBHI_FlushTransfers(
801 PVOID BusContext,
802 PVOID DeviceHandle)
803 {
804 UNIMPLEMENTED
805 }
806
807 VOID
808 USB_BUSIFFN
809 USBHI_SetDeviceHandleData(
810 PVOID BusContext,
811 PVOID DeviceHandle,
812 PDEVICE_OBJECT UsbDevicePdo)
813 {
814 UNIMPLEMENTED
815 }
816
817 //=================================================================================================
818 //
819 // USB Device Interface functions
820 //
821
822 VOID
823 USB_BUSIFFN
824 USBDI_GetUSBDIVersion(
825 PVOID BusContext,
826 PUSBD_VERSION_INFORMATION VersionInformation,
827 PULONG HcdCapabilites)
828 {
829 UNIMPLEMENTED
830 }
831
832 NTSTATUS
833 USB_BUSIFFN
834 USBDI_QueryBusTime(
835 PVOID BusContext,
836 PULONG CurrentFrame)
837 {
838 UNIMPLEMENTED
839 return STATUS_NOT_IMPLEMENTED;
840 }
841
842 NTSTATUS
843 USB_BUSIFFN
844 USBDI_SubmitIsoOutUrb(
845 PVOID BusContext,
846 PURB Urb)
847 {
848 UNIMPLEMENTED
849 return STATUS_NOT_IMPLEMENTED;
850 }
851
852 NTSTATUS
853 USB_BUSIFFN
854 USBDI_QueryBusInformation(
855 PVOID BusContext,
856 ULONG Level,
857 PVOID BusInformationBuffer,
858 PULONG BusInformationBufferLength,
859 PULONG BusInformationActualLength)
860 {
861 UNIMPLEMENTED
862 return STATUS_NOT_IMPLEMENTED;
863 }
864
865 BOOLEAN
866 USB_BUSIFFN
867 USBDI_IsDeviceHighSpeed(
868 PVOID BusContext)
869 {
870 UNIMPLEMENTED
871 return TRUE;
872 }
873
874 NTSTATUS
875 USB_BUSIFFN
876 USBDI_EnumLogEntry(
877 PVOID BusContext,
878 ULONG DriverTag,
879 ULONG EnumTag,
880 ULONG P1,
881 ULONG P2)
882 {
883 UNIMPLEMENTED
884 return STATUS_NOT_IMPLEMENTED;
885 }
886
887 NTSTATUS
888 CHubController::HandleQueryInterface(
889 PIO_STACK_LOCATION IoStack)
890 {
891 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
892 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
893 UNICODE_STRING GuidBuffer;
894 NTSTATUS Status;
895
896 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
897 {
898 //
899 // get request parameters
900 //
901 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
902 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
903
904 //
905 // check version
906 //
907 if (IoStack->Parameters.QueryInterface.Version >= 6)
908 {
909 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
910
911 //
912 // version not supported
913 //
914 return STATUS_NOT_SUPPORTED;
915 }
916
917 //
918 // Interface version 0
919 //
920 if (IoStack->Parameters.QueryInterface.Version >= 0)
921 {
922 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
923 InterfaceHub->BusContext = PVOID(this);
924 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
925 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
926 }
927
928 //
929 // Interface version 1
930 //
931 if (IoStack->Parameters.QueryInterface.Version >= 1)
932 {
933 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
934 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
935 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
936 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
937 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
938 InterfaceHub->GetPortHackFlags = USBHI_GetPortHackFlags;
939 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
940 }
941
942 //
943 // Interface version 2
944 //
945 if (IoStack->Parameters.QueryInterface.Version >= 2)
946 {
947 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
948 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
949 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
950 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
951 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
952 InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
953
954 }
955
956 //
957 // Interface version 3
958 //
959 if (IoStack->Parameters.QueryInterface.Version >= 3)
960 {
961 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
962 }
963
964 //
965 // Interface version 4
966 //
967 if (IoStack->Parameters.QueryInterface.Version >= 4)
968 {
969 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
970 }
971
972 //
973 // Interface version 5
974 //
975 if (IoStack->Parameters.QueryInterface.Version >= 5)
976 {
977 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
978 }
979
980 //
981 // request completed
982 //
983 return STATUS_SUCCESS;
984 }
985 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
986 {
987 //
988 // get request parameters
989 //
990 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
991 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
992
993 //
994 // check version
995 //
996 if (IoStack->Parameters.QueryInterface.Version >= 3)
997 {
998 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
999
1000 //
1001 // version not supported
1002 //
1003 return STATUS_NOT_SUPPORTED;
1004 }
1005
1006 //
1007 // interface version 0
1008 //
1009 if (IoStack->Parameters.QueryInterface.Version >= 0)
1010 {
1011 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
1012 InterfaceDI->BusContext = PVOID(this);
1013 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
1014 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
1015 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
1016 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
1017 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
1018 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
1019 }
1020
1021 //
1022 // interface version 1
1023 //
1024 if (IoStack->Parameters.QueryInterface.Version >= 1)
1025 {
1026 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
1027 }
1028
1029 //
1030 // interface version 2
1031 //
1032 if (IoStack->Parameters.QueryInterface.Version >= 2)
1033 {
1034 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
1035 }
1036
1037 //
1038 // request completed
1039 //
1040 return STATUS_SUCCESS;
1041 }
1042 else
1043 {
1044 //
1045 // convert guid to string
1046 //
1047 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
1048 if (NT_SUCCESS(Status))
1049 {
1050 //
1051 // print interface
1052 //
1053 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
1054
1055 //
1056 // free guid buffer
1057 //
1058 RtlFreeUnicodeString(&GuidBuffer);
1059 }
1060 }
1061 return STATUS_NOT_SUPPORTED;
1062 }
1063
1064 NTSTATUS
1065 CHubController::SetDeviceInterface(
1066 BOOLEAN Enable)
1067 {
1068 NTSTATUS Status = STATUS_SUCCESS;
1069
1070 if (Enable)
1071 {
1072 //
1073 // register device interface
1074 //
1075 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
1076
1077 if (NT_SUCCESS(Status))
1078 {
1079 //
1080 // now enable the device interface
1081 //
1082 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
1083
1084 //
1085 // enable interface
1086 //
1087 m_InterfaceEnabled = TRUE;
1088 }
1089 }
1090 else if (m_InterfaceEnabled)
1091 {
1092 //
1093 // disable device interface
1094 //
1095 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
1096
1097 if (NT_SUCCESS(Status))
1098 {
1099 //
1100 // now delete interface string
1101 //
1102 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
1103 }
1104
1105 //
1106 // disable interface
1107 //
1108 m_InterfaceEnabled = FALSE;
1109 }
1110
1111 //
1112 // done
1113 //
1114 return Status;
1115 }
1116
1117 NTSTATUS
1118 CHubController::CreatePDO(
1119 PDRIVER_OBJECT DriverObject,
1120 PDEVICE_OBJECT * OutDeviceObject)
1121 {
1122 WCHAR CharDeviceName[64];
1123 NTSTATUS Status;
1124 ULONG UsbDeviceNumber = 0;
1125 UNICODE_STRING DeviceName;
1126
1127 while (TRUE)
1128 {
1129 //
1130 // construct device name
1131 //
1132 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
1133
1134 //
1135 // initialize device name
1136 //
1137 RtlInitUnicodeString(&DeviceName, CharDeviceName);
1138
1139 //
1140 // create device
1141 //
1142 Status = IoCreateDevice(DriverObject,
1143 sizeof(COMMON_DEVICE_EXTENSION),
1144 &DeviceName,
1145 FILE_DEVICE_CONTROLLER,
1146 0,
1147 FALSE,
1148 OutDeviceObject);
1149
1150 /* check for success */
1151 if (NT_SUCCESS(Status))
1152 break;
1153
1154 //
1155 // is there a device object with that same name
1156 //
1157 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
1158 {
1159 //
1160 // Try the next name
1161 //
1162 UsbDeviceNumber++;
1163 continue;
1164 }
1165
1166 //
1167 // bail out on other errors
1168 //
1169 if (!NT_SUCCESS(Status))
1170 {
1171 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
1172 return Status;
1173 }
1174 }
1175
1176 //
1177 // store PDO number
1178 //
1179 //m_PDODeviceNumber = UsbDeviceNumber;
1180
1181 DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
1182
1183 /* done */
1184 return Status;
1185 }
1186
1187
1188
1189 NTSTATUS
1190 CreateHubController(
1191 PHUBCONTROLLER *OutHcdController)
1192 {
1193 PHUBCONTROLLER This;
1194
1195 //
1196 // allocate controller
1197 //
1198 This = new(NonPagedPool, TAG_USBEHCI) CHubController(0);
1199 if (!This)
1200 {
1201 //
1202 // failed to allocate
1203 //
1204 return STATUS_INSUFFICIENT_RESOURCES;
1205 }
1206
1207 //
1208 // add reference count
1209 //
1210 This->AddRef();
1211
1212 //
1213 // return result
1214 //
1215 *OutHcdController = (PHUBCONTROLLER)This;
1216
1217 //
1218 // done
1219 //
1220 return STATUS_SUCCESS;
1221 }