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