[USBEHCI]
[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 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
794
795 //
796 // get device
797 //
798 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
799
800 return UsbDevice->SubmitIrp(Irp);
801 }
802
803 //-----------------------------------------------------------------------------------------
804 NTSTATUS
805 CHubController::HandleBulkOrInterruptTransfer(
806 IN OUT PIRP Irp,
807 PURB Urb)
808 {
809 PUSBDEVICE UsbDevice;
810 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
811 //
812 // First check if the request is for the Status Change Endpoint
813 //
814
815 //
816 // Is the Request for the root hub
817 //
818 if (Urb->UrbHeader.UsbdDeviceHandle == 0)
819 {
820 ASSERT(m_PendingSCEIrp == NULL);
821 if (QueryStatusChageEndpoint(Irp))
822 {
823 StatusChangeEndpointCallBack(this);
824 return STATUS_SUCCESS;
825 }
826
827 //
828 // Else pend the IRP, to be completed when a device connects or disconnects.
829 //
830 DPRINT1("Pending SCE Irp\n");;
831 m_PendingSCEIrp = Irp;
832 IoMarkIrpPending(Irp);
833 return STATUS_PENDING;
834 }
835
836 //
837 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
838 //
839 EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
840
841 //
842 // sanity checks
843 //
844 ASSERT(EndPointDesc);
845 ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK || (EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT);
846
847 //
848 // check if this is a valid usb device handle
849 //
850 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
851
852 //
853 // get device
854 //
855 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
856
857 return UsbDevice->SubmitIrp(Irp);
858 }
859
860 //-----------------------------------------------------------------------------------------
861 NTSTATUS
862 CHubController::HandleClassOther(
863 IN OUT PIRP Irp,
864 PURB Urb)
865 {
866 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
867 USHORT PortStatus = 0, PortChange = 0;
868 PUSHORT Buffer;
869 ULONG NumPort;
870 ULONG PortId;
871
872 DPRINT("CHubController::HandleClassOther> Request %x Value %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
873
874 //
875 // get number of ports available
876 //
877 Status = m_Hardware->GetDeviceDetails(NULL, NULL, &NumPort, NULL);
878 PC_ASSERT(Status == STATUS_SUCCESS);
879
880 //
881 // sanity check
882 //
883 PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < (USHORT)NumPort);
884
885 //
886 // port range reported start from 1 -n
887 // convert back port id so it matches the hardware
888 //
889 PortId = Urb->UrbControlVendorClassRequest.Index - 1;
890
891 //
892 // check request code
893 //
894 switch(Urb->UrbControlVendorClassRequest.Request)
895 {
896 case USB_REQUEST_GET_STATUS:
897 {
898 //
899 // sanity check
900 //
901 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength == sizeof(USHORT) * 2);
902 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
903
904 //
905 // get port status
906 //
907 Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
908
909 if (NT_SUCCESS(Status))
910 {
911 //
912 // request contains buffer of 2 ushort which are used from submitting port status and port change status
913 //
914 DPRINT("PortId %x PortStatus %x PortChange %x\n", PortId, PortStatus, PortChange);
915 Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer;
916
917 //
918 // store status, then port change
919 //
920 *Buffer = PortStatus;
921 Buffer++;
922 *Buffer = PortChange;
923 }
924
925 //
926 // done
927 //
928 break;
929 }
930 case USB_REQUEST_CLEAR_FEATURE:
931 {
932 switch (Urb->UrbControlVendorClassRequest.Value)
933 {
934 case C_PORT_CONNECTION:
935 Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
936 break;
937 case C_PORT_RESET:
938 Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
939 break;
940 default:
941 DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
942 break;
943 }
944
945 Status = STATUS_SUCCESS;
946 break;
947 }
948 case USB_REQUEST_SET_FEATURE:
949 {
950 //
951 // request set feature
952 //
953 switch(Urb->UrbControlVendorClassRequest.Value)
954 {
955 case PORT_ENABLE:
956 {
957 //
958 // port enable is a no-op for EHCI
959 //
960 Status = STATUS_SUCCESS;
961 break;
962 }
963
964 case PORT_SUSPEND:
965 {
966 //
967 // set suspend port feature
968 //
969 Status = m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
970 break;
971 }
972 case PORT_POWER:
973 {
974 //
975 // set power feature on port
976 //
977 Status = m_Hardware->SetPortFeature(PortId, PORT_POWER);
978 break;
979 }
980
981 case PORT_RESET:
982 {
983 //
984 // reset port feature
985 //
986 Status = m_Hardware->SetPortFeature(PortId, PORT_RESET);
987 PC_ASSERT(Status == STATUS_SUCCESS);
988 break;
989 }
990 default:
991 DPRINT1("Unsupported request id %x\n", Urb->UrbControlVendorClassRequest.Value);
992 PC_ASSERT(FALSE);
993 }
994 break;
995 }
996 default:
997 DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb->UrbControlVendorClassRequest.Request);
998 PC_ASSERT(0);
999 Status = STATUS_INVALID_DEVICE_REQUEST;
1000 }
1001 return Status;
1002 }
1003
1004 //-----------------------------------------------------------------------------------------
1005 NTSTATUS
1006 CHubController::HandleSelectConfiguration(
1007 IN OUT PIRP Irp,
1008 PURB Urb)
1009 {
1010 PUSBDEVICE UsbDevice;
1011 PUSBD_INTERFACE_INFORMATION InterfaceInfo;
1012
1013 //
1014 // is the request for the Root Hub
1015 //
1016 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1017 {
1018 //
1019 // FIXME: support setting device to unconfigured state
1020 //
1021 PC_ASSERT(Urb->UrbSelectConfiguration.ConfigurationDescriptor);
1022
1023 //
1024 // set device handle
1025 //
1026 Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&ROOTHUB2_CONFIGURATION_DESCRIPTOR;
1027
1028 //
1029 // copy interface info
1030 //
1031 InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
1032
1033 InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&ROOTHUB2_INTERFACE_DESCRIPTOR;
1034 InterfaceInfo->Class = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceClass;
1035 InterfaceInfo->SubClass = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceSubClass;
1036 InterfaceInfo->Protocol = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceProtocol;
1037 InterfaceInfo->Reserved = 0;
1038
1039 //
1040 // sanity check
1041 //
1042 PC_ASSERT(InterfaceInfo->NumberOfPipes == 1);
1043
1044 //
1045 // copy pipe info
1046 //
1047 InterfaceInfo->Pipes[0].MaximumPacketSize = ROOTHUB2_ENDPOINT_DESCRIPTOR.wMaxPacketSize;
1048 InterfaceInfo->Pipes[0].EndpointAddress = ROOTHUB2_ENDPOINT_DESCRIPTOR.bEndpointAddress;
1049 InterfaceInfo->Pipes[0].Interval = ROOTHUB2_ENDPOINT_DESCRIPTOR.bInterval;
1050 InterfaceInfo->Pipes[0].PipeType = (USBD_PIPE_TYPE)(ROOTHUB2_ENDPOINT_DESCRIPTOR.bmAttributes & USB_ENDPOINT_TYPE_MASK);
1051 InterfaceInfo->Pipes[0].PipeHandle = (PVOID)&ROOTHUB2_ENDPOINT_DESCRIPTOR;
1052
1053 return STATUS_SUCCESS;
1054 }
1055 else
1056 {
1057 //
1058 // check if this is a valid usb device handle
1059 //
1060 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1061
1062 //
1063 // get device
1064 //
1065 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1066
1067 //
1068 // select configuration
1069 //
1070 return UsbDevice->SelectConfiguration(Urb->UrbSelectConfiguration.ConfigurationDescriptor, &Urb->UrbSelectConfiguration.Interface, &Urb->UrbSelectConfiguration.ConfigurationHandle);
1071 }
1072 }
1073
1074 //-----------------------------------------------------------------------------------------
1075 NTSTATUS
1076 CHubController::HandleSelectInterface(
1077 IN OUT PIRP Irp,
1078 PURB Urb)
1079 {
1080 PUSBDEVICE UsbDevice;
1081
1082 //
1083 // sanity check
1084 //
1085 PC_ASSERT(Urb->UrbSelectInterface.ConfigurationHandle);
1086
1087 //
1088 // is the request for the Root Hub
1089 //
1090 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1091 {
1092 //
1093 // no op for root hub
1094 //
1095 return STATUS_SUCCESS;
1096 }
1097 else
1098 {
1099 //
1100 // check if this is a valid usb device handle
1101 //
1102 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1103
1104 //
1105 // get device
1106 //
1107 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1108
1109 //
1110 // select interface
1111 //
1112 return UsbDevice->SelectInterface(Urb->UrbSelectInterface.ConfigurationHandle, &Urb->UrbSelectInterface.Interface);
1113 }
1114 }
1115
1116 //-----------------------------------------------------------------------------------------
1117 NTSTATUS
1118 CHubController::HandleGetStatusFromDevice(
1119 IN OUT PIRP Irp,
1120 PURB Urb)
1121 {
1122 PUSHORT DeviceStatus;
1123 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1124 NTSTATUS Status;
1125 PUSBDEVICE UsbDevice;
1126
1127 //
1128 // sanity checks
1129 //
1130 PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1131 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
1132 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
1133
1134 //
1135 // get status buffer
1136 //
1137 DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
1138
1139
1140 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1141 {
1142 //
1143 // FIXME need more flags ?
1144 //
1145 *DeviceStatus = USB_PORT_STATUS_CONNECT;
1146 return STATUS_SUCCESS;
1147 }
1148
1149 //
1150 // check if this is a valid usb device handle
1151 //
1152 ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1153
1154 //
1155 // get device
1156 //
1157 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1158
1159
1160 //
1161 // generate setup packet
1162 //
1163 CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
1164 CtrlSetup.wValue.LowByte = 0;
1165 CtrlSetup.wValue.HiByte = 0;
1166 CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1167 CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
1168 CtrlSetup.bmRequestType.B = 0x80;
1169
1170 //
1171 // submit setup packet
1172 //
1173 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1174 ASSERT(Status == STATUS_SUCCESS);
1175 DPRINT1("CHubController::HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
1176
1177 //
1178 // done
1179 //
1180 return Status;
1181 }
1182
1183 //-----------------------------------------------------------------------------------------
1184 NTSTATUS
1185 CHubController::HandleClassDevice(
1186 IN OUT PIRP Irp,
1187 IN OUT PURB Urb)
1188 {
1189 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1190 PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
1191 ULONG PortCount, Dummy2;
1192 USHORT Dummy1;
1193 PUSBDEVICE UsbDevice;
1194 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1195
1196 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
1197
1198 //
1199 // check class request type
1200 //
1201 switch(Urb->UrbControlVendorClassRequest.Request)
1202 {
1203 case USB_REQUEST_GET_STATUS:
1204 {
1205 //
1206 // check if this is a valid usb device handle
1207 //
1208 ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1209
1210 //
1211 // get device
1212 //
1213 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1214
1215
1216 //
1217 // generate setup packet
1218 //
1219 CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
1220 CtrlSetup.wValue.LowByte = Urb->UrbControlVendorClassRequest.Index;
1221 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1222 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1223 CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
1224 CtrlSetup.bmRequestType.B = 0xA0;
1225
1226 //
1227 // submit setup packet
1228 //
1229 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1230 ASSERT(Status == STATUS_SUCCESS);
1231 break;
1232 }
1233 case USB_REQUEST_GET_DESCRIPTOR:
1234 {
1235 switch (Urb->UrbControlVendorClassRequest.Value >> 8)
1236 {
1237 case USB_DEVICE_CLASS_RESERVED: // FALL THROUGH
1238 case USB_DEVICE_CLASS_HUB:
1239 {
1240 //
1241 // sanity checks
1242 //
1243 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1244 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR));
1245
1246 //
1247 // get hub descriptor
1248 //
1249 UsbHubDescriptor = (PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer;
1250
1251 //
1252 // one hub is handled
1253 //
1254 UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
1255 Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR);
1256
1257 //
1258 // type should 0x29 according to msdn
1259 //
1260 UsbHubDescriptor->bDescriptorType = 0x29;
1261
1262 //
1263 // get port count
1264 //
1265 Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &PortCount, &Dummy2);
1266 PC_ASSERT(Status == STATUS_SUCCESS);
1267
1268 //
1269 // FIXME: retrieve values
1270 //
1271 UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount;
1272 UsbHubDescriptor->wHubCharacteristics = 0x00;
1273 UsbHubDescriptor->bPowerOnToPowerGood = 0x01;
1274 UsbHubDescriptor->bHubControlCurrent = 0x00;
1275
1276 //
1277 // done
1278 //
1279 Status = STATUS_SUCCESS;
1280 break;
1281 }
1282 default:
1283 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb->UrbControlVendorClassRequest.Value >> 8);
1284 break;
1285 }
1286 break;
1287 }
1288 default:
1289 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb->UrbControlVendorClassRequest.Request);
1290 }
1291
1292 return Status;
1293 }
1294
1295 //-----------------------------------------------------------------------------------------
1296 NTSTATUS
1297 CHubController::HandleGetDescriptorFromInterface(
1298 IN OUT PIRP Irp,
1299 IN OUT PURB Urb)
1300 {
1301 PUSBDEVICE UsbDevice;
1302 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1303 NTSTATUS Status;
1304
1305 //
1306 // sanity check
1307 //
1308 ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
1309 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1310
1311 //
1312 // check if this is a valid usb device handle
1313 //
1314 ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1315
1316 //
1317 // get device
1318 //
1319 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1320
1321 //
1322 // generate setup packet
1323 //
1324 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1325 CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1326 CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1327 CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1328 CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1329 CtrlSetup.bmRequestType.B = 0x81;
1330
1331 //
1332 // submit setup packet
1333 //
1334 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1335 ASSERT(Status == STATUS_SUCCESS);
1336
1337 //
1338 // done
1339 //
1340 return Status;
1341 }
1342
1343 //-----------------------------------------------------------------------------------------
1344 NTSTATUS
1345 CHubController::HandleGetDescriptor(
1346 IN OUT PIRP Irp,
1347 IN OUT PURB Urb)
1348 {
1349 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1350 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
1351 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1352 PUCHAR Buffer;
1353 PUSBDEVICE UsbDevice;
1354 ULONG Length;
1355
1356 DPRINT("CHubController::HandleGetDescriptor\n");
1357
1358 //
1359 // check descriptor type
1360 //
1361 switch(Urb->UrbControlDescriptorRequest.DescriptorType)
1362 {
1363 case USB_DEVICE_DESCRIPTOR_TYPE:
1364 {
1365 //
1366 // sanity check
1367 //
1368 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1369 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1370
1371 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1372 {
1373 //
1374 // copy root hub device descriptor
1375 //
1376 RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
1377 Status = STATUS_SUCCESS;
1378 }
1379 else
1380 {
1381 //
1382 // check if this is a valid usb device handle
1383 //
1384 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1385
1386 //
1387 // get device
1388 //
1389 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1390
1391 //
1392 // retrieve device descriptor from device
1393 //
1394 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
1395 Status = STATUS_SUCCESS;
1396 }
1397 break;
1398 }
1399 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
1400 {
1401 //
1402 // sanity checks
1403 //
1404 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1405 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
1406
1407 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1408 {
1409 //
1410 // request is for the root bus controller
1411 //
1412 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR));
1413
1414 //
1415 // get configuration descriptor, very retarded!
1416 //
1417 ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer;
1418
1419 //
1420 // check if buffer can hold interface and endpoint descriptor
1421 //
1422 if (ConfigurationDescriptor->wTotalLength > Urb->UrbControlDescriptorRequest.TransferBufferLength)
1423 {
1424 //
1425 // buffer too small
1426 //
1427 Status = STATUS_SUCCESS;
1428 ASSERT(FALSE);
1429 break;
1430 }
1431
1432 //
1433 // copy interface descriptor template
1434 //
1435 Buffer = (PUCHAR)(ConfigurationDescriptor + 1);
1436 RtlCopyMemory(Buffer, &ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR));
1437
1438 //
1439 // copy end point descriptor template
1440 //
1441 Buffer += sizeof(USB_INTERFACE_DESCRIPTOR);
1442 RtlCopyMemory(Buffer, &ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR));
1443
1444 //
1445 // done
1446 //
1447 Status = STATUS_SUCCESS;
1448
1449 }
1450 else
1451 {
1452 //
1453 // check if this is a valid usb device handle
1454 //
1455 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1456
1457 //
1458 // get device
1459 //
1460 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1461
1462 if (sizeof(USB_CONFIGURATION_DESCRIPTOR) > Urb->UrbControlDescriptorRequest.TransferBufferLength)
1463 {
1464 //
1465 // buffer too small
1466 //
1467 Urb->UrbControlDescriptorRequest.TransferBufferLength = UsbDevice->GetConfigurationDescriptorsLength();
1468
1469 //
1470 // bail out
1471 //
1472 Status = STATUS_SUCCESS;
1473 break;
1474 }
1475
1476 //
1477 // perform work in IUSBDevice
1478 //
1479 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength, &Length);
1480
1481 //
1482 // sanity check
1483 //
1484 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= Length);
1485
1486 //
1487 // store result size
1488 //
1489 Urb->UrbControlDescriptorRequest.TransferBufferLength = Length;
1490 Status = STATUS_SUCCESS;
1491 }
1492 break;
1493 }
1494 case USB_STRING_DESCRIPTOR_TYPE:
1495 {
1496 //
1497 // sanity check
1498 //
1499 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1500 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
1501
1502
1503 //
1504 // check if this is a valid usb device handle
1505 //
1506 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1507
1508 //
1509 // get device
1510 //
1511 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1512
1513 //
1514 // generate setup packet
1515 //
1516 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1517 CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1518 CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1519 CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1520 CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1521 CtrlSetup.bmRequestType.B = 0x80;
1522
1523 //
1524 // submit setup packet
1525 //
1526 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1527 break;
1528 }
1529 default:
1530 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb->UrbControlDescriptorRequest.DescriptorType);
1531 break;
1532 }
1533
1534 //
1535 // done
1536 //
1537 return Status;
1538 }
1539
1540 //-----------------------------------------------------------------------------------------
1541 NTSTATUS
1542 CHubController::HandleClassEndpoint(
1543 IN OUT PIRP Irp,
1544 IN OUT PURB Urb)
1545 {
1546 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1547 NTSTATUS Status;
1548 PUSBDEVICE UsbDevice;
1549
1550 //
1551 // sanity check
1552 //
1553 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1554 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1555 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1556
1557 //
1558 // check if this is a valid usb device handle
1559 //
1560 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1561
1562 //
1563 // get device
1564 //
1565 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1566
1567
1568 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1569 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
1570 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
1571 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
1572 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1573 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
1574 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1575 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
1576 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
1577
1578 //
1579 // initialize setup packet
1580 //
1581 CtrlSetup.bmRequestType.B = 0xa2; //FIXME: Const.
1582 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1583 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1584 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1585 CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
1586
1587 //
1588 // issue request
1589 //
1590 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1591
1592 //
1593 // assert on failure
1594 //
1595 PC_ASSERT(NT_SUCCESS(Status));
1596
1597
1598 //
1599 // done
1600 //
1601 return Status;
1602 }
1603
1604 //-----------------------------------------------------------------------------------------
1605 NTSTATUS
1606 CHubController::HandleClassInterface(
1607 IN OUT PIRP Irp,
1608 IN OUT PURB Urb)
1609 {
1610 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1611 NTSTATUS Status;
1612 PUSBDEVICE UsbDevice;
1613
1614 //
1615 // sanity check
1616 //
1617 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1618 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1619 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1620
1621 //
1622 // check if this is a valid usb device handle
1623 //
1624 PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
1625
1626 //
1627 // get device
1628 //
1629 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1630
1631
1632 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1633 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
1634 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
1635 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
1636 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1637 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
1638 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1639 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
1640 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
1641
1642 //
1643 // initialize setup packet
1644 //
1645 CtrlSetup.bmRequestType.B = 0xa1; //FIXME: Const.
1646 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1647 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1648 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1649 CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
1650
1651 //
1652 // issue request
1653 //
1654 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1655
1656 //
1657 // assert on failure
1658 //
1659 PC_ASSERT(NT_SUCCESS(Status));
1660
1661
1662 //
1663 // done
1664 //
1665 return Status;
1666 }
1667
1668 //-----------------------------------------------------------------------------------------
1669 NTSTATUS
1670 CHubController::HandleDeviceControl(
1671 IN PDEVICE_OBJECT DeviceObject,
1672 IN OUT PIRP Irp)
1673 {
1674 PIO_STACK_LOCATION IoStack;
1675 PCOMMON_DEVICE_EXTENSION DeviceExtension;
1676 PURB Urb;
1677 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1678
1679 //
1680 // get current stack location
1681 //
1682 IoStack = IoGetCurrentIrpStackLocation(Irp);
1683
1684 //
1685 // get device extension
1686 //
1687 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1688
1689 //
1690 // determine which request should be performed
1691 //
1692 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
1693 {
1694 case IOCTL_INTERNAL_USB_SUBMIT_URB:
1695 {
1696 //
1697 // get urb
1698 //
1699 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1700 PC_ASSERT(Urb);
1701
1702 switch (Urb->UrbHeader.Function)
1703 {
1704 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
1705 Status = HandleGetDescriptorFromInterface(Irp, Urb);
1706 break;
1707 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
1708 Status = HandleGetDescriptor(Irp, Urb);
1709 break;
1710 case URB_FUNCTION_CLASS_DEVICE:
1711 Status = HandleClassDevice(Irp, Urb);
1712 break;
1713 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
1714 Status = HandleGetStatusFromDevice(Irp, Urb);
1715 break;
1716 case URB_FUNCTION_SELECT_CONFIGURATION:
1717 Status = HandleSelectConfiguration(Irp, Urb);
1718 break;
1719 case URB_FUNCTION_SELECT_INTERFACE:
1720 Status = HandleSelectInterface(Irp, Urb);
1721 break;
1722 case URB_FUNCTION_CLASS_OTHER:
1723 Status = HandleClassOther(Irp, Urb);
1724 break;
1725 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
1726 Status = HandleBulkOrInterruptTransfer(Irp, Urb);
1727 break;
1728 case URB_FUNCTION_ISOCH_TRANSFER:
1729 Status = HandleIsochronousTransfer(Irp, Urb);
1730 break;
1731 case URB_FUNCTION_CLASS_INTERFACE:
1732 Status = HandleClassInterface(Irp, Urb);
1733 break;
1734 case URB_FUNCTION_CLASS_ENDPOINT:
1735 Status = HandleClassEndpoint(Irp, Urb);
1736 break;
1737 default:
1738 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
1739 break;
1740 }
1741 //
1742 // request completed
1743 //
1744 break;
1745 }
1746 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
1747 {
1748 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
1749
1750 if (IoStack->Parameters.Others.Argument1)
1751 {
1752 //
1753 // store object as device handle
1754 //
1755 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
1756 Status = STATUS_SUCCESS;
1757 }
1758 else
1759 {
1760 //
1761 // mis-behaving hub driver
1762 //
1763 Status = STATUS_INVALID_DEVICE_REQUEST;
1764 }
1765
1766 //
1767 // request completed
1768 //
1769 break;
1770 }
1771 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
1772 {
1773 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
1774
1775 //
1776 // this is the first request send, it delivers the PDO to the caller
1777 //
1778 if (IoStack->Parameters.Others.Argument1)
1779 {
1780 //
1781 // store root hub pdo object
1782 //
1783 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
1784 }
1785
1786 if (IoStack->Parameters.Others.Argument2)
1787 {
1788 //
1789 // documentation claims to deliver the hcd controller object, although it is wrong
1790 //
1791 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
1792 }
1793
1794 //
1795 // request completed
1796 //
1797 Status = STATUS_SUCCESS;
1798 break;
1799 }
1800 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
1801 {
1802 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
1803
1804 //
1805 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
1806 // requests this ioctl to deliver the number of presents.
1807
1808 if (IoStack->Parameters.Others.Argument1)
1809 {
1810 //
1811 // FIXME / verify: there is only one hub
1812 //
1813 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
1814 }
1815
1816 //
1817 // request completed
1818 //
1819 Status = STATUS_SUCCESS;
1820 Irp->IoStatus.Information = sizeof(ULONG);
1821 break;
1822 }
1823 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
1824 {
1825 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
1826 Status = STATUS_SUCCESS;
1827 break;
1828 }
1829 default:
1830 {
1831 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
1832 IoStack->Parameters.DeviceIoControl.IoControlCode,
1833 IoStack->Parameters.DeviceIoControl.InputBufferLength,
1834 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
1835 break;
1836 }
1837 }
1838 if (Status != STATUS_PENDING)
1839 {
1840 Irp->IoStatus.Status = Status;
1841 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1842 }
1843
1844 return Status;
1845 }
1846
1847 //-----------------------------------------------------------------------------------------
1848 PUSBHARDWAREDEVICE
1849 CHubController::GetUsbHardware()
1850 {
1851 return m_Hardware;
1852 }
1853
1854 //-----------------------------------------------------------------------------------------
1855 ULONG
1856 CHubController::AcquireDeviceAddress()
1857 {
1858 KIRQL OldLevel;
1859 ULONG DeviceAddress;
1860
1861 //
1862 // acquire device lock
1863 //
1864 KeAcquireSpinLock(&m_Lock, &OldLevel);
1865
1866 //
1867 // find address
1868 //
1869 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
1870 if (DeviceAddress != MAXULONG)
1871 {
1872 //
1873 // reserve address
1874 //
1875 RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
1876
1877 //
1878 // device addresses start from 0x1 - 0xFF
1879 //
1880 DeviceAddress++;
1881 }
1882
1883 //
1884 // release spin lock
1885 //
1886 KeReleaseSpinLock(&m_Lock, OldLevel);
1887
1888 //
1889 // return device address
1890 //
1891 return DeviceAddress;
1892 }
1893 //-----------------------------------------------------------------------------------------
1894 VOID
1895 CHubController::ReleaseDeviceAddress(
1896 ULONG DeviceAddress)
1897 {
1898 KIRQL OldLevel;
1899
1900 //
1901 // acquire device lock
1902 //
1903 KeAcquireSpinLock(&m_Lock, &OldLevel);
1904
1905 //
1906 // sanity check
1907 //
1908 PC_ASSERT(DeviceAddress != 0);
1909
1910 //
1911 // convert back to bit number
1912 //
1913 DeviceAddress--;
1914
1915 //
1916 // clear bit
1917 //
1918 RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
1919
1920 //
1921 // release lock
1922 //
1923 KeReleaseSpinLock(&m_Lock, OldLevel);
1924 }
1925 //-----------------------------------------------------------------------------------------
1926 NTSTATUS
1927 CHubController::RemoveUsbDevice(
1928 PUSBDEVICE UsbDevice)
1929 {
1930 PUSBDEVICE_ENTRY DeviceEntry;
1931 PLIST_ENTRY Entry;
1932 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1933 KIRQL OldLevel;
1934
1935 //
1936 // acquire lock
1937 //
1938 KeAcquireSpinLock(&m_Lock, &OldLevel);
1939
1940 //
1941 // point to first entry
1942 //
1943 Entry = m_UsbDeviceList.Flink;
1944
1945 //
1946 // find matching entry
1947 //
1948 while(Entry != &m_UsbDeviceList)
1949 {
1950 //
1951 // get entry
1952 //
1953 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
1954
1955 //
1956 // is it current entry
1957 //
1958 if (DeviceEntry->Device == UsbDevice)
1959 {
1960 //
1961 // remove entry
1962 //
1963 RemoveEntryList(Entry);
1964
1965 //
1966 // free entry
1967 //
1968 ExFreePoolWithTag(DeviceEntry, TAG_USBEHCI);
1969
1970 //
1971 // done
1972 //
1973 Status = STATUS_SUCCESS;
1974 break;
1975 }
1976
1977 //
1978 // goto next device
1979 //
1980 Entry = Entry->Flink;
1981 }
1982
1983 //
1984 // release lock
1985 //
1986 KeReleaseSpinLock(&m_Lock, OldLevel);
1987
1988 //
1989 // return result
1990 //
1991 return Status;
1992 }
1993 //-----------------------------------------------------------------------------------------
1994 BOOLEAN
1995 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
1996 {
1997 PUSBDEVICE_ENTRY DeviceEntry;
1998 PLIST_ENTRY Entry;
1999 KIRQL OldLevel;
2000 BOOLEAN Result = FALSE;
2001
2002 //
2003 // acquire lock
2004 //
2005 KeAcquireSpinLock(&m_Lock, &OldLevel);
2006
2007 //
2008 // point to first entry
2009 //
2010 Entry = m_UsbDeviceList.Flink;
2011
2012 //
2013 // find matching entry
2014 //
2015 while(Entry != &m_UsbDeviceList)
2016 {
2017 //
2018 // get entry
2019 //
2020 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2021
2022 //
2023 // is it current entry
2024 //
2025 if (DeviceEntry->Device == UsbDevice)
2026 {
2027 //
2028 // device is valid
2029 //
2030 Result = TRUE;
2031 break;
2032 }
2033
2034 //
2035 // goto next device
2036 //
2037 Entry = Entry->Flink;
2038 }
2039
2040 //
2041 // release lock
2042 //
2043 KeReleaseSpinLock(&m_Lock, OldLevel);
2044
2045 //
2046 // return result
2047 //
2048 return Result;
2049
2050 }
2051
2052 //-----------------------------------------------------------------------------------------
2053 NTSTATUS
2054 CHubController::AddUsbDevice(
2055 PUSBDEVICE UsbDevice)
2056 {
2057 PUSBDEVICE_ENTRY DeviceEntry;
2058 KIRQL OldLevel;
2059
2060 //
2061 // allocate device entry
2062 //
2063 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBEHCI);
2064 if (!DeviceEntry)
2065 {
2066 //
2067 // no memory
2068 //
2069 return STATUS_INSUFFICIENT_RESOURCES;
2070 }
2071
2072 //
2073 // initialize entry
2074 //
2075 DeviceEntry->Device = UsbDevice;
2076
2077 //
2078 // acquire lock
2079 //
2080 KeAcquireSpinLock(&m_Lock, &OldLevel);
2081
2082 //
2083 // insert entry
2084 //
2085 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
2086
2087 //
2088 // release spin lock
2089 //
2090 KeReleaseSpinLock(&m_Lock, OldLevel);
2091
2092 //
2093 // done
2094 //
2095 return STATUS_SUCCESS;
2096 }
2097
2098 //-----------------------------------------------------------------------------------------
2099 VOID
2100 CHubController::SetNotification(
2101 PVOID CallbackContext,
2102 PRH_INIT_CALLBACK CallbackRoutine)
2103 {
2104 KIRQL OldLevel;
2105
2106 //
2107 // acquire hub controller lock
2108 //
2109 KeAcquireSpinLock(&m_Lock, &OldLevel);
2110
2111 //
2112 // now set the callback routine and context of the hub
2113 //
2114 m_HubCallbackContext = CallbackContext;
2115 m_HubCallbackRoutine = CallbackRoutine;
2116
2117 //
2118 // release hub controller lock
2119 //
2120 KeReleaseSpinLock(&m_Lock, OldLevel);
2121 }
2122
2123 //=================================================================================================
2124 //
2125 // Generic Interface functions
2126 //
2127 VOID
2128 USB_BUSIFFN
2129 USBI_InterfaceReference(
2130 PVOID BusContext)
2131 {
2132 CHubController * Controller = (CHubController*)BusContext;
2133
2134 DPRINT1("USBH_InterfaceReference\n");
2135
2136 //
2137 // add reference
2138 //
2139 Controller->AddRef();
2140 }
2141
2142 VOID
2143 USB_BUSIFFN
2144 USBI_InterfaceDereference(
2145 PVOID BusContext)
2146 {
2147 CHubController * Controller = (CHubController*)BusContext;
2148
2149 DPRINT1("USBH_InterfaceDereference\n");
2150
2151 //
2152 // release
2153 //
2154 Controller->Release();
2155 }
2156 //=================================================================================================
2157 //
2158 // USB Hub Interface functions
2159 //
2160 NTSTATUS
2161 USB_BUSIFFN
2162 USBHI_CreateUsbDevice(
2163 PVOID BusContext,
2164 PUSB_DEVICE_HANDLE *NewDevice,
2165 PUSB_DEVICE_HANDLE HubDeviceHandle,
2166 USHORT PortStatus,
2167 USHORT PortNumber)
2168 {
2169 PUSBDEVICE NewUsbDevice;
2170 CHubController * Controller;
2171 NTSTATUS Status;
2172
2173 DPRINT1("USBHI_CreateUsbDevice\n");
2174
2175 //
2176 // first get hub controller
2177 //
2178 Controller = (CHubController *)BusContext;
2179
2180 //
2181 // sanity check
2182 //
2183 PC_ASSERT(Controller);
2184 PC_ASSERT(BusContext == HubDeviceHandle);
2185
2186 //
2187 // now allocate usb device
2188 //
2189 Status = CreateUSBDevice(&NewUsbDevice);
2190
2191 //
2192 // check for success
2193 //
2194 if (!NT_SUCCESS(Status))
2195 {
2196 //
2197 // release controller
2198 //
2199 Controller->Release();
2200 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
2201 return Status;
2202 }
2203
2204 //
2205 // now initialize device
2206 //
2207 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
2208
2209 //
2210 // check for success
2211 //
2212 if (!NT_SUCCESS(Status))
2213 {
2214 //
2215 // release usb device
2216 //
2217 NewUsbDevice->Release();
2218 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
2219 return Status;
2220 }
2221
2222 //
2223 // insert into list
2224 //
2225 Status = Controller->AddUsbDevice(NewUsbDevice);
2226 //
2227 // check for success
2228 //
2229 if (!NT_SUCCESS(Status))
2230 {
2231 //
2232 // release usb device
2233 //
2234 NewUsbDevice->Release();
2235
2236 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
2237 return Status;
2238 }
2239
2240 //
2241 // store the handle
2242 //
2243 *NewDevice = NewUsbDevice;
2244
2245 //
2246 // done
2247 //
2248 return STATUS_SUCCESS;
2249 }
2250
2251 NTSTATUS
2252 USB_BUSIFFN
2253 USBHI_InitializeUsbDevice(
2254 PVOID BusContext,
2255 PUSB_DEVICE_HANDLE DeviceHandle)
2256 {
2257 PUSBDEVICE UsbDevice;
2258 CHubController * Controller;
2259 ULONG DeviceAddress;
2260 NTSTATUS Status;
2261 ULONG Index = 0;
2262
2263 DPRINT1("USBHI_InitializeUsbDevice\n");
2264
2265 //
2266 // first get controller
2267 //
2268 Controller = (CHubController *)BusContext;
2269 PC_ASSERT(Controller);
2270
2271 //
2272 // get device object
2273 //
2274 UsbDevice = (PUSBDEVICE)DeviceHandle;
2275 PC_ASSERT(UsbDevice);
2276
2277 //
2278 // validate device handle
2279 //
2280 if (!Controller->ValidateUsbDevice(UsbDevice))
2281 {
2282 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
2283
2284 //
2285 // invalid device handle
2286 //
2287 return STATUS_DEVICE_NOT_CONNECTED;
2288 }
2289
2290 //
2291 // now reserve an address
2292 //
2293 DeviceAddress = Controller->AcquireDeviceAddress();
2294
2295 //
2296 // is the device address valid
2297 //
2298 if (DeviceAddress == MAXULONG)
2299 {
2300 //
2301 // failed to get an device address from the device address pool
2302 //
2303 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2304 return STATUS_DEVICE_DATA_ERROR;
2305 }
2306
2307 do
2308 {
2309 //
2310 // now set the device address
2311 //
2312 Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
2313
2314 if (NT_SUCCESS(Status))
2315 break;
2316
2317 }while(Index++ < 3 );
2318
2319 //
2320 // check for failure
2321 //
2322 if (!NT_SUCCESS(Status))
2323 {
2324 //
2325 // failed to set device address
2326 //
2327 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
2328
2329 //
2330 // release address
2331 //
2332 Controller->ReleaseDeviceAddress(DeviceAddress);
2333
2334 //
2335 // return error
2336 //
2337 return STATUS_DEVICE_DATA_ERROR;
2338 }
2339
2340 //
2341 // done
2342 //
2343 return STATUS_SUCCESS;
2344 }
2345
2346 NTSTATUS
2347 USB_BUSIFFN
2348 USBHI_GetUsbDescriptors(
2349 PVOID BusContext,
2350 PUSB_DEVICE_HANDLE DeviceHandle,
2351 PUCHAR DeviceDescriptorBuffer,
2352 PULONG DeviceDescriptorBufferLength,
2353 PUCHAR ConfigDescriptorBuffer,
2354 PULONG ConfigDescriptorBufferLength)
2355 {
2356 PUSBDEVICE UsbDevice;
2357 CHubController * Controller;
2358
2359 DPRINT1("USBHI_GetUsbDescriptors\n");
2360
2361 //
2362 // sanity check
2363 //
2364 PC_ASSERT(DeviceDescriptorBuffer);
2365 PC_ASSERT(DeviceDescriptorBufferLength);
2366 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
2367 PC_ASSERT(ConfigDescriptorBufferLength);
2368 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
2369
2370 //
2371 // first get controller
2372 //
2373 Controller = (CHubController *)BusContext;
2374 PC_ASSERT(Controller);
2375
2376
2377 //
2378 // get device object
2379 //
2380 UsbDevice = (PUSBDEVICE)DeviceHandle;
2381 PC_ASSERT(UsbDevice);
2382
2383 //
2384 // validate device handle
2385 //
2386 if (!Controller->ValidateUsbDevice(UsbDevice))
2387 {
2388 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
2389
2390 //
2391 // invalid device handle
2392 //
2393 return STATUS_DEVICE_NOT_CONNECTED;
2394 }
2395
2396 //
2397 // get device descriptor
2398 //
2399 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
2400
2401 //
2402 // store result length
2403 //
2404 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
2405
2406 //
2407 // get configuration descriptor
2408 //
2409 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
2410
2411 //
2412 // complete the request
2413 //
2414 return STATUS_SUCCESS;
2415 }
2416
2417 NTSTATUS
2418 USB_BUSIFFN
2419 USBHI_RemoveUsbDevice(
2420 PVOID BusContext,
2421 PUSB_DEVICE_HANDLE DeviceHandle,
2422 ULONG Flags)
2423 {
2424 PUSBDEVICE UsbDevice;
2425 CHubController * Controller;
2426 NTSTATUS Status;
2427
2428 DPRINT1("USBHI_RemoveUsbDevice\n");
2429
2430 //
2431 // first get controller
2432 //
2433 Controller = (CHubController *)BusContext;
2434 PC_ASSERT(Controller);
2435
2436 //
2437 // get device object
2438 //
2439 UsbDevice = (PUSBDEVICE)DeviceHandle;
2440 PC_ASSERT(UsbDevice);
2441
2442 //
2443 // validate device handle
2444 //
2445 if (!Controller->ValidateUsbDevice(UsbDevice))
2446 {
2447 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
2448
2449 //
2450 // invalid device handle
2451 //
2452 return STATUS_DEVICE_NOT_CONNECTED;
2453 }
2454
2455 //
2456 // check if there were flags passed
2457 //
2458 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
2459 {
2460 //
2461 // ignore flags for now
2462 //
2463 return STATUS_SUCCESS;
2464 }
2465
2466 //
2467 // remove device
2468 //
2469 Status = Controller->RemoveUsbDevice(UsbDevice);
2470 if (!NT_SUCCESS(Status))
2471 {
2472 //
2473 // invalid device handle
2474 //
2475 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
2476 PC_ASSERT(0);
2477 return STATUS_DEVICE_NOT_CONNECTED;
2478 }
2479
2480 //
2481 // release usb device
2482 //
2483 UsbDevice->Release();
2484
2485 //
2486 // done
2487 //
2488 return STATUS_SUCCESS;
2489 }
2490
2491 NTSTATUS
2492 USB_BUSIFFN
2493 USBHI_RestoreUsbDevice(
2494 PVOID BusContext,
2495 PUSB_DEVICE_HANDLE OldDeviceHandle,
2496 PUSB_DEVICE_HANDLE NewDeviceHandle)
2497 {
2498 PUSBDEVICE OldUsbDevice, NewUsbDevice;
2499 CHubController * Controller;
2500
2501 DPRINT1("USBHI_RestoreUsbDevice\n");
2502
2503 //
2504 // first get controller
2505 //
2506 Controller = (CHubController *)BusContext;
2507 PC_ASSERT(Controller);
2508
2509 //
2510 // get device object
2511 //
2512 OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
2513 NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
2514 PC_ASSERT(OldUsbDevice);
2515 PC_ASSERT(NewDeviceHandle);
2516
2517 //
2518 // validate device handle
2519 //
2520 PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
2521 PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
2522
2523 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
2524 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
2525
2526 //
2527 // remove old device handle
2528 //
2529 USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
2530
2531 return STATUS_SUCCESS;
2532 }
2533
2534 NTSTATUS
2535 USB_BUSIFFN
2536 USBHI_QueryDeviceInformation(
2537 PVOID BusContext,
2538 PUSB_DEVICE_HANDLE DeviceHandle,
2539 PVOID DeviceInformationBuffer,
2540 ULONG DeviceInformationBufferLength,
2541 PULONG LengthReturned)
2542 {
2543 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
2544 PUSBDEVICE UsbDevice;
2545 CHubController * Controller;
2546
2547 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
2548
2549 //
2550 // sanity check
2551 //
2552 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
2553 PC_ASSERT(DeviceInformationBuffer);
2554 PC_ASSERT(LengthReturned);
2555
2556 //
2557 // get controller object
2558 //
2559 Controller = (CHubController*)BusContext;
2560 PC_ASSERT(Controller);
2561
2562 //
2563 // get device object
2564 //
2565 UsbDevice = (PUSBDEVICE)DeviceHandle;
2566 PC_ASSERT(UsbDevice);
2567
2568 if (BusContext != DeviceHandle)
2569 {
2570 //
2571 // validate device handle
2572 //
2573 if (!Controller->ValidateUsbDevice(UsbDevice))
2574 {
2575 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
2576
2577 //
2578 // invalid device handle
2579 //
2580 return STATUS_DEVICE_NOT_CONNECTED;
2581 }
2582
2583 //
2584 // access information buffer
2585 //
2586 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2587
2588 //
2589 // initialize with default values
2590 //
2591 DeviceInfo->InformationLevel = 0;
2592 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2593 DeviceInfo->PortNumber = UsbDevice->GetPort();
2594 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
2595 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
2596 DeviceInfo->HubAddress = 0; //FIXME
2597 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
2598 DeviceInfo->DeviceType = UsbDevice->GetType();
2599 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2600
2601 //
2602 // get device descriptor
2603 //
2604 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
2605
2606 //
2607 // FIXME return pipe information
2608 //
2609
2610 //
2611 // store result length
2612 //
2613 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
2614
2615 return STATUS_SUCCESS;
2616 }
2617
2618 //
2619 // access information buffer
2620 //
2621 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2622
2623 //
2624 // initialize with default values
2625 //
2626 DeviceInfo->InformationLevel = 0;
2627 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2628 DeviceInfo->PortNumber = 0;
2629 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
2630 DeviceInfo->DeviceAddress = 0;
2631 DeviceInfo->HubAddress = 0; //FIXME
2632 DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
2633 DeviceInfo->DeviceType = Usb20Device; //FIXME
2634 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2635
2636 //
2637 // get device descriptor
2638 //
2639 RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
2640
2641 //
2642 // FIXME return pipe information
2643 //
2644
2645 //
2646 // store result length
2647 //
2648 #ifdef _MSC_VER
2649 *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
2650 #else
2651 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
2652 #endif
2653 //
2654 // done
2655 //
2656 return STATUS_SUCCESS;
2657 }
2658
2659 NTSTATUS
2660 USB_BUSIFFN
2661 USBHI_GetControllerInformation(
2662 PVOID BusContext,
2663 PVOID ControllerInformationBuffer,
2664 ULONG ControllerInformationBufferLength,
2665 PULONG LengthReturned)
2666 {
2667 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
2668
2669 DPRINT1("USBHI_GetControllerInformation\n");
2670
2671 //
2672 // sanity checks
2673 //
2674 PC_ASSERT(ControllerInformationBuffer);
2675 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
2676
2677 //
2678 // get controller info buffer
2679 //
2680 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
2681
2682 //
2683 // FIXME only version 0 is supported for now
2684 //
2685 PC_ASSERT(ControllerInfo->InformationLevel == 0);
2686
2687 //
2688 // fill in information
2689 //
2690 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
2691 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
2692 ControllerInfo->IsHighSpeedController = TRUE;
2693
2694 //
2695 // set length returned
2696 //
2697 *LengthReturned = ControllerInfo->ActualLength;
2698
2699 //
2700 // done
2701 //
2702 return STATUS_SUCCESS;
2703 }
2704
2705 NTSTATUS
2706 USB_BUSIFFN
2707 USBHI_ControllerSelectiveSuspend(
2708 PVOID BusContext,
2709 BOOLEAN Enable)
2710 {
2711 UNIMPLEMENTED
2712 return STATUS_NOT_IMPLEMENTED;
2713 }
2714
2715 NTSTATUS
2716 USB_BUSIFFN
2717 USBHI_GetExtendedHubInformation(
2718 PVOID BusContext,
2719 PDEVICE_OBJECT HubPhysicalDeviceObject,
2720 PVOID HubInformationBuffer,
2721 ULONG HubInformationBufferLength,
2722 PULONG LengthReturned)
2723 {
2724 PUSB_EXTHUB_INFORMATION_0 HubInfo;
2725 CHubController * Controller;
2726 PUSBHARDWAREDEVICE Hardware;
2727 ULONG Index;
2728 ULONG NumPort, Dummy2;
2729 USHORT Dummy1;
2730 NTSTATUS Status;
2731
2732 DPRINT1("USBHI_GetExtendedHubInformation\n");
2733
2734 //
2735 // sanity checks
2736 //
2737 PC_ASSERT(HubInformationBuffer);
2738 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
2739 PC_ASSERT(LengthReturned);
2740
2741 //
2742 // get hub controller
2743 //
2744 Controller = (CHubController *)BusContext;
2745 PC_ASSERT(Controller);
2746
2747 //
2748 // get usb hardware device
2749 //
2750 Hardware = Controller->GetUsbHardware();
2751
2752 //
2753 // retrieve number of ports
2754 //
2755 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
2756 if (!NT_SUCCESS(Status))
2757 {
2758 //
2759 // failed to get hardware details, ouch ;)
2760 //
2761 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
2762 return Status;
2763 }
2764
2765 //
2766 // get hub information buffer
2767 //
2768 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
2769
2770 //
2771 // initialize hub information
2772 //
2773 HubInfo->InformationLevel = 0;
2774
2775 //
2776 // store port count
2777 //
2778 HubInfo->NumberOfPorts = NumPort;
2779
2780 //
2781 // initialize port information
2782 //
2783 for(Index = 0; Index < NumPort; Index++)
2784 {
2785 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
2786 HubInfo->Port[Index].PortLabelNumber = Index + 1;
2787 HubInfo->Port[Index].VidOverride = 0;
2788 HubInfo->Port[Index].PidOverride = 0;
2789 HubInfo->Port[Index].PortAttributes = USB_PORTATTR_SHARED_USB2; //FIXME
2790 }
2791
2792 //
2793 // store result length
2794 //
2795 #ifdef _MSC_VER
2796 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
2797 #else
2798 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
2799 #endif
2800
2801 //
2802 // done
2803 //
2804 return STATUS_SUCCESS;
2805 }
2806
2807 NTSTATUS
2808 USB_BUSIFFN
2809 USBHI_GetRootHubSymbolicName(
2810 PVOID BusContext,
2811 PVOID HubSymNameBuffer,
2812 ULONG HubSymNameBufferLength,
2813 PULONG HubSymNameActualLength)
2814 {
2815 UNIMPLEMENTED
2816 return STATUS_NOT_IMPLEMENTED;
2817 }
2818
2819 PVOID
2820 USB_BUSIFFN
2821 USBHI_GetDeviceBusContext(
2822 PVOID HubBusContext,
2823 PVOID DeviceHandle)
2824 {
2825 UNIMPLEMENTED
2826 return NULL;
2827 }
2828
2829 NTSTATUS
2830 USB_BUSIFFN
2831 USBHI_Initialize20Hub(
2832 PVOID BusContext,
2833 PUSB_DEVICE_HANDLE HubDeviceHandle,
2834 ULONG TtCount)
2835 {
2836 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle, TtCount);
2837 return STATUS_SUCCESS;
2838 }
2839
2840 NTSTATUS
2841 USB_BUSIFFN
2842 USBHI_RootHubInitNotification(
2843 PVOID BusContext,
2844 PVOID CallbackContext,
2845 PRH_INIT_CALLBACK CallbackRoutine)
2846 {
2847 CHubController * Controller;
2848
2849 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
2850
2851 //
2852 // get controller object
2853 //
2854 Controller = (CHubController*)BusContext;
2855 PC_ASSERT(Controller);
2856
2857 //
2858 // set notification routine
2859 //
2860 Controller->SetNotification(CallbackContext, CallbackRoutine);
2861
2862 //
2863 // FIXME: determine when to perform callback
2864 //
2865 CallbackRoutine(CallbackContext);
2866
2867 //
2868 // done
2869 //
2870 return STATUS_SUCCESS;
2871 }
2872
2873 VOID
2874 USB_BUSIFFN
2875 USBHI_FlushTransfers(
2876 PVOID BusContext,
2877 PVOID DeviceHandle)
2878 {
2879 UNIMPLEMENTED
2880 }
2881
2882 VOID
2883 USB_BUSIFFN
2884 USBHI_SetDeviceHandleData(
2885 PVOID BusContext,
2886 PVOID DeviceHandle,
2887 PDEVICE_OBJECT UsbDevicePdo)
2888 {
2889 PUSBDEVICE UsbDevice;
2890 CHubController * Controller;
2891
2892 //
2893 // get controller
2894 //
2895 Controller = (CHubController *)BusContext;
2896 PC_ASSERT(Controller);
2897
2898 //
2899 // get device handle
2900 //
2901 UsbDevice = (PUSBDEVICE)DeviceHandle;
2902
2903 //
2904 // validate device handle
2905 //
2906 if (!Controller->ValidateUsbDevice(UsbDevice))
2907 {
2908 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
2909
2910 //
2911 // invalid handle
2912 //
2913 return;
2914 }
2915 else
2916 {
2917 //
2918 // usbhub sends this request as a part of the Pnp startup sequence
2919 // looks like we need apply a dragon voodoo to fixup the device stack
2920 // otherwise usbhub will cause a bugcheck
2921 //
2922 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo);
2923
2924 //
2925 // sanity check
2926 //
2927 PC_ASSERT(UsbDevicePdo->AttachedDevice);
2928
2929 //
2930 // should be usbstor
2931 // fixup device stack voodoo part #2
2932 //
2933 UsbDevicePdo->AttachedDevice->StackSize++;
2934
2935 //
2936 // set device handle data
2937 //
2938 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
2939 }
2940 }
2941
2942 //=================================================================================================
2943 //
2944 // USB Device Interface functions
2945 //
2946
2947 VOID
2948 USB_BUSIFFN
2949 USBDI_GetUSBDIVersion(
2950 PVOID BusContext,
2951 PUSBD_VERSION_INFORMATION VersionInformation,
2952 PULONG HcdCapabilites)
2953 {
2954 CHubController * Controller;
2955 PUSBHARDWAREDEVICE Device;
2956 ULONG Speed, Dummy2;
2957 USHORT Dummy1;
2958
2959 DPRINT1("USBDI_GetUSBDIVersion\n");
2960
2961 //
2962 // get controller
2963 //
2964 Controller = (CHubController*)BusContext;
2965
2966 //
2967 // get usb hardware
2968 //
2969 Device = Controller->GetUsbHardware();
2970 PC_ASSERT(Device);
2971
2972 if (VersionInformation)
2973 {
2974 //
2975 // windows xp supported
2976 //
2977 VersionInformation->USBDI_Version = 0x00000500;
2978
2979 //
2980 // get device speed
2981 //
2982 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
2983
2984 //
2985 // store speed details
2986 //
2987 VersionInformation->Supported_USB_Version = Speed;
2988 }
2989
2990 //
2991 // no flags supported
2992 //
2993 *HcdCapabilites = 0;
2994 }
2995
2996 NTSTATUS
2997 USB_BUSIFFN
2998 USBDI_QueryBusTime(
2999 PVOID BusContext,
3000 PULONG CurrentFrame)
3001 {
3002 UNIMPLEMENTED
3003 return STATUS_NOT_IMPLEMENTED;
3004 }
3005
3006 NTSTATUS
3007 USB_BUSIFFN
3008 USBDI_SubmitIsoOutUrb(
3009 PVOID BusContext,
3010 PURB Urb)
3011 {
3012 UNIMPLEMENTED
3013 return STATUS_NOT_IMPLEMENTED;
3014 }
3015
3016 NTSTATUS
3017 USB_BUSIFFN
3018 USBDI_QueryBusInformation(
3019 PVOID BusContext,
3020 ULONG Level,
3021 PVOID BusInformationBuffer,
3022 PULONG BusInformationBufferLength,
3023 PULONG BusInformationActualLength)
3024 {
3025 UNIMPLEMENTED
3026 return STATUS_NOT_IMPLEMENTED;
3027 }
3028
3029 BOOLEAN
3030 USB_BUSIFFN
3031 USBDI_IsDeviceHighSpeed(
3032 PVOID BusContext)
3033 {
3034 CHubController * Controller;
3035 PUSBHARDWAREDEVICE Device;
3036 ULONG Speed, Dummy2;
3037 USHORT Dummy1;
3038
3039 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3040
3041 //
3042 // get controller
3043 //
3044 Controller = (CHubController*)BusContext;
3045
3046 //
3047 // get usb hardware
3048 //
3049 Device = Controller->GetUsbHardware();
3050 PC_ASSERT(Device);
3051
3052 //
3053 // get device speed
3054 //
3055 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3056
3057 //
3058 // USB 2.0 equals 0x200
3059 //
3060 return (Speed == 0x200);
3061 }
3062
3063 NTSTATUS
3064 USB_BUSIFFN
3065 USBDI_EnumLogEntry(
3066 PVOID BusContext,
3067 ULONG DriverTag,
3068 ULONG EnumTag,
3069 ULONG P1,
3070 ULONG P2)
3071 {
3072 UNIMPLEMENTED
3073 return STATUS_NOT_IMPLEMENTED;
3074 }
3075
3076 NTSTATUS
3077 CHubController::HandleQueryInterface(
3078 PIO_STACK_LOCATION IoStack)
3079 {
3080 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
3081 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
3082 UNICODE_STRING GuidBuffer;
3083 NTSTATUS Status;
3084
3085 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
3086 {
3087 //
3088 // get request parameters
3089 //
3090 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
3091 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
3092
3093 //
3094 // check version
3095 //
3096 if (IoStack->Parameters.QueryInterface.Version >= 6)
3097 {
3098 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3099
3100 //
3101 // version not supported
3102 //
3103 return STATUS_NOT_SUPPORTED;
3104 }
3105
3106 //
3107 // Interface version 0
3108 //
3109 if (IoStack->Parameters.QueryInterface.Version >= 0)
3110 {
3111 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
3112 InterfaceHub->BusContext = PVOID(this);
3113 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
3114 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
3115 }
3116
3117 //
3118 // Interface version 1
3119 //
3120 if (IoStack->Parameters.QueryInterface.Version >= 1)
3121 {
3122 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
3123 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
3124 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
3125 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
3126 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
3127 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
3128 }
3129
3130 //
3131 // Interface version 2
3132 //
3133 if (IoStack->Parameters.QueryInterface.Version >= 2)
3134 {
3135 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
3136 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
3137 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
3138 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
3139 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
3140 InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
3141
3142 }
3143
3144 //
3145 // Interface version 3
3146 //
3147 if (IoStack->Parameters.QueryInterface.Version >= 3)
3148 {
3149 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
3150 }
3151
3152 //
3153 // Interface version 4
3154 //
3155 if (IoStack->Parameters.QueryInterface.Version >= 4)
3156 {
3157 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
3158 }
3159
3160 //
3161 // Interface version 5
3162 //
3163 if (IoStack->Parameters.QueryInterface.Version >= 5)
3164 {
3165 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
3166 }
3167
3168 //
3169 // request completed
3170 //
3171 return STATUS_SUCCESS;
3172 }
3173 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
3174 {
3175 //
3176 // get request parameters
3177 //
3178 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
3179 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
3180
3181 //
3182 // check version
3183 //
3184 if (IoStack->Parameters.QueryInterface.Version >= 3)
3185 {
3186 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3187
3188 //
3189 // version not supported
3190 //
3191 return STATUS_NOT_SUPPORTED;
3192 }
3193
3194 //
3195 // interface version 0
3196 //
3197 if (IoStack->Parameters.QueryInterface.Version >= 0)
3198 {
3199 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
3200 InterfaceDI->BusContext = PVOID(this);
3201 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
3202 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
3203 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
3204 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
3205 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
3206 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
3207 }
3208
3209 //
3210 // interface version 1
3211 //
3212 if (IoStack->Parameters.QueryInterface.Version >= 1)
3213 {
3214 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
3215 }
3216
3217 //
3218 // interface version 2
3219 //
3220 if (IoStack->Parameters.QueryInterface.Version >= 2)
3221 {
3222 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
3223 }
3224
3225 //
3226 // request completed
3227 //
3228 return STATUS_SUCCESS;
3229 }
3230 else
3231 {
3232 //
3233 // convert guid to string
3234 //
3235 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
3236 if (NT_SUCCESS(Status))
3237 {
3238 //
3239 // print interface
3240 //
3241 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
3242
3243 //
3244 // free guid buffer
3245 //
3246 RtlFreeUnicodeString(&GuidBuffer);
3247 }
3248 }
3249 return STATUS_NOT_SUPPORTED;
3250 }
3251
3252 NTSTATUS
3253 CHubController::SetDeviceInterface(
3254 BOOLEAN Enable)
3255 {
3256 NTSTATUS Status = STATUS_SUCCESS;
3257
3258 if (Enable)
3259 {
3260 //
3261 // register device interface
3262 //
3263 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
3264
3265 if (NT_SUCCESS(Status))
3266 {
3267 //
3268 // now enable the device interface
3269 //
3270 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
3271
3272 //
3273 // enable interface
3274 //
3275 m_InterfaceEnabled = TRUE;
3276 }
3277 }
3278 else if (m_InterfaceEnabled)
3279 {
3280 //
3281 // disable device interface
3282 //
3283 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
3284
3285 if (NT_SUCCESS(Status))
3286 {
3287 //
3288 // now delete interface string
3289 //
3290 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
3291 }
3292
3293 //
3294 // disable interface
3295 //
3296 m_InterfaceEnabled = FALSE;
3297 }
3298
3299 //
3300 // done
3301 //
3302 return STATUS_SUCCESS;
3303 }
3304
3305 NTSTATUS
3306 CHubController::CreatePDO(
3307 PDRIVER_OBJECT DriverObject,
3308 PDEVICE_OBJECT * OutDeviceObject)
3309 {
3310 WCHAR CharDeviceName[64];
3311 NTSTATUS Status;
3312 ULONG UsbDeviceNumber = 0;
3313 UNICODE_STRING DeviceName;
3314
3315 while (TRUE)
3316 {
3317 //
3318 // construct device name
3319 //
3320 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
3321
3322 //
3323 // initialize device name
3324 //
3325 RtlInitUnicodeString(&DeviceName, CharDeviceName);
3326
3327 //
3328 // create device
3329 //
3330 Status = IoCreateDevice(DriverObject,
3331 sizeof(COMMON_DEVICE_EXTENSION),
3332 &DeviceName,
3333 FILE_DEVICE_CONTROLLER,
3334 0,
3335 FALSE,
3336 OutDeviceObject);
3337
3338 /* check for success */
3339 if (NT_SUCCESS(Status))
3340 break;
3341
3342 //
3343 // is there a device object with that same name
3344 //
3345 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
3346 {
3347 //
3348 // Try the next name
3349 //
3350 UsbDeviceNumber++;
3351 continue;
3352 }
3353
3354 //
3355 // bail out on other errors
3356 //
3357 if (!NT_SUCCESS(Status))
3358 {
3359 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
3360 return Status;
3361 }
3362 }
3363
3364 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
3365
3366 //
3367 // fixup device stack voodoo part #1
3368 //
3369 (*OutDeviceObject)->StackSize++;
3370
3371 /* done */
3372 return Status;
3373 }
3374
3375
3376
3377 NTSTATUS
3378 CreateHubController(
3379 PHUBCONTROLLER *OutHcdController)
3380 {
3381 PHUBCONTROLLER This;
3382
3383 //
3384 // allocate controller
3385 //
3386 This = new(NonPagedPool, TAG_USBEHCI) CHubController(0);
3387 if (!This)
3388 {
3389 //
3390 // failed to allocate
3391 //
3392 return STATUS_INSUFFICIENT_RESOURCES;
3393 }
3394
3395 //
3396 // add reference count
3397 //
3398 This->AddRef();
3399
3400 //
3401 // return result
3402 //
3403 *OutHcdController = (PHUBCONTROLLER)This;
3404
3405 //
3406 // done
3407 //
3408 return STATUS_SUCCESS;
3409 }
3410
3411 VOID StatusChangeEndpointCallBack(PVOID Context)
3412 {
3413 CHubController* This;
3414 PIRP Irp;
3415 This = (CHubController*)Context;
3416
3417 ASSERT(This);
3418
3419 Irp = This->m_PendingSCEIrp;
3420 if (!Irp)
3421 {
3422 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3423 return;
3424 }
3425
3426 This->m_PendingSCEIrp = NULL;
3427 This->QueryStatusChageEndpoint(Irp);
3428
3429 Irp->IoStatus.Status = STATUS_SUCCESS;
3430 Irp->IoStatus.Information = 0;
3431
3432 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3433 }