[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 PUSBHARDWAREDEVICE GetUsbHardware();
51 ULONG AcquireDeviceAddress();
52 VOID ReleaseDeviceAddress(ULONG DeviceAddress);
53 BOOLEAN ValidateUsbDevice(PUSBDEVICE UsbDevice);
54 NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice);
55 NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice);
56 VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
57
58 // constructor / destructor
59 CHubController(IUnknown *OuterUnknown){}
60 virtual ~CHubController(){}
61
62 protected:
63 LONG m_Ref;
64 PHCDCONTROLLER m_Controller;
65 PUSBHARDWAREDEVICE m_Hardware;
66 BOOLEAN m_IsRootHubDevice;
67 ULONG m_DeviceAddress;
68 ULONG m_PDODeviceNumber;
69 BOOLEAN m_InterfaceEnabled;
70 UNICODE_STRING m_HubDeviceInterfaceString;
71 PDEVICE_OBJECT m_HubControllerDeviceObject;
72 PDRIVER_OBJECT m_DriverObject;
73
74 PVOID m_HubCallbackContext;
75 PRH_INIT_CALLBACK m_HubCallbackRoutine;
76
77
78 KSPIN_LOCK m_Lock;
79 RTL_BITMAP m_DeviceAddressBitmap;
80 PULONG m_DeviceAddressBitmapBuffer;
81 LIST_ENTRY m_UsbDeviceList;
82 };
83
84 typedef struct
85 {
86 LIST_ENTRY Entry;
87 PUSBDEVICE Device;
88 }USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY;
89
90
91 //----------------------------------------------------------------------------------------
92 NTSTATUS
93 STDMETHODCALLTYPE
94 CHubController::QueryInterface(
95 IN REFIID refiid,
96 OUT PVOID* Output)
97 {
98 return STATUS_UNSUCCESSFUL;
99 }
100 //----------------------------------------------------------------------------------------
101 NTSTATUS
102 CHubController::Initialize(
103 IN PDRIVER_OBJECT DriverObject,
104 IN PHCDCONTROLLER Controller,
105 IN PUSBHARDWAREDEVICE Device,
106 IN BOOLEAN IsRootHubDevice,
107 IN ULONG DeviceAddress)
108 {
109 NTSTATUS Status;
110 PCOMMON_DEVICE_EXTENSION DeviceExtension;
111
112 DPRINT1("CHubController::Initialize\n");
113
114 //
115 // initialize members
116 //
117 m_Controller = Controller;
118 m_Hardware = Device;
119 m_IsRootHubDevice = IsRootHubDevice;
120 m_DeviceAddress = DeviceAddress;
121 m_DriverObject = DriverObject;
122 KeInitializeSpinLock(&m_Lock);
123
124 //
125 // allocate device address bitmap buffer
126 //
127 m_DeviceAddressBitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, 16, TAG_USBEHCI);
128 if (!m_DeviceAddressBitmapBuffer)
129 {
130 //
131 // no memory
132 //
133 return STATUS_INSUFFICIENT_RESOURCES;
134 }
135
136 //
137 // initialize device address bitmap
138 //
139 RtlInitializeBitMap(&m_DeviceAddressBitmap, m_DeviceAddressBitmapBuffer, 128);
140 RtlClearAllBits(&m_DeviceAddressBitmap);
141
142
143 //
144 // create PDO
145 //
146 Status = CreatePDO(m_DriverObject, &m_HubControllerDeviceObject);
147 if (!NT_SUCCESS(Status))
148 {
149 //
150 // failed to create hub device object
151 //
152 return Status;
153 }
154
155 //
156 // get device extension
157 //
158 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_HubControllerDeviceObject->DeviceExtension;
159
160 //
161 // initialize device extension
162 //
163 DeviceExtension->IsFDO = FALSE;
164 DeviceExtension->IsHub = TRUE; //FIXME
165 DeviceExtension->Dispatcher = PDISPATCHIRP(this);
166
167 //
168 // clear init flag
169 //
170 m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
171
172
173 return STATUS_SUCCESS;
174 }
175
176 //-----------------------------------------------------------------------------------------
177 NTSTATUS
178 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject)
179 {
180 //
181 // store controller object
182 //
183 *HubDeviceObject = m_HubControllerDeviceObject;
184
185 return STATUS_SUCCESS;
186 }
187 //-----------------------------------------------------------------------------------------
188 NTSTATUS
189 CHubController::HandlePnp(
190 IN PDEVICE_OBJECT DeviceObject,
191 IN OUT PIRP Irp)
192 {
193 PIO_STACK_LOCATION IoStack;
194 PCOMMON_DEVICE_EXTENSION DeviceExtension;
195 PDEVICE_CAPABILITIES DeviceCapabilities;
196 PPNP_BUS_INFORMATION BusInformation;
197 NTSTATUS Status;
198 ULONG Index = 0, Length;
199 USHORT VendorID, DeviceID;
200 ULONG HiSpeed, NumPorts;
201 WCHAR Buffer[300];
202 LPWSTR DeviceName;
203
204 //
205 // get device extension
206 //
207 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
208
209 //
210 // sanity check
211 //
212 ASSERT(DeviceExtension->IsFDO == FALSE);
213
214 //
215 // get current stack location
216 //
217 IoStack = IoGetCurrentIrpStackLocation(Irp);
218
219 switch(IoStack->MinorFunction)
220 {
221 case IRP_MN_START_DEVICE:
222 {
223 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
224 //
225 // register device interface
226 //
227 Status = SetDeviceInterface(TRUE);
228 break;
229 }
230 case IRP_MN_QUERY_ID:
231 {
232 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack->Parameters.QueryId.IdType);
233
234 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
235 {
236 if (m_Hardware)
237 {
238 //
239 // query device id
240 //
241 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
242
243 if (HiSpeed == 0x200)
244 {
245 //
246 // USB 2.0 hub
247 //
248 swprintf(Buffer, L"USB\\ROOT_HUB20");
249 }
250 else
251 {
252 //
253 // USB 1.1 hub
254 //
255 swprintf(Buffer, L"USB\\ROOT_HUB");
256 }
257
258 DPRINT1("Name %S\n", Buffer);
259
260 //
261 // calculate length
262 //
263 Length = (wcslen(Buffer) + 1);
264
265 //
266 // allocate buffer
267 //
268 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_USBEHCI);
269
270 if (!DeviceName)
271 {
272 //
273 // no memory
274 //
275 Status = STATUS_INSUFFICIENT_RESOURCES;
276 break;
277 }
278
279 //
280 // copy device name
281 //
282 wcscpy(DeviceName, Buffer);
283
284 //
285 // store result
286 //
287 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
288 Status = STATUS_SUCCESS;
289 break;
290 }
291 Status = STATUS_UNSUCCESSFUL;
292 PC_ASSERT(0);
293 break;
294 }
295
296 if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
297 {
298 if (m_Hardware)
299 {
300 //
301 // query device id
302 //
303 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
304
305 if (!NT_SUCCESS(Status))
306 {
307 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status);
308 VendorID = 0x8086;
309 DeviceID = 0x3A37;
310 }
311
312 if (HiSpeed == 0x200)
313 {
314 //
315 // USB 2.0 hub
316 //
317 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
318 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID, DeviceID) + 1;
319 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
320 }
321 else
322 {
323 //
324 // USB 1.1 hub
325 //
326 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
327 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID, DeviceID) + 1;
328 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB") + 1;
329 }
330
331 Buffer[Index] = UNICODE_NULL;
332 Index++;
333
334
335 DPRINT1("Name %S\n", Buffer);
336
337 //
338 // allocate buffer
339 //
340 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Index * sizeof(WCHAR), TAG_USBEHCI);
341
342 if (!DeviceName)
343 {
344 //
345 // no memory
346 //
347 Status = STATUS_INSUFFICIENT_RESOURCES;
348 break;
349 }
350
351 //
352 // copy device name
353 //
354 RtlMoveMemory(DeviceName, Buffer, Index * sizeof(WCHAR));
355
356 //
357 // store result
358 //
359 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
360 Status = STATUS_SUCCESS;
361 break;
362 }
363 }
364 Status = STATUS_SUCCESS;
365 break;
366 }
367 case IRP_MN_QUERY_CAPABILITIES:
368 {
369 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
370
371 DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
372
373 DeviceCapabilities->LockSupported = FALSE;
374 DeviceCapabilities->EjectSupported = FALSE;
375 DeviceCapabilities->Removable = FALSE;
376 DeviceCapabilities->DockDevice = FALSE;
377 DeviceCapabilities->UniqueID = FALSE;
378 DeviceCapabilities->SilentInstall = FALSE;
379 DeviceCapabilities->RawDeviceOK = FALSE;
380 DeviceCapabilities->SurpriseRemovalOK = FALSE;
381 DeviceCapabilities->Address = 0;
382 DeviceCapabilities->UINumber = 0;
383 DeviceCapabilities->DeviceD2 = 1;
384
385 /* FIXME */
386 DeviceCapabilities->HardwareDisabled = FALSE;
387 DeviceCapabilities->NoDisplayInUI = FALSE;
388 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
389 for (Index = 0; Index < PowerSystemMaximum; Index++)
390 DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
391 DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
392 DeviceCapabilities->D1Latency = 0;
393 DeviceCapabilities->D2Latency = 0;
394 DeviceCapabilities->D3Latency = 0;
395
396 Status = STATUS_SUCCESS;
397 break;
398 }
399 case IRP_MN_QUERY_INTERFACE:
400 {
401 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
402
403 //
404 // handle device interface requests
405 //
406 Status = HandleQueryInterface(IoStack);
407 break;
408 }
409 case IRP_MN_REMOVE_DEVICE:
410 {
411 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
412
413 //
414 // deactivate device interface for BUS PDO
415 //
416 SetDeviceInterface(FALSE);
417
418 //
419 // complete the request first
420 //
421 Irp->IoStatus.Status = STATUS_SUCCESS;
422 IoCompleteRequest(Irp, IO_NO_INCREMENT);
423
424 //
425 // now delete device
426 //
427 IoDeleteDevice(m_HubControllerDeviceObject);
428
429 //
430 // nullify pointer
431 //
432 m_HubControllerDeviceObject = 0;
433
434 //
435 // done
436 //
437 return STATUS_SUCCESS;
438 }
439 case IRP_MN_QUERY_BUS_INFORMATION:
440 {
441 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
442
443 //
444 // allocate buffer for bus information
445 //
446 BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
447 if (BusInformation)
448 {
449 //
450 // copy BUS guid
451 //
452 RtlMoveMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_USB, sizeof(GUID));
453
454 //
455 // set bus type
456 //
457 BusInformation->LegacyBusType = PNPBus;
458 BusInformation->BusNumber = 0;
459
460 Status = STATUS_SUCCESS;
461 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
462 }
463 else
464 {
465 //
466 // no memory
467 //
468 Status = STATUS_INSUFFICIENT_RESOURCES;
469 }
470 break;
471 }
472 case IRP_MN_STOP_DEVICE:
473 {
474 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
475 //
476 // stop device
477 //
478 Status = STATUS_SUCCESS;
479 break;
480 }
481 default:
482 {
483 DPRINT1("CHubController::HandlePnp Unhandeled %x\n", IoStack->MinorFunction);
484 Status = Irp->IoStatus.Status;
485 break;
486 }
487 }
488
489 //
490 // complete request
491 //
492 Irp->IoStatus.Status = Status;
493 IoCompleteRequest(Irp, IO_NO_INCREMENT);
494
495 //
496 // done
497 //
498 return Status;
499 }
500
501 //-----------------------------------------------------------------------------------------
502 NTSTATUS
503 CHubController::HandlePower(
504 IN PDEVICE_OBJECT DeviceObject,
505 IN OUT PIRP Irp)
506 {
507 UNIMPLEMENTED
508 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
509 IoCompleteRequest(Irp, IO_NO_INCREMENT);
510 return STATUS_NOT_IMPLEMENTED;
511 }
512
513 //-----------------------------------------------------------------------------------------
514 NTSTATUS
515 CHubController::HandleDeviceControl(
516 IN PDEVICE_OBJECT DeviceObject,
517 IN OUT PIRP Irp)
518 {
519 PIO_STACK_LOCATION IoStack;
520 PCOMMON_DEVICE_EXTENSION DeviceExtension;
521 PURB Urb;
522 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
523
524 //
525 // get current stack location
526 //
527 IoStack = IoGetCurrentIrpStackLocation(Irp);
528
529 //
530 // get device extension
531 //
532 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
533
534
535 DPRINT1("HandleDeviceControl>Type: FDO %u IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n",
536 DeviceExtension->IsFDO,
537 IoStack->Parameters.DeviceIoControl.IoControlCode,
538 IoStack->Parameters.DeviceIoControl.InputBufferLength,
539 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
540
541 //
542 // determine which request should be performed
543 //
544 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
545 {
546 case IOCTL_INTERNAL_USB_SUBMIT_URB:
547 {
548 //
549 // get urb
550 //
551 Urb = (PURB)IoStack->Parameters.Others.Argument1;
552 PC_ASSERT(Urb);
553
554 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x Length %lu Status %x Handle %p Flags %x UNIMPLEMENTED\n", Urb->UrbHeader.Function, Urb->UrbHeader.Length, Urb->UrbHeader.Status, Urb->UrbHeader.UsbdDeviceHandle, Urb->UrbHeader.UsbdFlags);
555
556 //
557 // request completed
558 //
559 Status = STATUS_NOT_IMPLEMENTED;
560 break;
561 }
562 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
563 {
564 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
565
566 if (IoStack->Parameters.Others.Argument1)
567 {
568 //
569 // store object as device handle
570 //
571 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
572 Status = STATUS_SUCCESS;
573 }
574 else
575 {
576 //
577 // mis-behaving hub driver
578 //
579 Status = STATUS_INVALID_DEVICE_REQUEST;
580 }
581
582 //
583 // request completed
584 //
585 break;
586 }
587 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
588 {
589 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
590
591 //
592 // this is the first request send, it delivers the PDO to the caller
593 //
594 if (IoStack->Parameters.Others.Argument1)
595 {
596 //
597 // store root hub pdo object
598 //
599 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
600 }
601
602 if (IoStack->Parameters.Others.Argument2)
603 {
604 //
605 // documentation claims to deliver the hcd controller object, although it is wrong
606 //
607 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
608 }
609
610 //
611 // request completed
612 //
613 Status = STATUS_SUCCESS;
614 break;
615 }
616 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
617 {
618 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
619
620 //
621 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
622 // requests this ioctl to deliver the number of presents.
623
624 if (IoStack->Parameters.Others.Argument1)
625 {
626 //
627 // FIXME / verify: there is only one hub
628 //
629 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
630 }
631
632 //
633 // request completed
634 //
635 Status = STATUS_SUCCESS;
636 Irp->IoStatus.Information = sizeof(ULONG);
637 break;
638 }
639 }
640
641 Irp->IoStatus.Status = Status;
642 IoCompleteRequest(Irp, IO_NO_INCREMENT);
643 return Status;
644 }
645
646 //-----------------------------------------------------------------------------------------
647 PUSBHARDWAREDEVICE
648 CHubController::GetUsbHardware()
649 {
650 return m_Hardware;
651 }
652
653 //-----------------------------------------------------------------------------------------
654 ULONG
655 CHubController::AcquireDeviceAddress()
656 {
657 KIRQL OldLevel;
658 ULONG DeviceAddress;
659
660 //
661 // acquire device lock
662 //
663 KeAcquireSpinLock(&m_Lock, &OldLevel);
664
665 //
666 // find address
667 //
668 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
669 if (DeviceAddress != MAXULONG)
670 {
671 //
672 // reserve address
673 //
674 RtlSetBit(&m_DeviceAddressBitmap, DeviceAddress);
675
676 //
677 // device addresses start from 0x1 - 0xFF
678 //
679 DeviceAddress++;
680 }
681
682 //
683 // release spin lock
684 //
685 KeReleaseSpinLock(&m_Lock, OldLevel);
686
687 //
688 // return device address
689 //
690 return DeviceAddress;
691 }
692 //-----------------------------------------------------------------------------------------
693 VOID
694 CHubController::ReleaseDeviceAddress(
695 ULONG DeviceAddress)
696 {
697 KIRQL OldLevel;
698
699 //
700 // acquire device lock
701 //
702 KeAcquireSpinLock(&m_Lock, &OldLevel);
703
704 //
705 // sanity check
706 //
707 PC_ASSERT(DeviceAddress != 0);
708
709 //
710 // convert back to bit number
711 //
712 DeviceAddress--;
713
714 //
715 // clear bit
716 //
717 RtlClearBit(&m_DeviceAddressBitmap, DeviceAddress);
718
719 //
720 // release lock
721 //
722 KeReleaseSpinLock(&m_Lock, OldLevel);
723 }
724 //-----------------------------------------------------------------------------------------
725 NTSTATUS
726 CHubController::RemoveUsbDevice(
727 PUSBDEVICE UsbDevice)
728 {
729 PUSBDEVICE_ENTRY DeviceEntry;
730 PLIST_ENTRY Entry;
731 NTSTATUS Status = STATUS_UNSUCCESSFUL;
732 KIRQL OldLevel;
733
734 //
735 // acquire lock
736 //
737 KeAcquireSpinLock(&m_Lock, &OldLevel);
738
739 //
740 // point to first entry
741 //
742 Entry = m_UsbDeviceList.Flink;
743
744 //
745 // find matching entry
746 //
747 while(Entry != &m_UsbDeviceList)
748 {
749 //
750 // get entry
751 //
752 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
753
754 //
755 // is it current entry
756 //
757 if (DeviceEntry->Device == UsbDevice)
758 {
759 //
760 // remove entry
761 //
762 RemoveEntryList(Entry);
763
764 //
765 // free entry
766 //
767 ExFreePoolWithTag(DeviceEntry, TAG_USBEHCI);
768
769 //
770 // done
771 //
772 Status = STATUS_SUCCESS;
773 break;
774 }
775
776 //
777 // goto next device
778 //
779 Entry = Entry->Flink;
780 }
781
782 //
783 // release lock
784 //
785 KeReleaseSpinLock(&m_Lock, OldLevel);
786
787 //
788 // return result
789 //
790 return Status;
791 }
792 //-----------------------------------------------------------------------------------------
793 BOOLEAN
794 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
795 {
796 PUSBDEVICE_ENTRY DeviceEntry;
797 PLIST_ENTRY Entry;
798 KIRQL OldLevel;
799 BOOLEAN Result = FALSE;
800
801 //
802 // acquire lock
803 //
804 KeAcquireSpinLock(&m_Lock, &OldLevel);
805
806 //
807 // point to first entry
808 //
809 Entry = m_UsbDeviceList.Flink;
810
811 //
812 // find matching entry
813 //
814 while(Entry != &m_UsbDeviceList)
815 {
816 //
817 // get entry
818 //
819 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
820
821 //
822 // is it current entry
823 //
824 if (DeviceEntry->Device == UsbDevice)
825 {
826 //
827 // device is valid
828 //
829 Result = TRUE;
830 break;
831 }
832
833 //
834 // goto next device
835 //
836 Entry = Entry->Flink;
837 }
838
839 //
840 // release lock
841 //
842 KeReleaseSpinLock(&m_Lock, OldLevel);
843
844 //
845 // return result
846 //
847 return Result;
848
849 }
850
851 //-----------------------------------------------------------------------------------------
852 NTSTATUS
853 CHubController::AddUsbDevice(
854 PUSBDEVICE UsbDevice)
855 {
856 PUSBDEVICE_ENTRY DeviceEntry;
857 NTSTATUS Status;
858 KIRQL OldLevel;
859
860 //
861 // allocate device entry
862 //
863 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBEHCI);
864 if (!DeviceEntry)
865 {
866 //
867 // no memory
868 //
869 return STATUS_INSUFFICIENT_RESOURCES;
870 }
871
872 //
873 // initialize entry
874 //
875 DeviceEntry->Device = UsbDevice;
876
877 //
878 // acquire lock
879 //
880 KeAcquireSpinLock(&m_Lock, &OldLevel);
881
882 //
883 // insert entry
884 //
885 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
886
887 //
888 // release spin lock
889 //
890 KeReleaseSpinLock(&m_Lock, OldLevel);
891
892 //
893 // done
894 //
895 return STATUS_SUCCESS;
896 }
897
898 //-----------------------------------------------------------------------------------------
899 VOID
900 CHubController::SetNotification(
901 PVOID CallbackContext,
902 PRH_INIT_CALLBACK CallbackRoutine)
903 {
904 KIRQL OldLevel;
905
906 //
907 // acquire hub controller lock
908 //
909 KeAcquireSpinLock(&m_Lock, &OldLevel);
910
911 //
912 // now set the callback routine and context of the hub
913 //
914 m_HubCallbackContext = CallbackContext;
915 m_HubCallbackRoutine = CallbackRoutine;
916
917 //
918 // release hub controller lock
919 //
920 KeReleaseSpinLock(&m_Lock, OldLevel);
921 }
922
923 //=================================================================================================
924 //
925 // Generic Interface functions
926 //
927 VOID
928 USB_BUSIFFN
929 USBI_InterfaceReference(
930 PVOID BusContext)
931 {
932 CHubController * Controller = (CHubController*)BusContext;
933
934 DPRINT1("USBH_InterfaceReference\n");
935
936 //
937 // add reference
938 //
939 Controller->AddRef();
940 }
941
942 VOID
943 USB_BUSIFFN
944 USBI_InterfaceDereference(
945 PVOID BusContext)
946 {
947 CHubController * Controller = (CHubController*)BusContext;
948
949 DPRINT1("USBH_InterfaceDereference\n");
950
951 //
952 // release
953 //
954 Controller->Release();
955 }
956 //=================================================================================================
957 //
958 // USB Hub Interface functions
959 //
960 NTSTATUS
961 USB_BUSIFFN
962 USBHI_CreateUsbDevice(
963 PVOID BusContext,
964 PUSB_DEVICE_HANDLE *NewDevice,
965 PUSB_DEVICE_HANDLE HubDeviceHandle,
966 USHORT PortStatus,
967 USHORT PortNumber)
968 {
969 PUSBDEVICE NewUsbDevice;
970 CHubController * Controller;
971 NTSTATUS Status;
972
973 DPRINT1("USBHI_CreateUsbDevice\n");
974
975 //
976 // first get hub controller
977 //
978 Controller = (CHubController *)BusContext;
979
980 //
981 // sanity check
982 //
983 PC_ASSERT(Controller);
984 PC_ASSERT(BusContext == HubDeviceHandle);
985
986 //
987 // now allocate usb device
988 //
989 Status = CreateUSBDevice(&NewUsbDevice);
990
991 //
992 // check for success
993 //
994 if (!NT_SUCCESS(Status))
995 {
996 //
997 // release controller
998 //
999 Controller->Release();
1000 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
1001 return Status;
1002 }
1003
1004 //
1005 // now initialize device
1006 //
1007 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber);
1008
1009 //
1010 // check for success
1011 //
1012 if (!NT_SUCCESS(Status))
1013 {
1014 //
1015 // release usb device
1016 //
1017 NewUsbDevice->Release();
1018 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
1019 return Status;
1020 }
1021
1022 //
1023 // insert into list
1024 //
1025 Status = Controller->AddUsbDevice(NewUsbDevice);
1026 //
1027 // check for success
1028 //
1029 if (!NT_SUCCESS(Status))
1030 {
1031 //
1032 // release usb device
1033 //
1034 NewUsbDevice->Release();
1035
1036 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
1037 return Status;
1038 }
1039
1040 //
1041 // store the handle
1042 //
1043 *NewDevice = NewUsbDevice;
1044
1045 //
1046 // done
1047 //
1048 return STATUS_SUCCESS;
1049 }
1050
1051 NTSTATUS
1052 USB_BUSIFFN
1053 USBHI_InitializeUsbDevice(
1054 PVOID BusContext,
1055 PUSB_DEVICE_HANDLE DeviceHandle)
1056 {
1057 PUSBDEVICE UsbDevice;
1058 CHubController * Controller;
1059 ULONG DeviceAddress;
1060 NTSTATUS Status;
1061 ULONG Index = 0;
1062
1063 DPRINT1("USBHI_InitializeUsbDevice\n");
1064
1065 //
1066 // first get controller
1067 //
1068 Controller = (CHubController *)BusContext;
1069 PC_ASSERT(Controller);
1070
1071 //
1072 // get device object
1073 //
1074 UsbDevice = (PUSBDEVICE)DeviceHandle;
1075 PC_ASSERT(UsbDevice);
1076
1077 //
1078 // validate device handle
1079 //
1080 if (!Controller->ValidateUsbDevice(UsbDevice))
1081 {
1082 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
1083
1084 //
1085 // invalid device handle
1086 //
1087 return STATUS_DEVICE_NOT_CONNECTED;
1088 }
1089
1090 //
1091 // now reserve an address
1092 //
1093 DeviceAddress = Controller->AcquireDeviceAddress();
1094
1095 //
1096 // is the device address valid
1097 //
1098 if (DeviceAddress == MAXULONG)
1099 {
1100 //
1101 // failed to get an device address from the device address pool
1102 //
1103 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
1104 return STATUS_DEVICE_DATA_ERROR;
1105 }
1106
1107 do
1108 {
1109 //
1110 // now set the device address
1111 //
1112 Status = UsbDevice->SetDeviceAddress(DeviceAddress);
1113
1114 if (NT_SUCCESS(Status))
1115 break;
1116
1117 }while(Index++ < 3 );
1118
1119 //
1120 // check for failure
1121 //
1122 if (!NT_SUCCESS(Status))
1123 {
1124 //
1125 // failed to set device address
1126 //
1127 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
1128
1129 //
1130 // release address
1131 //
1132 Controller->ReleaseDeviceAddress(DeviceAddress);
1133
1134 //
1135 // return error
1136 //
1137 return STATUS_DEVICE_DATA_ERROR;
1138 }
1139
1140 //
1141 // done
1142 //
1143 return STATUS_SUCCESS;
1144 }
1145
1146 NTSTATUS
1147 USB_BUSIFFN
1148 USBHI_GetUsbDescriptors(
1149 PVOID BusContext,
1150 PUSB_DEVICE_HANDLE DeviceHandle,
1151 PUCHAR DeviceDescriptorBuffer,
1152 PULONG DeviceDescriptorBufferLength,
1153 PUCHAR ConfigDescriptorBuffer,
1154 PULONG ConfigDescriptorBufferLength)
1155 {
1156 PUSBDEVICE UsbDevice;
1157 CHubController * Controller;
1158 NTSTATUS Status;
1159 PURB Urb;
1160
1161 DPRINT1("USBHI_GetUsbDescriptors\n");
1162
1163 //
1164 // sanity check
1165 //
1166 PC_ASSERT(DeviceDescriptorBuffer);
1167 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1168
1169 //
1170 // first get controller
1171 //
1172 Controller = (CHubController *)BusContext;
1173 PC_ASSERT(Controller);
1174
1175
1176 //
1177 // get device object
1178 //
1179 UsbDevice = (PUSBDEVICE)DeviceHandle;
1180 PC_ASSERT(UsbDevice);
1181
1182 //
1183 // validate device handle
1184 //
1185 if (!Controller->ValidateUsbDevice(UsbDevice))
1186 {
1187 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
1188
1189 //
1190 // invalid device handle
1191 //
1192 return STATUS_DEVICE_NOT_CONNECTED;
1193 }
1194
1195 //
1196 // get device descriptor
1197 //
1198 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
1199
1200 //
1201 // store result length
1202 //
1203 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
1204
1205 //
1206 // allocate urb
1207 //
1208 Urb = (PURB)ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), TAG_USBEHCI);
1209 if (!Urb)
1210 {
1211 //
1212 // no memory
1213 //
1214 return STATUS_INSUFFICIENT_RESOURCES;
1215 }
1216
1217 //
1218 // zero request
1219 //
1220 RtlZeroMemory(Urb, sizeof(URB));
1221
1222 //
1223 // initialize request
1224 //
1225 Urb->UrbHeader.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
1226 Urb->UrbHeader.Length = sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST);
1227 Urb->UrbControlDescriptorRequest.DescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE;
1228 Urb->UrbControlDescriptorRequest.TransferBuffer = ConfigDescriptorBuffer;
1229 Urb->UrbControlDescriptorRequest.TransferBufferLength = *ConfigDescriptorBufferLength;
1230
1231 //
1232 // submit urb
1233 //
1234 Status = UsbDevice->SubmitUrb(Urb);
1235
1236 if (NT_SUCCESS(Status))
1237 {
1238 //
1239 // TransferBufferLength holds the number of bytes transferred
1240 //
1241 *ConfigDescriptorBufferLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
1242 }
1243
1244 //
1245 // free urb
1246 //
1247 ExFreePoolWithTag(Urb, TAG_USBEHCI);
1248
1249 //
1250 // complete the request
1251 //
1252 return Status;
1253 }
1254
1255 NTSTATUS
1256 USB_BUSIFFN
1257 USBHI_RemoveUsbDevice(
1258 PVOID BusContext,
1259 PUSB_DEVICE_HANDLE DeviceHandle,
1260 ULONG Flags)
1261 {
1262 PUSBDEVICE UsbDevice;
1263 CHubController * Controller;
1264 NTSTATUS Status;
1265
1266 DPRINT1("USBHI_RemoveUsbDevice\n");
1267
1268 //
1269 // first get controller
1270 //
1271 Controller = (CHubController *)BusContext;
1272 PC_ASSERT(Controller);
1273
1274 //
1275 // get device object
1276 //
1277 UsbDevice = (PUSBDEVICE)DeviceHandle;
1278 PC_ASSERT(UsbDevice);
1279
1280 //
1281 // validate device handle
1282 //
1283 if (!Controller->ValidateUsbDevice(UsbDevice))
1284 {
1285 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
1286
1287 //
1288 // invalid device handle
1289 //
1290 return STATUS_DEVICE_NOT_CONNECTED;
1291 }
1292
1293 //
1294 // check if there were flags passed
1295 //
1296 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
1297 {
1298 //
1299 // ignore flags for now
1300 //
1301 return STATUS_SUCCESS;
1302 }
1303
1304 //
1305 // remove device
1306 //
1307 Status = Controller->RemoveUsbDevice(UsbDevice);
1308 if (!NT_SUCCESS(Status))
1309 {
1310 //
1311 // invalid device handle
1312 //
1313 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
1314 PC_ASSERT(0);
1315 return STATUS_DEVICE_NOT_CONNECTED;
1316 }
1317
1318 //
1319 // release usb device
1320 //
1321 UsbDevice->Release();
1322
1323 //
1324 // done
1325 //
1326 return STATUS_SUCCESS;
1327 }
1328
1329 NTSTATUS
1330 USB_BUSIFFN
1331 USBHI_RestoreUsbDevice(
1332 PVOID BusContext,
1333 PUSB_DEVICE_HANDLE OldDeviceHandle,
1334 PUSB_DEVICE_HANDLE NewDeviceHandle)
1335 {
1336 UNIMPLEMENTED
1337 return STATUS_NOT_IMPLEMENTED;
1338 }
1339
1340 NTSTATUS
1341 USB_BUSIFFN
1342 USBHI_GetPortHackFlags(
1343 PVOID BusContext,
1344 PULONG Flags)
1345 {
1346 UNIMPLEMENTED
1347 return STATUS_NOT_IMPLEMENTED;
1348 }
1349
1350 NTSTATUS
1351 USB_BUSIFFN
1352 USBHI_QueryDeviceInformation(
1353 PVOID BusContext,
1354 PUSB_DEVICE_HANDLE DeviceHandle,
1355 PVOID DeviceInformationBuffer,
1356 ULONG DeviceInformationBufferLength,
1357 PULONG LengthReturned)
1358 {
1359 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
1360 PUSBDEVICE UsbDevice;
1361 CHubController * Controller;
1362 NTSTATUS Status;
1363
1364 DPRINT1("USBHI_QueryDeviceInformation\n");
1365
1366 //
1367 // sanity check
1368 //
1369 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
1370 PC_ASSERT(DeviceInformationBuffer);
1371 PC_ASSERT(LengthReturned);
1372
1373 //
1374 // get controller object
1375 //
1376 Controller = (CHubController*)BusContext;
1377 PC_ASSERT(Controller);
1378
1379 //
1380 // get device object
1381 //
1382 UsbDevice = (PUSBDEVICE)DeviceHandle;
1383 PC_ASSERT(UsbDevice);
1384
1385 //
1386 // validate device handle
1387 //
1388 if (!Controller->ValidateUsbDevice(UsbDevice))
1389 {
1390 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
1391
1392 //
1393 // invalid device handle
1394 //
1395 return STATUS_DEVICE_NOT_CONNECTED;
1396 }
1397
1398 //
1399 // access information buffer
1400 //
1401 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
1402
1403 //
1404 // initialize with default values
1405 //
1406 DeviceInfo->InformationLevel = 0;
1407 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
1408 DeviceInfo->PortNumber = UsbDevice->GetPort();
1409 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
1410 DeviceInfo->DeviceAddress = 0; UsbDevice->GetDeviceAddress();
1411 DeviceInfo->HubAddress = 0; //FIXME
1412 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
1413 DeviceInfo->DeviceType = UsbDevice->GetType();
1414 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
1415
1416 //
1417 // get device descriptor
1418 //
1419 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
1420
1421 //
1422 // FIXME return pipe information
1423 //
1424
1425 //
1426 // store result length
1427 //
1428 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
1429
1430 return STATUS_SUCCESS;
1431 }
1432
1433 NTSTATUS
1434 USB_BUSIFFN
1435 USBHI_GetControllerInformation(
1436 PVOID BusContext,
1437 PVOID ControllerInformationBuffer,
1438 ULONG ControllerInformationBufferLength,
1439 PULONG LengthReturned)
1440 {
1441 UNIMPLEMENTED
1442 return STATUS_NOT_IMPLEMENTED;
1443 }
1444
1445 NTSTATUS
1446 USB_BUSIFFN
1447 USBHI_ControllerSelectiveSuspend(
1448 PVOID BusContext,
1449 BOOLEAN Enable)
1450 {
1451 UNIMPLEMENTED
1452 return STATUS_NOT_IMPLEMENTED;
1453 }
1454
1455 NTSTATUS
1456 USB_BUSIFFN
1457 USBHI_GetExtendedHubInformation(
1458 PVOID BusContext,
1459 PDEVICE_OBJECT HubPhysicalDeviceObject,
1460 PVOID HubInformationBuffer,
1461 ULONG HubInformationBufferLength,
1462 PULONG LengthReturned)
1463 {
1464 PUSB_EXTHUB_INFORMATION_0 HubInfo;
1465 CHubController * Controller;
1466 PUSBHARDWAREDEVICE Hardware;
1467 ULONG Index;
1468 ULONG NumPort, Dummy2;
1469 USHORT Dummy1;
1470 NTSTATUS Status;
1471
1472 DPRINT1("USBHI_GetExtendedHubInformation\n");
1473
1474 //
1475 // sanity checks
1476 //
1477 PC_ASSERT(HubInformationBuffer);
1478 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
1479 PC_ASSERT(LengthReturned);
1480
1481 //
1482 // get hub controller
1483 //
1484 Controller = (CHubController *)BusContext;
1485 PC_ASSERT(Controller);
1486
1487 //
1488 // get usb hardware device
1489 //
1490 Hardware = Controller->GetUsbHardware();
1491
1492 //
1493 // retrieve number of ports
1494 //
1495 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
1496 if (!NT_SUCCESS(Status))
1497 {
1498 //
1499 // failed to get hardware details, ouch ;)
1500 //
1501 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
1502 return Status;
1503 }
1504
1505 //
1506 // get hub information buffer
1507 //
1508 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
1509
1510 //
1511 // initialize hub information
1512 //
1513 HubInfo->InformationLevel = 0;
1514
1515 //
1516 // store port count
1517 //
1518 HubInfo->NumberOfPorts = NumPort;
1519
1520 //
1521 // initialize port information
1522 //
1523 for(Index = 0; Index < NumPort; Index++)
1524 {
1525 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
1526 HubInfo->Port[Index].PortLabelNumber = Index + 1;
1527 HubInfo->Port[Index].VidOverride = 0;
1528 HubInfo->Port[Index].PidOverride = 0;
1529 HubInfo->Port[Index].PortAttributes = USB_PORTATTR_SHARED_USB2; //FIXME
1530 }
1531
1532 //
1533 // store result length
1534 //
1535 #ifdef _MSC_VER
1536 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
1537 #else
1538 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
1539 #endif
1540
1541 //
1542 // done
1543 //
1544 return STATUS_SUCCESS;
1545 }
1546
1547 NTSTATUS
1548 USB_BUSIFFN
1549 USBHI_GetRootHubSymbolicName(
1550 PVOID BusContext,
1551 PVOID HubSymNameBuffer,
1552 ULONG HubSymNameBufferLength,
1553 PULONG HubSymNameActualLength)
1554 {
1555 UNIMPLEMENTED
1556 return STATUS_NOT_IMPLEMENTED;
1557 }
1558
1559 PVOID
1560 USB_BUSIFFN
1561 USBHI_GetDeviceBusContext(
1562 PVOID HubBusContext,
1563 PVOID DeviceHandle)
1564 {
1565 UNIMPLEMENTED
1566 return NULL;
1567 }
1568
1569 NTSTATUS
1570 USB_BUSIFFN
1571 USBHI_Initialize20Hub(
1572 PVOID BusContext,
1573 PUSB_DEVICE_HANDLE HubDeviceHandle,
1574 ULONG TtCount)
1575 {
1576 UNIMPLEMENTED
1577 return STATUS_NOT_IMPLEMENTED;
1578 }
1579
1580 NTSTATUS
1581 USB_BUSIFFN
1582 USBHI_RootHubInitNotification(
1583 PVOID BusContext,
1584 PVOID CallbackContext,
1585 PRH_INIT_CALLBACK CallbackRoutine)
1586 {
1587 CHubController * Controller;
1588
1589 DPRINT1("USBHI_RootHubInitNotification\n");
1590
1591 //
1592 // get controller object
1593 //
1594 Controller = (CHubController*)BusContext;
1595 PC_ASSERT(Controller);
1596
1597 //
1598 // set notification routine
1599 //
1600 Controller->SetNotification(CallbackContext, CallbackRoutine);
1601
1602 //
1603 // done
1604 //
1605 return STATUS_SUCCESS;
1606 }
1607
1608 VOID
1609 USB_BUSIFFN
1610 USBHI_FlushTransfers(
1611 PVOID BusContext,
1612 PVOID DeviceHandle)
1613 {
1614 UNIMPLEMENTED
1615 }
1616
1617 VOID
1618 USB_BUSIFFN
1619 USBHI_SetDeviceHandleData(
1620 PVOID BusContext,
1621 PVOID DeviceHandle,
1622 PDEVICE_OBJECT UsbDevicePdo)
1623 {
1624 PUSBDEVICE UsbDevice;
1625 CHubController * Controller;
1626
1627 //
1628 // get controller
1629 //
1630 Controller = (CHubController *)BusContext;
1631 PC_ASSERT(Controller);
1632
1633 //
1634 // get device handle
1635 //
1636 UsbDevice = (PUSBDEVICE)DeviceHandle;
1637
1638 //
1639 // validate device handle
1640 //
1641 if (!Controller->ValidateUsbDevice(UsbDevice))
1642 {
1643 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
1644
1645 //
1646 // invalid handle
1647 //
1648 return;
1649 }
1650
1651 //
1652 // set device handle data
1653 //
1654 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
1655 }
1656
1657 //=================================================================================================
1658 //
1659 // USB Device Interface functions
1660 //
1661
1662 VOID
1663 USB_BUSIFFN
1664 USBDI_GetUSBDIVersion(
1665 PVOID BusContext,
1666 PUSBD_VERSION_INFORMATION VersionInformation,
1667 PULONG HcdCapabilites)
1668 {
1669 CHubController * Controller;
1670 PUSBHARDWAREDEVICE Device;
1671 ULONG Speed, Dummy2;
1672 USHORT Dummy1;
1673
1674 DPRINT1("USBDI_GetUSBDIVersion\n");
1675
1676 //
1677 // get controller
1678 //
1679 Controller = (CHubController*)BusContext;
1680
1681 //
1682 // get usb hardware
1683 //
1684 Device = Controller->GetUsbHardware();
1685 PC_ASSERT(Device);
1686
1687 if (VersionInformation)
1688 {
1689 //
1690 // windows xp supported
1691 //
1692 VersionInformation->USBDI_Version = 0x00000500;
1693
1694 //
1695 // get device speed
1696 //
1697 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
1698
1699 //
1700 // store speed details
1701 //
1702 VersionInformation->Supported_USB_Version = Speed;
1703 }
1704
1705 //
1706 // no flags supported
1707 //
1708 *HcdCapabilites = 0;
1709 }
1710
1711 NTSTATUS
1712 USB_BUSIFFN
1713 USBDI_QueryBusTime(
1714 PVOID BusContext,
1715 PULONG CurrentFrame)
1716 {
1717 UNIMPLEMENTED
1718 return STATUS_NOT_IMPLEMENTED;
1719 }
1720
1721 NTSTATUS
1722 USB_BUSIFFN
1723 USBDI_SubmitIsoOutUrb(
1724 PVOID BusContext,
1725 PURB Urb)
1726 {
1727 UNIMPLEMENTED
1728 return STATUS_NOT_IMPLEMENTED;
1729 }
1730
1731 NTSTATUS
1732 USB_BUSIFFN
1733 USBDI_QueryBusInformation(
1734 PVOID BusContext,
1735 ULONG Level,
1736 PVOID BusInformationBuffer,
1737 PULONG BusInformationBufferLength,
1738 PULONG BusInformationActualLength)
1739 {
1740 UNIMPLEMENTED
1741 return STATUS_NOT_IMPLEMENTED;
1742 }
1743
1744 BOOLEAN
1745 USB_BUSIFFN
1746 USBDI_IsDeviceHighSpeed(
1747 PVOID BusContext)
1748 {
1749 CHubController * Controller;
1750 PUSBHARDWAREDEVICE Device;
1751 ULONG Speed, Dummy2;
1752 USHORT Dummy1;
1753
1754 DPRINT1("USBDI_IsDeviceHighSpeed\n");
1755
1756 //
1757 // get controller
1758 //
1759 Controller = (CHubController*)BusContext;
1760
1761 //
1762 // get usb hardware
1763 //
1764 Device = Controller->GetUsbHardware();
1765 PC_ASSERT(Device);
1766
1767 //
1768 // get device speed
1769 //
1770 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
1771
1772 //
1773 // USB 2.0 equals 0x200
1774 //
1775 return (Speed == 0x200);
1776 }
1777
1778 NTSTATUS
1779 USB_BUSIFFN
1780 USBDI_EnumLogEntry(
1781 PVOID BusContext,
1782 ULONG DriverTag,
1783 ULONG EnumTag,
1784 ULONG P1,
1785 ULONG P2)
1786 {
1787 UNIMPLEMENTED
1788 return STATUS_NOT_IMPLEMENTED;
1789 }
1790
1791 NTSTATUS
1792 CHubController::HandleQueryInterface(
1793 PIO_STACK_LOCATION IoStack)
1794 {
1795 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
1796 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
1797 UNICODE_STRING GuidBuffer;
1798 NTSTATUS Status;
1799
1800 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
1801 {
1802 //
1803 // get request parameters
1804 //
1805 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
1806 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
1807
1808 //
1809 // check version
1810 //
1811 if (IoStack->Parameters.QueryInterface.Version >= 6)
1812 {
1813 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
1814
1815 //
1816 // version not supported
1817 //
1818 return STATUS_NOT_SUPPORTED;
1819 }
1820
1821 //
1822 // Interface version 0
1823 //
1824 if (IoStack->Parameters.QueryInterface.Version >= 0)
1825 {
1826 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
1827 InterfaceHub->BusContext = PVOID(this);
1828 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
1829 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
1830 }
1831
1832 //
1833 // Interface version 1
1834 //
1835 if (IoStack->Parameters.QueryInterface.Version >= 1)
1836 {
1837 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
1838 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
1839 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
1840 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
1841 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
1842 InterfaceHub->GetPortHackFlags = USBHI_GetPortHackFlags;
1843 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
1844 }
1845
1846 //
1847 // Interface version 2
1848 //
1849 if (IoStack->Parameters.QueryInterface.Version >= 2)
1850 {
1851 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
1852 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
1853 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
1854 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
1855 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
1856 InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
1857
1858 }
1859
1860 //
1861 // Interface version 3
1862 //
1863 if (IoStack->Parameters.QueryInterface.Version >= 3)
1864 {
1865 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
1866 }
1867
1868 //
1869 // Interface version 4
1870 //
1871 if (IoStack->Parameters.QueryInterface.Version >= 4)
1872 {
1873 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
1874 }
1875
1876 //
1877 // Interface version 5
1878 //
1879 if (IoStack->Parameters.QueryInterface.Version >= 5)
1880 {
1881 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
1882 }
1883
1884 //
1885 // request completed
1886 //
1887 return STATUS_SUCCESS;
1888 }
1889 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
1890 {
1891 //
1892 // get request parameters
1893 //
1894 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
1895 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
1896
1897 //
1898 // check version
1899 //
1900 if (IoStack->Parameters.QueryInterface.Version >= 3)
1901 {
1902 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
1903
1904 //
1905 // version not supported
1906 //
1907 return STATUS_NOT_SUPPORTED;
1908 }
1909
1910 //
1911 // interface version 0
1912 //
1913 if (IoStack->Parameters.QueryInterface.Version >= 0)
1914 {
1915 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
1916 InterfaceDI->BusContext = PVOID(this);
1917 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
1918 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
1919 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
1920 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
1921 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
1922 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
1923 }
1924
1925 //
1926 // interface version 1
1927 //
1928 if (IoStack->Parameters.QueryInterface.Version >= 1)
1929 {
1930 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
1931 }
1932
1933 //
1934 // interface version 2
1935 //
1936 if (IoStack->Parameters.QueryInterface.Version >= 2)
1937 {
1938 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
1939 }
1940
1941 //
1942 // request completed
1943 //
1944 return STATUS_SUCCESS;
1945 }
1946 else
1947 {
1948 //
1949 // convert guid to string
1950 //
1951 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
1952 if (NT_SUCCESS(Status))
1953 {
1954 //
1955 // print interface
1956 //
1957 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
1958
1959 //
1960 // free guid buffer
1961 //
1962 RtlFreeUnicodeString(&GuidBuffer);
1963 }
1964 }
1965 return STATUS_NOT_SUPPORTED;
1966 }
1967
1968 NTSTATUS
1969 CHubController::SetDeviceInterface(
1970 BOOLEAN Enable)
1971 {
1972 NTSTATUS Status = STATUS_SUCCESS;
1973
1974 if (Enable)
1975 {
1976 //
1977 // register device interface
1978 //
1979 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
1980
1981 if (NT_SUCCESS(Status))
1982 {
1983 //
1984 // now enable the device interface
1985 //
1986 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
1987
1988 //
1989 // enable interface
1990 //
1991 m_InterfaceEnabled = TRUE;
1992 }
1993 }
1994 else if (m_InterfaceEnabled)
1995 {
1996 //
1997 // disable device interface
1998 //
1999 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
2000
2001 if (NT_SUCCESS(Status))
2002 {
2003 //
2004 // now delete interface string
2005 //
2006 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
2007 }
2008
2009 //
2010 // disable interface
2011 //
2012 m_InterfaceEnabled = FALSE;
2013 }
2014
2015 //
2016 // done
2017 //
2018 return Status;
2019 }
2020
2021 NTSTATUS
2022 CHubController::CreatePDO(
2023 PDRIVER_OBJECT DriverObject,
2024 PDEVICE_OBJECT * OutDeviceObject)
2025 {
2026 WCHAR CharDeviceName[64];
2027 NTSTATUS Status;
2028 ULONG UsbDeviceNumber = 0;
2029 UNICODE_STRING DeviceName;
2030
2031 while (TRUE)
2032 {
2033 //
2034 // construct device name
2035 //
2036 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
2037
2038 //
2039 // initialize device name
2040 //
2041 RtlInitUnicodeString(&DeviceName, CharDeviceName);
2042
2043 //
2044 // create device
2045 //
2046 Status = IoCreateDevice(DriverObject,
2047 sizeof(COMMON_DEVICE_EXTENSION),
2048 &DeviceName,
2049 FILE_DEVICE_CONTROLLER,
2050 0,
2051 FALSE,
2052 OutDeviceObject);
2053
2054 /* check for success */
2055 if (NT_SUCCESS(Status))
2056 break;
2057
2058 //
2059 // is there a device object with that same name
2060 //
2061 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
2062 {
2063 //
2064 // Try the next name
2065 //
2066 UsbDeviceNumber++;
2067 continue;
2068 }
2069
2070 //
2071 // bail out on other errors
2072 //
2073 if (!NT_SUCCESS(Status))
2074 {
2075 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
2076 return Status;
2077 }
2078 }
2079
2080 //
2081 // store PDO number
2082 //
2083 //m_PDODeviceNumber = UsbDeviceNumber;
2084
2085 DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
2086
2087 /* done */
2088 return Status;
2089 }
2090
2091
2092
2093 NTSTATUS
2094 CreateHubController(
2095 PHUBCONTROLLER *OutHcdController)
2096 {
2097 PHUBCONTROLLER This;
2098
2099 //
2100 // allocate controller
2101 //
2102 This = new(NonPagedPool, TAG_USBEHCI) CHubController(0);
2103 if (!This)
2104 {
2105 //
2106 // failed to allocate
2107 //
2108 return STATUS_INSUFFICIENT_RESOURCES;
2109 }
2110
2111 //
2112 // add reference count
2113 //
2114 This->AddRef();
2115
2116 //
2117 // return result
2118 //
2119 *OutHcdController = (PHUBCONTROLLER)This;
2120
2121 //
2122 // done
2123 //
2124 return STATUS_SUCCESS;
2125 }