[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 VOID StatusChangeEndpointCallBack(
15 PVOID Context);
16
17 class CHubController : public IHubController,
18 public IDispatchIrp
19 {
20 public:
21 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
22
23 STDMETHODIMP_(ULONG) AddRef()
24 {
25 InterlockedIncrement(&m_Ref);
26 return m_Ref;
27 }
28 STDMETHODIMP_(ULONG) Release()
29 {
30 InterlockedDecrement(&m_Ref);
31
32 if (!m_Ref)
33 {
34 delete this;
35 return 0;
36 }
37 return m_Ref;
38 }
39
40 // IHubController interface functions
41 virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject, IN PHCDCONTROLLER Controller, IN PUSBHARDWAREDEVICE Device, IN BOOLEAN IsRootHubDevice, IN ULONG DeviceAddress);
42 virtual NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject);
43 virtual NTSTATUS GetHubControllerSymbolicLink(ULONG BufferLength, PVOID Buffer, PULONG RequiredLength);
44
45 // IDispatchIrp interface functions
46 virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
47 virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
48 virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
49
50 // local functions
51 NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack);
52 NTSTATUS SetDeviceInterface(BOOLEAN bEnable);
53 NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
54 PUSBHARDWAREDEVICE GetUsbHardware();
55 ULONG AcquireDeviceAddress();
56 VOID ReleaseDeviceAddress(ULONG DeviceAddress);
57 BOOLEAN ValidateUsbDevice(PUSBDEVICE UsbDevice);
58 NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice);
59 NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice);
60 VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
61 // internal ioctl routines
62 NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
63 NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
64 NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
65 NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
66 NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
67 NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
68
69 friend VOID StatusChangeEndpointCallBack(PVOID Context);
70
71 // constructor / destructor
72 CHubController(IUnknown *OuterUnknown){}
73 virtual ~CHubController(){}
74
75 protected:
76 LONG m_Ref;
77 PHCDCONTROLLER m_Controller;
78 PUSBHARDWAREDEVICE m_Hardware;
79 BOOLEAN m_IsRootHubDevice;
80 ULONG m_DeviceAddress;
81
82 BOOLEAN m_InterfaceEnabled;
83 UNICODE_STRING m_HubDeviceInterfaceString;
84
85 PDEVICE_OBJECT m_HubControllerDeviceObject;
86 PDRIVER_OBJECT m_DriverObject;
87
88 PVOID m_HubCallbackContext;
89 PRH_INIT_CALLBACK m_HubCallbackRoutine;
90
91 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
92
93 KSPIN_LOCK m_Lock;
94 RTL_BITMAP m_DeviceAddressBitmap;
95 PULONG m_DeviceAddressBitmapBuffer;
96 LIST_ENTRY m_UsbDeviceList;
97 PIRP m_PendingSCEIrp;
98
99 //Internal Functions
100 BOOLEAN QueryStatusChageEndpoint(PIRP Irp);
101 };
102
103 typedef struct
104 {
105 LIST_ENTRY Entry;
106 PUSBDEVICE Device;
107 }USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY;
108
109 /* Lifted from Linux with slight changes */
110 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
111 {
112 0x12, /* bLength; */
113 USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */
114 0x00, 0x20, /* bcdUSB; v1.1 */
115 USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */
116 0x01, /* bDeviceSubClass; */
117 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
118 0x08, /* bMaxPacketSize0; 8 Bytes */
119 /* Fill Vendor and Product in when init root hub */
120 0x00, 0x00, /* idVendor; */
121 0x00, 0x00, /* idProduct; */
122 0x00, 0x00, /* bcdDevice */
123 0x00, /* iManufacturer; */
124 0x00, /* iProduct; */
125 0x00, /* iSerialNumber; */
126 0x01 /* bNumConfigurations; */
127
128 };
129
130 const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] =
131 {
132 /* one configuration */
133 0x09, /* bLength; */
134 0x02, /* bDescriptorType; Configuration */
135 0x19, 0x00, /* wTotalLength; */
136 0x01, /* bNumInterfaces; (1) */
137 0x23, /* bConfigurationValue; */
138 0x00, /* iConfiguration; */
139 0x40, /* bmAttributes; */
140 0x00 /* MaxPower; */
141 };
142
143 const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
144 {
145 /* one interface */
146 0x09, /* bLength: Interface; */
147 0x04, /* bDescriptorType; Interface */
148 0x00, /* bInterfaceNumber; */
149 0x00, /* bAlternateSetting; */
150 0x01, /* bNumEndpoints; */
151 0x09, /* bInterfaceClass; HUB_CLASSCODE */
152 0x01, /* bInterfaceSubClass; */
153 0x00, /* bInterfaceProtocol: */
154 0x00 /* iInterface; */
155 };
156
157 const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
158 {
159 /* one endpoint (status change endpoint) */
160 0x07, /* bLength; */
161 0x05, /* bDescriptorType; Endpoint */
162 0x81, /* bEndpointAddress; IN Endpoint 1 */
163 0x03, /* bmAttributes; Interrupt */
164 0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
165 0xFF /* bInterval; (255ms -- usb 2.0 spec) */
166 };
167
168 //----------------------------------------------------------------------------------------
169 NTSTATUS
170 STDMETHODCALLTYPE
171 CHubController::QueryInterface(
172 IN REFIID refiid,
173 OUT PVOID* Output)
174 {
175 return STATUS_UNSUCCESSFUL;
176 }
177 //----------------------------------------------------------------------------------------
178 NTSTATUS
179 CHubController::Initialize(
180 IN PDRIVER_OBJECT DriverObject,
181 IN PHCDCONTROLLER Controller,
182 IN PUSBHARDWAREDEVICE Device,
183 IN BOOLEAN IsRootHubDevice,
184 IN ULONG DeviceAddress)
185 {
186 NTSTATUS Status;
187 PCOMMON_DEVICE_EXTENSION DeviceExtension;
188 USHORT VendorID, DeviceID;
189 ULONG Dummy1;
190
191 DPRINT1("CHubController::Initialize\n");
192
193 //
194 // initialize members
195 //
196 m_Controller = Controller;
197 m_Hardware = Device;
198 m_IsRootHubDevice = IsRootHubDevice;
199 m_DeviceAddress = DeviceAddress;
200 m_DriverObject = DriverObject;
201 KeInitializeSpinLock(&m_Lock);
202 InitializeListHead(&m_UsbDeviceList);
203
204 //
205 // allocate device address bitmap buffer
206 //
207 m_DeviceAddressBitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, 16, TAG_USBEHCI);
208 if (!m_DeviceAddressBitmapBuffer)
209 {
210 //
211 // no memory
212 //
213 return STATUS_INSUFFICIENT_RESOURCES;
214 }
215
216 //
217 // initialize device address bitmap
218 //
219 RtlInitializeBitMap(&m_DeviceAddressBitmap, m_DeviceAddressBitmapBuffer, 128);
220 RtlClearAllBits(&m_DeviceAddressBitmap);
221
222
223 //
224 // create PDO
225 //
226 Status = CreatePDO(m_DriverObject, &m_HubControllerDeviceObject);
227 if (!NT_SUCCESS(Status))
228 {
229 //
230 // failed to create hub device object
231 //
232 return Status;
233 }
234
235 //
236 // get device extension
237 //
238 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_HubControllerDeviceObject->DeviceExtension;
239
240 //
241 // initialize device extension
242 //
243 DeviceExtension->IsFDO = FALSE;
244 DeviceExtension->IsHub = TRUE; //FIXME
245 DeviceExtension->Dispatcher = PDISPATCHIRP(this);
246
247 //
248 // intialize device descriptor
249 //
250 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
251 RtlMoveMemory(&m_DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
252
253 if (NT_SUCCESS(m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &Dummy1, &Dummy1)))
254 {
255 //
256 // update device descriptor
257 //
258 m_DeviceDescriptor.idVendor = VendorID;
259 m_DeviceDescriptor.idProduct = DeviceID;
260 m_DeviceDescriptor.bcdUSB = 0x200; //FIXME
261 }
262
263 //
264 // Set the SCE Callback that the Hardware Device will call on port status change
265 //
266 Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this);
267 //
268 // clear init flag
269 //
270 m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
271
272
273 return STATUS_SUCCESS;
274 }
275
276 //
277 // Queries the ports to see if there has been a device connected or removed.
278 //
279 BOOLEAN
280 CHubController::QueryStatusChageEndpoint(
281 PIRP Irp)
282 {
283 ULONG PortCount, PortId;
284 PIO_STACK_LOCATION IoStack;
285 USHORT PortStatus, PortChange;
286 PURB Urb;
287
288 //
289 // get current stack location
290 //
291 IoStack = IoGetCurrentIrpStackLocation(Irp);
292 ASSERT(IoStack);
293
294 //
295 // Get the Urb
296 //
297 Urb = (PURB)IoStack->Parameters.Others.Argument1;
298 ASSERT(Urb);
299
300 //
301 // Get the number of ports and check each one for device connected
302 //
303 m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
304 DPRINT1("SCE Request\n");
305 ((PULONG)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 0;
306 for (PortId = 0; PortId < PortCount; PortId++)
307 {
308 m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
309
310 DPRINT1("Port %d: Status %x, Change %x\n", PortId, PortStatus, PortChange);
311
312 //
313 // Loop the ports
314 //
315 if ((PortStatus & USB_PORT_STATUS_CONNECT) && (PortChange & USB_PORT_STATUS_CONNECT))
316 {
317 DPRINT1("Device is connected on port %d\n", PortId);
318 // Set the value for the port number
319 ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((PortId + 1) & 7);
320 }
321 }
322
323 //
324 // If there were changes then return TRUE
325 //
326 if (((PULONG)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] != 0)
327 return TRUE;
328
329 return FALSE;
330 }
331
332 //-----------------------------------------------------------------------------------------
333 NTSTATUS
334 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject)
335 {
336 //
337 // store controller object
338 //
339 *HubDeviceObject = m_HubControllerDeviceObject;
340
341 return STATUS_SUCCESS;
342 }
343 //-----------------------------------------------------------------------------------------
344 NTSTATUS
345 CHubController::GetHubControllerSymbolicLink(
346 ULONG BufferLength,
347 PVOID Buffer,
348 PULONG RequiredLength)
349 {
350 if (!m_InterfaceEnabled)
351 {
352 //
353 // device interface not yet enabled
354 //
355 return STATUS_UNSUCCESSFUL;
356 }
357
358 if (BufferLength < (ULONG)m_HubDeviceInterfaceString.Length - 8)
359 {
360 //
361 // buffer too small
362 // length is without '\??\'
363 //
364 *RequiredLength = m_HubDeviceInterfaceString.Length- 8;
365
366 //
367 // done
368 //
369 return STATUS_BUFFER_OVERFLOW;
370 }
371
372 //
373 // copy symbolic link
374 //
375 RtlCopyMemory(Buffer, &m_HubDeviceInterfaceString.Buffer[4], m_HubDeviceInterfaceString.Length - 8);
376
377 //
378 // store length, length is without '\??\'
379 //
380 *RequiredLength = m_HubDeviceInterfaceString.Length - 8;
381
382 //
383 // done
384 //
385 return STATUS_SUCCESS;
386 }
387
388 //-----------------------------------------------------------------------------------------
389 NTSTATUS
390 CHubController::HandlePnp(
391 IN PDEVICE_OBJECT DeviceObject,
392 IN OUT PIRP Irp)
393 {
394 PIO_STACK_LOCATION IoStack;
395 PCOMMON_DEVICE_EXTENSION DeviceExtension;
396 PDEVICE_CAPABILITIES DeviceCapabilities;
397 PPNP_BUS_INFORMATION BusInformation;
398 PDEVICE_RELATIONS DeviceRelations;
399 NTSTATUS Status;
400 ULONG Index = 0, Length;
401 USHORT VendorID, DeviceID;
402 ULONG HiSpeed, NumPorts;
403 WCHAR Buffer[300];
404 LPWSTR DeviceName;
405
406 //
407 // get device extension
408 //
409 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
410
411 //
412 // sanity check
413 //
414 ASSERT(DeviceExtension->IsFDO == FALSE);
415
416 //
417 // get current stack location
418 //
419 IoStack = IoGetCurrentIrpStackLocation(Irp);
420
421 switch(IoStack->MinorFunction)
422 {
423 case IRP_MN_START_DEVICE:
424 {
425 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
426 //
427 // register device interface
428 //
429 Status = SetDeviceInterface(TRUE);
430 break;
431 }
432 case IRP_MN_QUERY_ID:
433 {
434 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack->Parameters.QueryId.IdType);
435
436 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
437 {
438 if (m_Hardware)
439 {
440 //
441 // query device id
442 //
443 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
444
445 if (HiSpeed == 0x200)
446 {
447 //
448 // USB 2.0 hub
449 //
450 swprintf(Buffer, L"USB\\ROOT_HUB20");
451 }
452 else
453 {
454 //
455 // USB 1.1 hub
456 //
457 swprintf(Buffer, L"USB\\ROOT_HUB");
458 }
459
460 DPRINT1("Name %S\n", Buffer);
461
462 //
463 // calculate length
464 //
465 Length = (wcslen(Buffer) + 1);
466
467 //
468 // allocate buffer
469 //
470 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_USBEHCI);
471
472 if (!DeviceName)
473 {
474 //
475 // no memory
476 //
477 Status = STATUS_INSUFFICIENT_RESOURCES;
478 break;
479 }
480
481 //
482 // copy device name
483 //
484 wcscpy(DeviceName, Buffer);
485
486 //
487 // store result
488 //
489 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
490 Status = STATUS_SUCCESS;
491 break;
492 }
493 Status = STATUS_UNSUCCESSFUL;
494 PC_ASSERT(0);
495 break;
496 }
497
498 if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
499 {
500 if (m_Hardware)
501 {
502 //
503 // query device id
504 //
505 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
506
507 if (!NT_SUCCESS(Status))
508 {
509 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status);
510 VendorID = 0x8086;
511 DeviceID = 0x3A37;
512 }
513
514 if (HiSpeed == 0x200)
515 {
516 //
517 // USB 2.0 hub
518 //
519 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
520 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID, DeviceID) + 1;
521 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
522 }
523 else
524 {
525 //
526 // USB 1.1 hub
527 //
528 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
529 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID, DeviceID) + 1;
530 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB") + 1;
531 }
532
533 Buffer[Index] = UNICODE_NULL;
534 Index++;
535
536
537 DPRINT1("Name %S\n", Buffer);
538
539 //
540 // allocate buffer
541 //
542 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Index * sizeof(WCHAR), TAG_USBEHCI);
543
544 if (!DeviceName)
545 {
546 //
547 // no memory
548 //
549 Status = STATUS_INSUFFICIENT_RESOURCES;
550 break;
551 }
552
553 //
554 // copy device name
555 //
556 RtlMoveMemory(DeviceName, Buffer, Index * sizeof(WCHAR));
557
558 //
559 // store result
560 //
561 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
562 Status = STATUS_SUCCESS;
563 break;
564 }
565 }
566 Status = STATUS_SUCCESS;
567 break;
568 }
569 case IRP_MN_QUERY_CAPABILITIES:
570 {
571 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
572
573 DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
574
575 DeviceCapabilities->LockSupported = FALSE;
576 DeviceCapabilities->EjectSupported = FALSE;
577 DeviceCapabilities->Removable = FALSE;
578 DeviceCapabilities->DockDevice = FALSE;
579 DeviceCapabilities->UniqueID = FALSE;
580 DeviceCapabilities->SilentInstall = FALSE;
581 DeviceCapabilities->RawDeviceOK = FALSE;
582 DeviceCapabilities->SurpriseRemovalOK = FALSE;
583 DeviceCapabilities->Address = 0;
584 DeviceCapabilities->UINumber = 0;
585 DeviceCapabilities->DeviceD2 = 1;
586
587 /* FIXME */
588 DeviceCapabilities->HardwareDisabled = FALSE;
589 DeviceCapabilities->NoDisplayInUI = FALSE;
590 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
591 for (Index = 0; Index < PowerSystemMaximum; Index++)
592 DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
593 DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
594 DeviceCapabilities->D1Latency = 0;
595 DeviceCapabilities->D2Latency = 0;
596 DeviceCapabilities->D3Latency = 0;
597
598 Status = STATUS_SUCCESS;
599 break;
600 }
601 case IRP_MN_QUERY_INTERFACE:
602 {
603 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
604
605 //
606 // handle device interface requests
607 //
608 Status = HandleQueryInterface(IoStack);
609 break;
610 }
611 case IRP_MN_REMOVE_DEVICE:
612 {
613 DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
614
615 //
616 // deactivate device interface for BUS PDO
617 //
618 SetDeviceInterface(FALSE);
619
620 //
621 // complete the request first
622 //
623 Irp->IoStatus.Status = STATUS_SUCCESS;
624 IoCompleteRequest(Irp, IO_NO_INCREMENT);
625
626 //
627 // now delete device
628 //
629 IoDeleteDevice(m_HubControllerDeviceObject);
630
631 //
632 // nullify pointer
633 //
634 m_HubControllerDeviceObject = 0;
635
636 //
637 // done
638 //
639 return STATUS_SUCCESS;
640 }
641 case IRP_MN_QUERY_DEVICE_RELATIONS:
642 {
643 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack->Parameters.QueryDeviceRelations.Type);
644
645 if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
646 {
647 //
648 // allocate device relations
649 //
650 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_USBEHCI);
651 if (!DeviceRelations)
652 {
653 //
654 // no memory
655 //
656 Status = STATUS_INSUFFICIENT_RESOURCES;
657 break;
658 }
659
660 //
661 // initialize device relations
662 //
663 DeviceRelations->Count = 1;
664 DeviceRelations->Objects[0] = DeviceObject;
665 ObReferenceObject(DeviceObject);
666
667 //
668 // done
669 //
670 Status = STATUS_SUCCESS;
671 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
672 }
673 else
674 {
675 //
676 // not handled
677 //
678 Status = Irp->IoStatus.Status;
679 }
680 break;
681 }
682 case IRP_MN_QUERY_BUS_INFORMATION:
683 {
684 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
685
686 //
687 // allocate buffer for bus information
688 //
689 BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
690 if (BusInformation)
691 {
692 //
693 // copy BUS guid
694 //
695 RtlMoveMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_USB, sizeof(GUID));
696
697 //
698 // set bus type
699 //
700 BusInformation->LegacyBusType = PNPBus;
701 BusInformation->BusNumber = 0;
702
703 Status = STATUS_SUCCESS;
704 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
705 }
706 else
707 {
708 //
709 // no memory
710 //
711 Status = STATUS_INSUFFICIENT_RESOURCES;
712 }
713 break;
714 }
715 case IRP_MN_STOP_DEVICE:
716 {
717 DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
718 //
719 // stop device
720 //
721 Status = STATUS_SUCCESS;
722 break;
723 }
724 default:
725 {
726 //
727 // ignore request with default status
728 //
729 Status = Irp->IoStatus.Status;
730 break;
731 }
732 }
733
734 //
735 // complete request
736 //
737 Irp->IoStatus.Status = Status;
738 IoCompleteRequest(Irp, IO_NO_INCREMENT);
739
740 //
741 // done
742 //
743 return Status;
744 }
745
746 //-----------------------------------------------------------------------------------------
747 NTSTATUS
748 CHubController::HandlePower(
749 IN PDEVICE_OBJECT DeviceObject,
750 IN OUT PIRP Irp)
751 {
752 UNIMPLEMENTED
753 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
754 IoCompleteRequest(Irp, IO_NO_INCREMENT);
755 return STATUS_NOT_IMPLEMENTED;
756 }
757 //-----------------------------------------------------------------------------------------
758 NTSTATUS
759 CHubController::HandleBulkOrInterruptTransfer(
760 IN OUT PIRP Irp,
761 PURB Urb)
762 {
763 //
764 // First check if the request is for the Status Change Endpoint
765 //
766
767 //
768 // Is the Request for the root hub
769 //
770 if (Urb->UrbHeader.UsbdDeviceHandle == 0)
771 {
772 ASSERT(m_PendingSCEIrp == NULL);
773 if (QueryStatusChageEndpoint(Irp))
774 {
775 return STATUS_SUCCESS;
776 }
777
778 //
779 // Else pend the IRP, to be completed when a device connects or disconnects.
780 //
781 m_PendingSCEIrp = Irp;
782 IoMarkIrpPending(Irp);
783 return STATUS_PENDING;
784 }
785
786 UNIMPLEMENTED
787 return STATUS_NOT_IMPLEMENTED;
788 }
789
790 //-----------------------------------------------------------------------------------------
791 NTSTATUS
792 CHubController::HandleClassOther(
793 IN OUT PIRP Irp,
794 PURB Urb)
795 {
796 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
797 USHORT PortStatus = 0, PortChange = 0;
798 PUSHORT Buffer;
799 ULONG NumPort;
800 ULONG PortId;
801
802 //DPRINT1("CHubController::HandleClassOther> Request %x Value %x not implemented\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
803
804 //
805 // get number of ports available
806 //
807 Status = m_Hardware->GetDeviceDetails(NULL, NULL, &NumPort, NULL);
808 PC_ASSERT(Status == STATUS_SUCCESS);
809
810 //
811 // sanity check
812 //
813 PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < (USHORT)NumPort);
814
815 //
816 // port range reported start from 1 -n
817 // convert back port id so it matches the hardware
818 //
819 PortId = Urb->UrbControlVendorClassRequest.Index - 1;
820
821 //
822 // check request code
823 //
824 switch(Urb->UrbControlVendorClassRequest.Request)
825 {
826 case USB_REQUEST_GET_STATUS:
827 {
828 //
829 // sanity check
830 //
831 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength == sizeof(USHORT) * 2);
832 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
833
834 //
835 // get port status
836 //
837 Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
838
839 if (NT_SUCCESS(Status))
840 {
841 //
842 // request contains buffer of 2 ushort which are used from submitting port status and port change status
843 //
844 Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer;
845
846 //
847 // store status, then port change
848 //
849 *Buffer = PortStatus;
850 Buffer++;
851 *Buffer = PortChange;
852 }
853
854 //
855 // done
856 //
857 break;
858 }
859 case USB_REQUEST_CLEAR_FEATURE:
860 {
861 switch (Urb->UrbControlVendorClassRequest.Value)
862 {
863 case C_PORT_CONNECTION:
864 Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
865 break;
866 case C_PORT_RESET:
867 Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
868 break;
869 default:
870 DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
871 PC_ASSERT(FALSE);
872 break;
873 }
874
875 Status = STATUS_SUCCESS;
876 break;
877 }
878 case USB_REQUEST_SET_FEATURE:
879 {
880 //
881 // request set feature
882 //
883 switch(Urb->UrbControlVendorClassRequest.Value)
884 {
885 case PORT_ENABLE:
886 {
887 //
888 // port enable is a no-op for EHCI
889 //
890 Status = STATUS_SUCCESS;
891 break;
892 }
893
894 case PORT_SUSPEND:
895 {
896 //
897 // set suspend port feature
898 //
899 Status = m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
900 break;
901 }
902 case PORT_POWER:
903 {
904 //
905 // set power feature on port
906 //
907 Status = m_Hardware->SetPortFeature(PortId, PORT_POWER);
908 break;
909 }
910
911 case PORT_RESET:
912 {
913 //
914 // reset port feature
915 //
916 Status = m_Hardware->ResetPort(PortId);
917 PC_ASSERT(Status == STATUS_SUCCESS);
918 break;
919 }
920 default:
921 DPRINT1("Unsupported request id %x\n", Urb->UrbControlVendorClassRequest.Value);
922 PC_ASSERT(FALSE);
923 }
924 break;
925 }
926 default:
927 DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb->UrbControlVendorClassRequest.Request);
928 PC_ASSERT(0);
929 Status = STATUS_INVALID_DEVICE_REQUEST;
930 }
931
932
933 return STATUS_SUCCESS;
934 }
935
936 //-----------------------------------------------------------------------------------------
937 NTSTATUS
938 CHubController::HandleSelectConfiguration(
939 IN OUT PIRP Irp,
940 PURB Urb)
941 {
942 //
943 // sanity checks
944 //
945
946 //
947 // FIXME: support devices
948 //
949 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
950
951 //
952 // FIXME: support setting device to unconfigured state
953 //
954 PC_ASSERT(Urb->UrbSelectConfiguration.ConfigurationDescriptor);
955
956 //
957 // set device handle
958 //
959 Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)ROOTHUB2_CONFIGURATION_DESCRIPTOR;
960
961 //
962 // TODO: copy interface info
963 //
964 return STATUS_SUCCESS;
965 }
966
967 //-----------------------------------------------------------------------------------------
968 NTSTATUS
969 CHubController::HandleGetStatusFromDevice(
970 IN OUT PIRP Irp,
971 PURB Urb)
972 {
973 PUSHORT Status;
974
975 //
976 // sanity checks
977 //
978 PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
979 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
980 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
981 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
982
983 //
984 // get status buffer
985 //
986 Status = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
987
988 //
989 // FIXME need more flags ?
990 //
991 *Status = USB_PORT_STATUS_CONNECT;
992
993 //
994 // done
995 //
996 return STATUS_SUCCESS;
997 }
998
999 //-----------------------------------------------------------------------------------------
1000 NTSTATUS
1001 CHubController::HandleClassDevice(
1002 IN OUT PIRP Irp,
1003 IN OUT PURB Urb)
1004 {
1005 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1006 PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
1007 ULONG PortCount, Dummy2;
1008 USHORT Dummy1;
1009
1010 //
1011 // check class request type
1012 //
1013 switch(Urb->UrbControlVendorClassRequest.Request)
1014 {
1015 case USB_REQUEST_GET_DESCRIPTOR:
1016 {
1017 switch (Urb->UrbControlVendorClassRequest.Value >> 8)
1018 {
1019 case USB_DEVICE_CLASS_RESERVED: // FALL THROUGH
1020 case USB_DEVICE_CLASS_HUB:
1021 {
1022 //
1023 // sanity checks
1024 //
1025 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1026 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR));
1027
1028 //
1029 // get hub descriptor
1030 //
1031 UsbHubDescriptor = (PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer;
1032
1033 //
1034 // one hub is handled
1035 //
1036 UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
1037 Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR);
1038
1039 //
1040 // type should 0x29 according to msdn
1041 //
1042 UsbHubDescriptor->bDescriptorType = 0x29;
1043
1044 //
1045 // get port count
1046 //
1047 Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &PortCount, &Dummy2);
1048 PC_ASSERT(Status == STATUS_SUCCESS);
1049
1050 //
1051 // FIXME: retrieve values
1052 //
1053 UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount;
1054 UsbHubDescriptor->wHubCharacteristics = 0x0012;
1055 UsbHubDescriptor->bPowerOnToPowerGood = 0x01;
1056 UsbHubDescriptor->bHubControlCurrent = 0x00;
1057
1058 //
1059 // done
1060 //
1061 Status = STATUS_SUCCESS;
1062 break;
1063 }
1064 default:
1065 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb->UrbControlVendorClassRequest.Value >> 8);
1066 break;
1067 }
1068 break;
1069 }
1070 default:
1071 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb->UrbControlVendorClassRequest.Request);
1072 }
1073
1074 return Status;
1075 }
1076 //-----------------------------------------------------------------------------------------
1077 NTSTATUS
1078 CHubController::HandleGetDescriptor(
1079 IN OUT PIRP Irp,
1080 IN OUT PURB Urb)
1081 {
1082 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1083 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
1084 PUCHAR Buffer;
1085
1086 //
1087 // check descriptor type
1088 //
1089 switch(Urb->UrbControlDescriptorRequest.DescriptorType)
1090 {
1091 case USB_DEVICE_DESCRIPTOR_TYPE:
1092 {
1093 //
1094 // sanity check
1095 //
1096 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1097
1098 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1099 {
1100 //
1101 // copy root hub device descriptor
1102 //
1103 RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
1104 Status = STATUS_SUCCESS;
1105 break;
1106 }
1107 break;
1108 }
1109 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
1110 {
1111 //
1112 // sanity checks
1113 //
1114 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1115 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
1116
1117 //
1118 // FIXME: support devices
1119 //
1120 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
1121
1122 //
1123 // copy configuration descriptor template
1124 //
1125 C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR) == sizeof(USB_CONFIGURATION_DESCRIPTOR));
1126 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR));
1127
1128 //
1129 // get configuration descriptor, very retarded!
1130 //
1131 ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer;
1132
1133 //
1134 // check if buffer can hold interface and endpoint descriptor
1135 //
1136 if (ConfigurationDescriptor->wTotalLength > Urb->UrbControlDescriptorRequest.TransferBufferLength)
1137 {
1138 //
1139 // buffer too small
1140 //
1141 Status = STATUS_SUCCESS;
1142 break;
1143 }
1144
1145 //
1146 // copy interface descriptor template
1147 //
1148 Buffer = (PUCHAR)(ConfigurationDescriptor + 1);
1149 C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR) == sizeof(USB_INTERFACE_DESCRIPTOR));
1150 RtlCopyMemory(Buffer, ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR));
1151
1152 //
1153 // copy end point descriptor template
1154 //
1155 Buffer += sizeof(USB_INTERFACE_DESCRIPTOR);
1156 C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR) == sizeof(USB_ENDPOINT_DESCRIPTOR));
1157 RtlCopyMemory(Buffer, ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR));
1158
1159 //
1160 // done
1161 //
1162 Status = STATUS_SUCCESS;
1163 break;
1164 }
1165 default:
1166 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb->UrbControlDescriptorRequest.DescriptorType);
1167 break;
1168 }
1169
1170 //
1171 // done
1172 //
1173 return Status;
1174 }
1175
1176 //-----------------------------------------------------------------------------------------
1177 NTSTATUS
1178 CHubController::HandleDeviceControl(
1179 IN PDEVICE_OBJECT DeviceObject,
1180 IN OUT PIRP Irp)
1181 {
1182 PIO_STACK_LOCATION IoStack;
1183 PCOMMON_DEVICE_EXTENSION DeviceExtension;
1184 PURB Urb;
1185 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1186
1187 //
1188 // get current stack location
1189 //
1190 IoStack = IoGetCurrentIrpStackLocation(Irp);
1191
1192 //
1193 // get device extension
1194 //
1195 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1196
1197 //
1198 // determine which request should be performed
1199 //
1200 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
1201 {
1202 case IOCTL_INTERNAL_USB_SUBMIT_URB:
1203 {
1204 //
1205 // get urb
1206 //
1207 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1208 PC_ASSERT(Urb);
1209
1210 switch (Urb->UrbHeader.Function)
1211 {
1212 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
1213 Status = HandleGetDescriptor(Irp, Urb);
1214 break;
1215 case URB_FUNCTION_CLASS_DEVICE:
1216 Status = HandleClassDevice(Irp, Urb);
1217 break;
1218 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
1219 Status = HandleGetStatusFromDevice(Irp, Urb);
1220 break;
1221 case URB_FUNCTION_SELECT_CONFIGURATION:
1222 Status = HandleSelectConfiguration(Irp, Urb);
1223 break;
1224 case URB_FUNCTION_CLASS_OTHER:
1225 Status = HandleClassOther(Irp, Urb);
1226 break;
1227 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
1228 Status = HandleBulkOrInterruptTransfer(Irp, Urb);
1229 break;
1230 default:
1231 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
1232 break;
1233 }
1234 //
1235 // request completed
1236 //
1237 break;
1238 }
1239 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
1240 {
1241 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
1242
1243 if (IoStack->Parameters.Others.Argument1)
1244 {
1245 //
1246 // store object as device handle
1247 //
1248 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
1249 Status = STATUS_SUCCESS;
1250 }
1251 else
1252 {
1253 //
1254 // mis-behaving hub driver
1255 //
1256 Status = STATUS_INVALID_DEVICE_REQUEST;
1257 }
1258
1259 //
1260 // request completed
1261 //
1262 break;
1263 }
1264 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
1265 {
1266 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
1267
1268 //
1269 // this is the first request send, it delivers the PDO to the caller
1270 //
1271 if (IoStack->Parameters.Others.Argument1)
1272 {
1273 //
1274 // store root hub pdo object
1275 //
1276 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
1277 }
1278
1279 if (IoStack->Parameters.Others.Argument2)
1280 {
1281 //
1282 // documentation claims to deliver the hcd controller object, although it is wrong
1283 //
1284 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
1285 }
1286
1287 //
1288 // request completed
1289 //
1290 Status = STATUS_SUCCESS;
1291 break;
1292 }
1293 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
1294 {
1295 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
1296
1297 //
1298 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
1299 // requests this ioctl to deliver the number of presents.
1300
1301 if (IoStack->Parameters.Others.Argument1)
1302 {
1303 //
1304 // FIXME / verify: there is only one hub
1305 //
1306 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
1307 }
1308
1309 //
1310 // request completed
1311 //
1312 Status = STATUS_SUCCESS;
1313 Irp->IoStatus.Information = sizeof(ULONG);
1314 break;
1315 }
1316 default:
1317 {
1318 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
1319 IoStack->Parameters.DeviceIoControl.IoControlCode,
1320 IoStack->Parameters.DeviceIoControl.InputBufferLength,
1321 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
1322 break;
1323 }
1324 }
1325 if (Status != STATUS_PENDING)
1326 {
1327 Irp->IoStatus.Status = Status;
1328 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1329 }
1330
1331 return Status;
1332 }
1333
1334 //-----------------------------------------------------------------------------------------
1335 PUSBHARDWAREDEVICE
1336 CHubController::GetUsbHardware()
1337 {
1338 return m_Hardware;
1339 }
1340
1341 //-----------------------------------------------------------------------------------------
1342 ULONG
1343 CHubController::AcquireDeviceAddress()
1344 {
1345 KIRQL OldLevel;
1346 ULONG DeviceAddress;
1347
1348 //
1349 // acquire device lock
1350 //
1351 KeAcquireSpinLock(&m_Lock, &OldLevel);
1352
1353 //
1354 // find address
1355 //
1356 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
1357 if (DeviceAddress != MAXULONG)
1358 {
1359 //
1360 // reserve address
1361 //
1362 RtlSetBit(&m_DeviceAddressBitmap, DeviceAddress);
1363
1364 //
1365 // device addresses start from 0x1 - 0xFF
1366 //
1367 DeviceAddress++;
1368 }
1369
1370 //
1371 // release spin lock
1372 //
1373 KeReleaseSpinLock(&m_Lock, OldLevel);
1374
1375 //
1376 // return device address
1377 //
1378 return DeviceAddress;
1379 }
1380 //-----------------------------------------------------------------------------------------
1381 VOID
1382 CHubController::ReleaseDeviceAddress(
1383 ULONG DeviceAddress)
1384 {
1385 KIRQL OldLevel;
1386
1387 //
1388 // acquire device lock
1389 //
1390 KeAcquireSpinLock(&m_Lock, &OldLevel);
1391
1392 //
1393 // sanity check
1394 //
1395 PC_ASSERT(DeviceAddress != 0);
1396
1397 //
1398 // convert back to bit number
1399 //
1400 DeviceAddress--;
1401
1402 //
1403 // clear bit
1404 //
1405 RtlClearBit(&m_DeviceAddressBitmap, DeviceAddress);
1406
1407 //
1408 // release lock
1409 //
1410 KeReleaseSpinLock(&m_Lock, OldLevel);
1411 }
1412 //-----------------------------------------------------------------------------------------
1413 NTSTATUS
1414 CHubController::RemoveUsbDevice(
1415 PUSBDEVICE UsbDevice)
1416 {
1417 PUSBDEVICE_ENTRY DeviceEntry;
1418 PLIST_ENTRY Entry;
1419 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1420 KIRQL OldLevel;
1421
1422 //
1423 // acquire lock
1424 //
1425 KeAcquireSpinLock(&m_Lock, &OldLevel);
1426
1427 //
1428 // point to first entry
1429 //
1430 Entry = m_UsbDeviceList.Flink;
1431
1432 //
1433 // find matching entry
1434 //
1435 while(Entry != &m_UsbDeviceList)
1436 {
1437 //
1438 // get entry
1439 //
1440 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
1441
1442 //
1443 // is it current entry
1444 //
1445 if (DeviceEntry->Device == UsbDevice)
1446 {
1447 //
1448 // remove entry
1449 //
1450 RemoveEntryList(Entry);
1451
1452 //
1453 // free entry
1454 //
1455 ExFreePoolWithTag(DeviceEntry, TAG_USBEHCI);
1456
1457 //
1458 // done
1459 //
1460 Status = STATUS_SUCCESS;
1461 break;
1462 }
1463
1464 //
1465 // goto next device
1466 //
1467 Entry = Entry->Flink;
1468 }
1469
1470 //
1471 // release lock
1472 //
1473 KeReleaseSpinLock(&m_Lock, OldLevel);
1474
1475 //
1476 // return result
1477 //
1478 return Status;
1479 }
1480 //-----------------------------------------------------------------------------------------
1481 BOOLEAN
1482 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
1483 {
1484 PUSBDEVICE_ENTRY DeviceEntry;
1485 PLIST_ENTRY Entry;
1486 KIRQL OldLevel;
1487 BOOLEAN Result = FALSE;
1488
1489 //
1490 // acquire lock
1491 //
1492 KeAcquireSpinLock(&m_Lock, &OldLevel);
1493
1494 //
1495 // point to first entry
1496 //
1497 Entry = m_UsbDeviceList.Flink;
1498
1499 //
1500 // find matching entry
1501 //
1502 while(Entry != &m_UsbDeviceList)
1503 {
1504 //
1505 // get entry
1506 //
1507 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
1508
1509 //
1510 // is it current entry
1511 //
1512 if (DeviceEntry->Device == UsbDevice)
1513 {
1514 //
1515 // device is valid
1516 //
1517 Result = TRUE;
1518 break;
1519 }
1520
1521 //
1522 // goto next device
1523 //
1524 Entry = Entry->Flink;
1525 }
1526
1527 //
1528 // release lock
1529 //
1530 KeReleaseSpinLock(&m_Lock, OldLevel);
1531
1532 //
1533 // return result
1534 //
1535 return Result;
1536
1537 }
1538
1539 //-----------------------------------------------------------------------------------------
1540 NTSTATUS
1541 CHubController::AddUsbDevice(
1542 PUSBDEVICE UsbDevice)
1543 {
1544 PUSBDEVICE_ENTRY DeviceEntry;
1545 KIRQL OldLevel;
1546
1547 //
1548 // allocate device entry
1549 //
1550 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBEHCI);
1551 if (!DeviceEntry)
1552 {
1553 //
1554 // no memory
1555 //
1556 return STATUS_INSUFFICIENT_RESOURCES;
1557 }
1558
1559 //
1560 // initialize entry
1561 //
1562 DeviceEntry->Device = UsbDevice;
1563
1564 //
1565 // acquire lock
1566 //
1567 KeAcquireSpinLock(&m_Lock, &OldLevel);
1568
1569 //
1570 // insert entry
1571 //
1572 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
1573
1574 //
1575 // release spin lock
1576 //
1577 KeReleaseSpinLock(&m_Lock, OldLevel);
1578
1579 //
1580 // done
1581 //
1582 return STATUS_SUCCESS;
1583 }
1584
1585 //-----------------------------------------------------------------------------------------
1586 VOID
1587 CHubController::SetNotification(
1588 PVOID CallbackContext,
1589 PRH_INIT_CALLBACK CallbackRoutine)
1590 {
1591 KIRQL OldLevel;
1592
1593 //
1594 // acquire hub controller lock
1595 //
1596 KeAcquireSpinLock(&m_Lock, &OldLevel);
1597
1598 //
1599 // now set the callback routine and context of the hub
1600 //
1601 m_HubCallbackContext = CallbackContext;
1602 m_HubCallbackRoutine = CallbackRoutine;
1603
1604 //
1605 // release hub controller lock
1606 //
1607 KeReleaseSpinLock(&m_Lock, OldLevel);
1608 }
1609
1610 //=================================================================================================
1611 //
1612 // Generic Interface functions
1613 //
1614 VOID
1615 USB_BUSIFFN
1616 USBI_InterfaceReference(
1617 PVOID BusContext)
1618 {
1619 CHubController * Controller = (CHubController*)BusContext;
1620
1621 DPRINT1("USBH_InterfaceReference\n");
1622
1623 //
1624 // add reference
1625 //
1626 Controller->AddRef();
1627 }
1628
1629 VOID
1630 USB_BUSIFFN
1631 USBI_InterfaceDereference(
1632 PVOID BusContext)
1633 {
1634 CHubController * Controller = (CHubController*)BusContext;
1635
1636 DPRINT1("USBH_InterfaceDereference\n");
1637
1638 //
1639 // release
1640 //
1641 Controller->Release();
1642 }
1643 //=================================================================================================
1644 //
1645 // USB Hub Interface functions
1646 //
1647 NTSTATUS
1648 USB_BUSIFFN
1649 USBHI_CreateUsbDevice(
1650 PVOID BusContext,
1651 PUSB_DEVICE_HANDLE *NewDevice,
1652 PUSB_DEVICE_HANDLE HubDeviceHandle,
1653 USHORT PortStatus,
1654 USHORT PortNumber)
1655 {
1656 PUSBDEVICE NewUsbDevice;
1657 CHubController * Controller;
1658 NTSTATUS Status;
1659
1660 DPRINT1("USBHI_CreateUsbDevice\n");
1661
1662 //
1663 // first get hub controller
1664 //
1665 Controller = (CHubController *)BusContext;
1666
1667 //
1668 // sanity check
1669 //
1670 PC_ASSERT(Controller);
1671 PC_ASSERT(BusContext == HubDeviceHandle);
1672
1673 //
1674 // now allocate usb device
1675 //
1676 Status = CreateUSBDevice(&NewUsbDevice);
1677
1678 //
1679 // check for success
1680 //
1681 if (!NT_SUCCESS(Status))
1682 {
1683 //
1684 // release controller
1685 //
1686 Controller->Release();
1687 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
1688 return Status;
1689 }
1690
1691 //
1692 // now initialize device
1693 //
1694 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
1695
1696 //
1697 // check for success
1698 //
1699 if (!NT_SUCCESS(Status))
1700 {
1701 //
1702 // release usb device
1703 //
1704 NewUsbDevice->Release();
1705 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
1706 return Status;
1707 }
1708
1709 //
1710 // insert into list
1711 //
1712 Status = Controller->AddUsbDevice(NewUsbDevice);
1713 //
1714 // check for success
1715 //
1716 if (!NT_SUCCESS(Status))
1717 {
1718 //
1719 // release usb device
1720 //
1721 NewUsbDevice->Release();
1722
1723 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
1724 return Status;
1725 }
1726
1727 //
1728 // store the handle
1729 //
1730 *NewDevice = NewUsbDevice;
1731
1732 //
1733 // done
1734 //
1735 return STATUS_SUCCESS;
1736 }
1737
1738 NTSTATUS
1739 USB_BUSIFFN
1740 USBHI_InitializeUsbDevice(
1741 PVOID BusContext,
1742 PUSB_DEVICE_HANDLE DeviceHandle)
1743 {
1744 PUSBDEVICE UsbDevice;
1745 CHubController * Controller;
1746 ULONG DeviceAddress;
1747 NTSTATUS Status;
1748 ULONG Index = 0;
1749
1750 DPRINT1("USBHI_InitializeUsbDevice\n");
1751
1752 //
1753 // first get controller
1754 //
1755 Controller = (CHubController *)BusContext;
1756 PC_ASSERT(Controller);
1757
1758 //
1759 // get device object
1760 //
1761 UsbDevice = (PUSBDEVICE)DeviceHandle;
1762 PC_ASSERT(UsbDevice);
1763
1764 //
1765 // validate device handle
1766 //
1767 if (!Controller->ValidateUsbDevice(UsbDevice))
1768 {
1769 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
1770
1771 //
1772 // invalid device handle
1773 //
1774 return STATUS_DEVICE_NOT_CONNECTED;
1775 }
1776
1777 //
1778 // now reserve an address
1779 //
1780 DeviceAddress = Controller->AcquireDeviceAddress();
1781
1782 //
1783 // is the device address valid
1784 //
1785 if (DeviceAddress == MAXULONG)
1786 {
1787 //
1788 // failed to get an device address from the device address pool
1789 //
1790 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
1791 return STATUS_DEVICE_DATA_ERROR;
1792 }
1793
1794 do
1795 {
1796 //
1797 // now set the device address
1798 //
1799 Status = UsbDevice->SetDeviceAddress(DeviceAddress);
1800
1801 if (NT_SUCCESS(Status))
1802 break;
1803
1804 }while(Index++ < 3 );
1805
1806 //
1807 // check for failure
1808 //
1809 if (!NT_SUCCESS(Status))
1810 {
1811 //
1812 // failed to set device address
1813 //
1814 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
1815
1816 //
1817 // release address
1818 //
1819 Controller->ReleaseDeviceAddress(DeviceAddress);
1820
1821 //
1822 // return error
1823 //
1824 return STATUS_DEVICE_DATA_ERROR;
1825 }
1826
1827 //
1828 // done
1829 //
1830 return STATUS_SUCCESS;
1831 }
1832
1833 NTSTATUS
1834 USB_BUSIFFN
1835 USBHI_GetUsbDescriptors(
1836 PVOID BusContext,
1837 PUSB_DEVICE_HANDLE DeviceHandle,
1838 PUCHAR DeviceDescriptorBuffer,
1839 PULONG DeviceDescriptorBufferLength,
1840 PUCHAR ConfigDescriptorBuffer,
1841 PULONG ConfigDescriptorBufferLength)
1842 {
1843 PUSBDEVICE UsbDevice;
1844 CHubController * Controller;
1845
1846 DPRINT1("USBHI_GetUsbDescriptors\n");
1847
1848 //
1849 // sanity check
1850 //
1851 PC_ASSERT(DeviceDescriptorBuffer);
1852 PC_ASSERT(DeviceDescriptorBufferLength);
1853 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1854 PC_ASSERT(ConfigDescriptorBufferLength);
1855 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
1856
1857 //
1858 // first get controller
1859 //
1860 Controller = (CHubController *)BusContext;
1861 PC_ASSERT(Controller);
1862
1863
1864 //
1865 // get device object
1866 //
1867 UsbDevice = (PUSBDEVICE)DeviceHandle;
1868 PC_ASSERT(UsbDevice);
1869
1870 //
1871 // validate device handle
1872 //
1873 if (!Controller->ValidateUsbDevice(UsbDevice))
1874 {
1875 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
1876
1877 //
1878 // invalid device handle
1879 //
1880 return STATUS_DEVICE_NOT_CONNECTED;
1881 }
1882
1883 //
1884 // get device descriptor
1885 //
1886 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
1887
1888 //
1889 // store result length
1890 //
1891 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
1892
1893 //
1894 // get configuration descriptor
1895 //
1896 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
1897
1898 //
1899 // complete the request
1900 //
1901 return STATUS_SUCCESS;
1902 }
1903
1904 NTSTATUS
1905 USB_BUSIFFN
1906 USBHI_RemoveUsbDevice(
1907 PVOID BusContext,
1908 PUSB_DEVICE_HANDLE DeviceHandle,
1909 ULONG Flags)
1910 {
1911 PUSBDEVICE UsbDevice;
1912 CHubController * Controller;
1913 NTSTATUS Status;
1914
1915 DPRINT1("USBHI_RemoveUsbDevice\n");
1916
1917 //
1918 // first get controller
1919 //
1920 Controller = (CHubController *)BusContext;
1921 PC_ASSERT(Controller);
1922
1923 //
1924 // get device object
1925 //
1926 UsbDevice = (PUSBDEVICE)DeviceHandle;
1927 PC_ASSERT(UsbDevice);
1928
1929 //
1930 // validate device handle
1931 //
1932 if (!Controller->ValidateUsbDevice(UsbDevice))
1933 {
1934 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
1935
1936 //
1937 // invalid device handle
1938 //
1939 return STATUS_DEVICE_NOT_CONNECTED;
1940 }
1941
1942 //
1943 // check if there were flags passed
1944 //
1945 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
1946 {
1947 //
1948 // ignore flags for now
1949 //
1950 return STATUS_SUCCESS;
1951 }
1952
1953 //
1954 // remove device
1955 //
1956 Status = Controller->RemoveUsbDevice(UsbDevice);
1957 if (!NT_SUCCESS(Status))
1958 {
1959 //
1960 // invalid device handle
1961 //
1962 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
1963 PC_ASSERT(0);
1964 return STATUS_DEVICE_NOT_CONNECTED;
1965 }
1966
1967 //
1968 // release usb device
1969 //
1970 UsbDevice->Release();
1971
1972 //
1973 // done
1974 //
1975 return STATUS_SUCCESS;
1976 }
1977
1978 NTSTATUS
1979 USB_BUSIFFN
1980 USBHI_RestoreUsbDevice(
1981 PVOID BusContext,
1982 PUSB_DEVICE_HANDLE OldDeviceHandle,
1983 PUSB_DEVICE_HANDLE NewDeviceHandle)
1984 {
1985 UNIMPLEMENTED
1986 return STATUS_NOT_IMPLEMENTED;
1987 }
1988
1989 NTSTATUS
1990 USB_BUSIFFN
1991 USBHI_QueryDeviceInformation(
1992 PVOID BusContext,
1993 PUSB_DEVICE_HANDLE DeviceHandle,
1994 PVOID DeviceInformationBuffer,
1995 ULONG DeviceInformationBufferLength,
1996 PULONG LengthReturned)
1997 {
1998 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
1999 PUSBDEVICE UsbDevice;
2000 CHubController * Controller;
2001
2002 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
2003
2004 //
2005 // sanity check
2006 //
2007 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
2008 PC_ASSERT(DeviceInformationBuffer);
2009 PC_ASSERT(LengthReturned);
2010
2011 //
2012 // get controller object
2013 //
2014 Controller = (CHubController*)BusContext;
2015 PC_ASSERT(Controller);
2016
2017 //
2018 // get device object
2019 //
2020 UsbDevice = (PUSBDEVICE)DeviceHandle;
2021 PC_ASSERT(UsbDevice);
2022
2023 if (BusContext != DeviceHandle)
2024 {
2025 //
2026 // validate device handle
2027 //
2028 if (!Controller->ValidateUsbDevice(UsbDevice))
2029 {
2030 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
2031
2032 //
2033 // invalid device handle
2034 //
2035 return STATUS_DEVICE_NOT_CONNECTED;
2036 }
2037
2038 //
2039 // access information buffer
2040 //
2041 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2042
2043 //
2044 // initialize with default values
2045 //
2046 DeviceInfo->InformationLevel = 0;
2047 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2048 DeviceInfo->PortNumber = UsbDevice->GetPort();
2049 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
2050 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
2051 DeviceInfo->HubAddress = 0; //FIXME
2052 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
2053 DeviceInfo->DeviceType = UsbDevice->GetType();
2054 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2055
2056 //
2057 // get device descriptor
2058 //
2059 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
2060
2061 //
2062 // FIXME return pipe information
2063 //
2064
2065 //
2066 // store result length
2067 //
2068 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
2069
2070 return STATUS_SUCCESS;
2071 }
2072
2073 //
2074 // access information buffer
2075 //
2076 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2077
2078 //
2079 // initialize with default values
2080 //
2081 DeviceInfo->InformationLevel = 0;
2082 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2083 DeviceInfo->PortNumber = 0;
2084 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
2085 DeviceInfo->DeviceAddress = 0;
2086 DeviceInfo->HubAddress = 0; //FIXME
2087 DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
2088 DeviceInfo->DeviceType = Usb20Device; //FIXME
2089 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2090
2091 //
2092 // FIXME get device descriptor
2093 //
2094
2095 //
2096 // FIXME return pipe information
2097 //
2098
2099 //
2100 // store result length
2101 //
2102 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
2103
2104 //
2105 // done
2106 //
2107 return STATUS_SUCCESS;
2108 }
2109
2110 NTSTATUS
2111 USB_BUSIFFN
2112 USBHI_GetControllerInformation(
2113 PVOID BusContext,
2114 PVOID ControllerInformationBuffer,
2115 ULONG ControllerInformationBufferLength,
2116 PULONG LengthReturned)
2117 {
2118 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
2119
2120 DPRINT1("USBHI_GetControllerInformation\n");
2121
2122 //
2123 // sanity checks
2124 //
2125 PC_ASSERT(ControllerInformationBuffer);
2126 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
2127
2128 //
2129 // get controller info buffer
2130 //
2131 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
2132
2133 //
2134 // FIXME only version 0 is supported for now
2135 //
2136 PC_ASSERT(ControllerInfo->InformationLevel == 0);
2137
2138 //
2139 // fill in information
2140 //
2141 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
2142 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
2143 ControllerInfo->IsHighSpeedController = TRUE;
2144
2145 //
2146 // set length returned
2147 //
2148 *LengthReturned = ControllerInfo->ActualLength;
2149
2150 //
2151 // done
2152 //
2153 return STATUS_SUCCESS;
2154 }
2155
2156 NTSTATUS
2157 USB_BUSIFFN
2158 USBHI_ControllerSelectiveSuspend(
2159 PVOID BusContext,
2160 BOOLEAN Enable)
2161 {
2162 UNIMPLEMENTED
2163 return STATUS_NOT_IMPLEMENTED;
2164 }
2165
2166 NTSTATUS
2167 USB_BUSIFFN
2168 USBHI_GetExtendedHubInformation(
2169 PVOID BusContext,
2170 PDEVICE_OBJECT HubPhysicalDeviceObject,
2171 PVOID HubInformationBuffer,
2172 ULONG HubInformationBufferLength,
2173 PULONG LengthReturned)
2174 {
2175 PUSB_EXTHUB_INFORMATION_0 HubInfo;
2176 CHubController * Controller;
2177 PUSBHARDWAREDEVICE Hardware;
2178 ULONG Index;
2179 ULONG NumPort, Dummy2;
2180 USHORT Dummy1;
2181 NTSTATUS Status;
2182
2183 DPRINT1("USBHI_GetExtendedHubInformation\n");
2184
2185 //
2186 // sanity checks
2187 //
2188 PC_ASSERT(HubInformationBuffer);
2189 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
2190 PC_ASSERT(LengthReturned);
2191
2192 //
2193 // get hub controller
2194 //
2195 Controller = (CHubController *)BusContext;
2196 PC_ASSERT(Controller);
2197
2198 //
2199 // get usb hardware device
2200 //
2201 Hardware = Controller->GetUsbHardware();
2202
2203 //
2204 // retrieve number of ports
2205 //
2206 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
2207 if (!NT_SUCCESS(Status))
2208 {
2209 //
2210 // failed to get hardware details, ouch ;)
2211 //
2212 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
2213 return Status;
2214 }
2215
2216 //
2217 // get hub information buffer
2218 //
2219 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
2220
2221 //
2222 // initialize hub information
2223 //
2224 HubInfo->InformationLevel = 0;
2225
2226 //
2227 // store port count
2228 //
2229 HubInfo->NumberOfPorts = NumPort;
2230
2231 //
2232 // initialize port information
2233 //
2234 for(Index = 0; Index < NumPort; Index++)
2235 {
2236 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
2237 HubInfo->Port[Index].PortLabelNumber = Index + 1;
2238 HubInfo->Port[Index].VidOverride = 0;
2239 HubInfo->Port[Index].PidOverride = 0;
2240 HubInfo->Port[Index].PortAttributes = USB_PORTATTR_SHARED_USB2; //FIXME
2241 }
2242
2243 //
2244 // store result length
2245 //
2246 #ifdef _MSC_VER
2247 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
2248 #else
2249 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
2250 #endif
2251
2252 //
2253 // done
2254 //
2255 return STATUS_SUCCESS;
2256 }
2257
2258 NTSTATUS
2259 USB_BUSIFFN
2260 USBHI_GetRootHubSymbolicName(
2261 PVOID BusContext,
2262 PVOID HubSymNameBuffer,
2263 ULONG HubSymNameBufferLength,
2264 PULONG HubSymNameActualLength)
2265 {
2266 UNIMPLEMENTED
2267 return STATUS_NOT_IMPLEMENTED;
2268 }
2269
2270 PVOID
2271 USB_BUSIFFN
2272 USBHI_GetDeviceBusContext(
2273 PVOID HubBusContext,
2274 PVOID DeviceHandle)
2275 {
2276 UNIMPLEMENTED
2277 return NULL;
2278 }
2279
2280 NTSTATUS
2281 USB_BUSIFFN
2282 USBHI_Initialize20Hub(
2283 PVOID BusContext,
2284 PUSB_DEVICE_HANDLE HubDeviceHandle,
2285 ULONG TtCount)
2286 {
2287 UNIMPLEMENTED
2288 return STATUS_SUCCESS;
2289 }
2290
2291 NTSTATUS
2292 USB_BUSIFFN
2293 USBHI_RootHubInitNotification(
2294 PVOID BusContext,
2295 PVOID CallbackContext,
2296 PRH_INIT_CALLBACK CallbackRoutine)
2297 {
2298 CHubController * Controller;
2299
2300 DPRINT1("USBHI_RootHubInitNotification\n");
2301
2302 //
2303 // get controller object
2304 //
2305 Controller = (CHubController*)BusContext;
2306 PC_ASSERT(Controller);
2307
2308 //
2309 // set notification routine
2310 //
2311 Controller->SetNotification(CallbackContext, CallbackRoutine);
2312
2313 //
2314 // FIXME: determine when to perform callback
2315 //
2316 CallbackRoutine(CallbackContext);
2317
2318 //
2319 // done
2320 //
2321 return STATUS_SUCCESS;
2322 }
2323
2324 VOID
2325 USB_BUSIFFN
2326 USBHI_FlushTransfers(
2327 PVOID BusContext,
2328 PVOID DeviceHandle)
2329 {
2330 UNIMPLEMENTED
2331 }
2332
2333 VOID
2334 USB_BUSIFFN
2335 USBHI_SetDeviceHandleData(
2336 PVOID BusContext,
2337 PVOID DeviceHandle,
2338 PDEVICE_OBJECT UsbDevicePdo)
2339 {
2340 PUSBDEVICE UsbDevice;
2341 CHubController * Controller;
2342
2343 //
2344 // get controller
2345 //
2346 Controller = (CHubController *)BusContext;
2347 PC_ASSERT(Controller);
2348
2349 //
2350 // get device handle
2351 //
2352 UsbDevice = (PUSBDEVICE)DeviceHandle;
2353
2354 //
2355 // validate device handle
2356 //
2357 if (!Controller->ValidateUsbDevice(UsbDevice))
2358 {
2359 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
2360
2361 //
2362 // invalid handle
2363 //
2364 return;
2365 }
2366
2367 //
2368 // set device handle data
2369 //
2370 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
2371 }
2372
2373 //=================================================================================================
2374 //
2375 // USB Device Interface functions
2376 //
2377
2378 VOID
2379 USB_BUSIFFN
2380 USBDI_GetUSBDIVersion(
2381 PVOID BusContext,
2382 PUSBD_VERSION_INFORMATION VersionInformation,
2383 PULONG HcdCapabilites)
2384 {
2385 CHubController * Controller;
2386 PUSBHARDWAREDEVICE Device;
2387 ULONG Speed, Dummy2;
2388 USHORT Dummy1;
2389
2390 DPRINT1("USBDI_GetUSBDIVersion\n");
2391
2392 //
2393 // get controller
2394 //
2395 Controller = (CHubController*)BusContext;
2396
2397 //
2398 // get usb hardware
2399 //
2400 Device = Controller->GetUsbHardware();
2401 PC_ASSERT(Device);
2402
2403 if (VersionInformation)
2404 {
2405 //
2406 // windows xp supported
2407 //
2408 VersionInformation->USBDI_Version = 0x00000500;
2409
2410 //
2411 // get device speed
2412 //
2413 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
2414
2415 //
2416 // store speed details
2417 //
2418 VersionInformation->Supported_USB_Version = Speed;
2419 }
2420
2421 //
2422 // no flags supported
2423 //
2424 *HcdCapabilites = 0;
2425 }
2426
2427 NTSTATUS
2428 USB_BUSIFFN
2429 USBDI_QueryBusTime(
2430 PVOID BusContext,
2431 PULONG CurrentFrame)
2432 {
2433 UNIMPLEMENTED
2434 return STATUS_NOT_IMPLEMENTED;
2435 }
2436
2437 NTSTATUS
2438 USB_BUSIFFN
2439 USBDI_SubmitIsoOutUrb(
2440 PVOID BusContext,
2441 PURB Urb)
2442 {
2443 UNIMPLEMENTED
2444 return STATUS_NOT_IMPLEMENTED;
2445 }
2446
2447 NTSTATUS
2448 USB_BUSIFFN
2449 USBDI_QueryBusInformation(
2450 PVOID BusContext,
2451 ULONG Level,
2452 PVOID BusInformationBuffer,
2453 PULONG BusInformationBufferLength,
2454 PULONG BusInformationActualLength)
2455 {
2456 UNIMPLEMENTED
2457 return STATUS_NOT_IMPLEMENTED;
2458 }
2459
2460 BOOLEAN
2461 USB_BUSIFFN
2462 USBDI_IsDeviceHighSpeed(
2463 PVOID BusContext)
2464 {
2465 CHubController * Controller;
2466 PUSBHARDWAREDEVICE Device;
2467 ULONG Speed, Dummy2;
2468 USHORT Dummy1;
2469
2470 DPRINT1("USBDI_IsDeviceHighSpeed\n");
2471
2472 //
2473 // get controller
2474 //
2475 Controller = (CHubController*)BusContext;
2476
2477 //
2478 // get usb hardware
2479 //
2480 Device = Controller->GetUsbHardware();
2481 PC_ASSERT(Device);
2482
2483 //
2484 // get device speed
2485 //
2486 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
2487
2488 //
2489 // USB 2.0 equals 0x200
2490 //
2491 return (Speed == 0x200);
2492 }
2493
2494 NTSTATUS
2495 USB_BUSIFFN
2496 USBDI_EnumLogEntry(
2497 PVOID BusContext,
2498 ULONG DriverTag,
2499 ULONG EnumTag,
2500 ULONG P1,
2501 ULONG P2)
2502 {
2503 UNIMPLEMENTED
2504 return STATUS_NOT_IMPLEMENTED;
2505 }
2506
2507 NTSTATUS
2508 CHubController::HandleQueryInterface(
2509 PIO_STACK_LOCATION IoStack)
2510 {
2511 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
2512 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
2513 UNICODE_STRING GuidBuffer;
2514 NTSTATUS Status;
2515
2516 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
2517 {
2518 //
2519 // get request parameters
2520 //
2521 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
2522 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
2523
2524 //
2525 // check version
2526 //
2527 if (IoStack->Parameters.QueryInterface.Version >= 6)
2528 {
2529 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
2530
2531 //
2532 // version not supported
2533 //
2534 return STATUS_NOT_SUPPORTED;
2535 }
2536
2537 //
2538 // Interface version 0
2539 //
2540 if (IoStack->Parameters.QueryInterface.Version >= 0)
2541 {
2542 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
2543 InterfaceHub->BusContext = PVOID(this);
2544 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
2545 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
2546 }
2547
2548 //
2549 // Interface version 1
2550 //
2551 if (IoStack->Parameters.QueryInterface.Version >= 1)
2552 {
2553 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
2554 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
2555 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
2556 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
2557 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
2558 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
2559 }
2560
2561 //
2562 // Interface version 2
2563 //
2564 if (IoStack->Parameters.QueryInterface.Version >= 2)
2565 {
2566 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
2567 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
2568 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
2569 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
2570 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
2571 InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
2572
2573 }
2574
2575 //
2576 // Interface version 3
2577 //
2578 if (IoStack->Parameters.QueryInterface.Version >= 3)
2579 {
2580 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
2581 }
2582
2583 //
2584 // Interface version 4
2585 //
2586 if (IoStack->Parameters.QueryInterface.Version >= 4)
2587 {
2588 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
2589 }
2590
2591 //
2592 // Interface version 5
2593 //
2594 if (IoStack->Parameters.QueryInterface.Version >= 5)
2595 {
2596 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
2597 }
2598
2599 //
2600 // request completed
2601 //
2602 return STATUS_SUCCESS;
2603 }
2604 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
2605 {
2606 //
2607 // get request parameters
2608 //
2609 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
2610 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
2611
2612 //
2613 // check version
2614 //
2615 if (IoStack->Parameters.QueryInterface.Version >= 3)
2616 {
2617 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
2618
2619 //
2620 // version not supported
2621 //
2622 return STATUS_NOT_SUPPORTED;
2623 }
2624
2625 //
2626 // interface version 0
2627 //
2628 if (IoStack->Parameters.QueryInterface.Version >= 0)
2629 {
2630 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
2631 InterfaceDI->BusContext = PVOID(this);
2632 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
2633 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
2634 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
2635 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
2636 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
2637 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
2638 }
2639
2640 //
2641 // interface version 1
2642 //
2643 if (IoStack->Parameters.QueryInterface.Version >= 1)
2644 {
2645 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
2646 }
2647
2648 //
2649 // interface version 2
2650 //
2651 if (IoStack->Parameters.QueryInterface.Version >= 2)
2652 {
2653 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
2654 }
2655
2656 //
2657 // request completed
2658 //
2659 return STATUS_SUCCESS;
2660 }
2661 else
2662 {
2663 //
2664 // convert guid to string
2665 //
2666 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
2667 if (NT_SUCCESS(Status))
2668 {
2669 //
2670 // print interface
2671 //
2672 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
2673
2674 //
2675 // free guid buffer
2676 //
2677 RtlFreeUnicodeString(&GuidBuffer);
2678 }
2679 }
2680 return STATUS_NOT_SUPPORTED;
2681 }
2682
2683 NTSTATUS
2684 CHubController::SetDeviceInterface(
2685 BOOLEAN Enable)
2686 {
2687 NTSTATUS Status = STATUS_SUCCESS;
2688
2689 if (Enable)
2690 {
2691 //
2692 // register device interface
2693 //
2694 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
2695
2696 if (NT_SUCCESS(Status))
2697 {
2698 //
2699 // now enable the device interface
2700 //
2701 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
2702
2703 //
2704 // enable interface
2705 //
2706 m_InterfaceEnabled = TRUE;
2707 }
2708 }
2709 else if (m_InterfaceEnabled)
2710 {
2711 //
2712 // disable device interface
2713 //
2714 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
2715
2716 if (NT_SUCCESS(Status))
2717 {
2718 //
2719 // now delete interface string
2720 //
2721 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
2722 }
2723
2724 //
2725 // disable interface
2726 //
2727 m_InterfaceEnabled = FALSE;
2728 }
2729
2730 //
2731 // done
2732 //
2733 return Status;
2734 }
2735
2736 NTSTATUS
2737 CHubController::CreatePDO(
2738 PDRIVER_OBJECT DriverObject,
2739 PDEVICE_OBJECT * OutDeviceObject)
2740 {
2741 WCHAR CharDeviceName[64];
2742 NTSTATUS Status;
2743 ULONG UsbDeviceNumber = 0;
2744 UNICODE_STRING DeviceName;
2745
2746 while (TRUE)
2747 {
2748 //
2749 // construct device name
2750 //
2751 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
2752
2753 //
2754 // initialize device name
2755 //
2756 RtlInitUnicodeString(&DeviceName, CharDeviceName);
2757
2758 //
2759 // create device
2760 //
2761 Status = IoCreateDevice(DriverObject,
2762 sizeof(COMMON_DEVICE_EXTENSION),
2763 &DeviceName,
2764 FILE_DEVICE_CONTROLLER,
2765 0,
2766 FALSE,
2767 OutDeviceObject);
2768
2769 /* check for success */
2770 if (NT_SUCCESS(Status))
2771 break;
2772
2773 //
2774 // is there a device object with that same name
2775 //
2776 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
2777 {
2778 //
2779 // Try the next name
2780 //
2781 UsbDeviceNumber++;
2782 continue;
2783 }
2784
2785 //
2786 // bail out on other errors
2787 //
2788 if (!NT_SUCCESS(Status))
2789 {
2790 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
2791 return Status;
2792 }
2793 }
2794
2795 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
2796
2797 /* done */
2798 return Status;
2799 }
2800
2801
2802
2803 NTSTATUS
2804 CreateHubController(
2805 PHUBCONTROLLER *OutHcdController)
2806 {
2807 PHUBCONTROLLER This;
2808
2809 //
2810 // allocate controller
2811 //
2812 This = new(NonPagedPool, TAG_USBEHCI) CHubController(0);
2813 if (!This)
2814 {
2815 //
2816 // failed to allocate
2817 //
2818 return STATUS_INSUFFICIENT_RESOURCES;
2819 }
2820
2821 //
2822 // add reference count
2823 //
2824 This->AddRef();
2825
2826 //
2827 // return result
2828 //
2829 *OutHcdController = (PHUBCONTROLLER)This;
2830
2831 //
2832 // done
2833 //
2834 return STATUS_SUCCESS;
2835 }
2836
2837 VOID StatusChangeEndpointCallBack(PVOID Context)
2838 {
2839 CHubController* This;
2840 PIRP Irp;
2841 This = (CHubController*)Context;
2842
2843 ASSERT(This);
2844
2845 DPRINT1("SCE Notification!\n");
2846 Irp = This->m_PendingSCEIrp;
2847 This->m_PendingSCEIrp = NULL;
2848
2849 This->QueryStatusChageEndpoint(Irp);
2850
2851 Irp->IoStatus.Status = STATUS_SUCCESS;
2852 Irp->IoStatus.Information = 0;
2853 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2854 }