4e071d12517f6a6aeaafc9524d226457808041cc
[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 = 0; 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 DPRINT(__FUNCTION__ " acquire\n");
1865 KeAcquireSpinLock(&m_Lock, &OldLevel);
1866 DPRINT(__FUNCTION__ " acquired\n");
1867
1868 //
1869 // find address
1870 //
1871 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
1872 if (DeviceAddress != MAXULONG)
1873 {
1874 //
1875 // reserve address
1876 //
1877 RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
1878
1879 //
1880 // device addresses start from 0x1 - 0xFF
1881 //
1882 DeviceAddress++;
1883 }
1884
1885 //
1886 // release spin lock
1887 //
1888 DPRINT(__FUNCTION__ "release\n");
1889 KeReleaseSpinLock(&m_Lock, OldLevel);
1890
1891 //
1892 // return device address
1893 //
1894 return DeviceAddress;
1895 }
1896 //-----------------------------------------------------------------------------------------
1897 VOID
1898 CHubController::ReleaseDeviceAddress(
1899 ULONG DeviceAddress)
1900 {
1901 KIRQL OldLevel;
1902
1903 //
1904 // acquire device lock
1905 //
1906 DPRINT(__FUNCTION__ " acquire\n");
1907 KeAcquireSpinLock(&m_Lock, &OldLevel);
1908 DPRINT(__FUNCTION__ " acquired\n");
1909
1910 //
1911 // sanity check
1912 //
1913 PC_ASSERT(DeviceAddress != 0);
1914
1915 //
1916 // convert back to bit number
1917 //
1918 DeviceAddress--;
1919
1920 //
1921 // clear bit
1922 //
1923 RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
1924
1925 //
1926 // release lock
1927 //
1928 DPRINT(__FUNCTION__ "release\n");
1929 KeReleaseSpinLock(&m_Lock, OldLevel);
1930 }
1931 //-----------------------------------------------------------------------------------------
1932 NTSTATUS
1933 CHubController::RemoveUsbDevice(
1934 PUSBDEVICE UsbDevice)
1935 {
1936 PUSBDEVICE_ENTRY DeviceEntry;
1937 PLIST_ENTRY Entry;
1938 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1939 KIRQL OldLevel;
1940
1941 //
1942 // acquire lock
1943 //
1944 DPRINT(__FUNCTION__ " acquire\n");
1945 KeAcquireSpinLock(&m_Lock, &OldLevel);
1946 DPRINT(__FUNCTION__ " acquired\n");
1947
1948 //
1949 // point to first entry
1950 //
1951 Entry = m_UsbDeviceList.Flink;
1952
1953 //
1954 // find matching entry
1955 //
1956 while(Entry != &m_UsbDeviceList)
1957 {
1958 //
1959 // get entry
1960 //
1961 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
1962
1963 //
1964 // is it current entry
1965 //
1966 if (DeviceEntry->Device == UsbDevice)
1967 {
1968 //
1969 // remove entry
1970 //
1971 RemoveEntryList(Entry);
1972
1973 //
1974 // free entry
1975 //
1976 ExFreePoolWithTag(DeviceEntry, TAG_USBEHCI);
1977
1978 //
1979 // done
1980 //
1981 Status = STATUS_SUCCESS;
1982 break;
1983 }
1984
1985 //
1986 // goto next device
1987 //
1988 Entry = Entry->Flink;
1989 }
1990
1991 //
1992 // release lock
1993 //
1994 DPRINT(__FUNCTION__ "release\n");
1995 KeReleaseSpinLock(&m_Lock, OldLevel);
1996
1997 //
1998 // return result
1999 //
2000 return Status;
2001 }
2002 //-----------------------------------------------------------------------------------------
2003 BOOLEAN
2004 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
2005 {
2006 PUSBDEVICE_ENTRY DeviceEntry;
2007 PLIST_ENTRY Entry;
2008 KIRQL OldLevel;
2009 BOOLEAN Result = FALSE;
2010
2011 //
2012 // acquire lock
2013 //
2014 DPRINT(__FUNCTION__ " acquire\n");
2015 KeAcquireSpinLock(&m_Lock, &OldLevel);
2016 DPRINT(__FUNCTION__ " acquired\n");
2017
2018 //
2019 // point to first entry
2020 //
2021 Entry = m_UsbDeviceList.Flink;
2022
2023 //
2024 // find matching entry
2025 //
2026 while(Entry != &m_UsbDeviceList)
2027 {
2028 //
2029 // get entry
2030 //
2031 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2032
2033 //
2034 // is it current entry
2035 //
2036 if (DeviceEntry->Device == UsbDevice)
2037 {
2038 //
2039 // device is valid
2040 //
2041 Result = TRUE;
2042 break;
2043 }
2044
2045 //
2046 // goto next device
2047 //
2048 Entry = Entry->Flink;
2049 }
2050
2051 //
2052 // release lock
2053 //
2054 DPRINT(__FUNCTION__ "release\n");
2055 KeReleaseSpinLock(&m_Lock, OldLevel);
2056
2057 //
2058 // return result
2059 //
2060 return Result;
2061
2062 }
2063
2064 //-----------------------------------------------------------------------------------------
2065 NTSTATUS
2066 CHubController::AddUsbDevice(
2067 PUSBDEVICE UsbDevice)
2068 {
2069 PUSBDEVICE_ENTRY DeviceEntry;
2070 KIRQL OldLevel;
2071
2072 //
2073 // allocate device entry
2074 //
2075 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBEHCI);
2076 if (!DeviceEntry)
2077 {
2078 //
2079 // no memory
2080 //
2081 return STATUS_INSUFFICIENT_RESOURCES;
2082 }
2083
2084 //
2085 // initialize entry
2086 //
2087 DeviceEntry->Device = UsbDevice;
2088
2089 //
2090 // acquire lock
2091 //
2092 DPRINT(__FUNCTION__ " acquire\n");
2093 KeAcquireSpinLock(&m_Lock, &OldLevel);
2094 DPRINT(__FUNCTION__ " acquired\n");
2095
2096 //
2097 // insert entry
2098 //
2099 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
2100
2101 //
2102 // release spin lock
2103 //
2104 DPRINT(__FUNCTION__ "release\n");
2105 KeReleaseSpinLock(&m_Lock, OldLevel);
2106
2107 //
2108 // done
2109 //
2110 return STATUS_SUCCESS;
2111 }
2112
2113 //-----------------------------------------------------------------------------------------
2114 VOID
2115 CHubController::SetNotification(
2116 PVOID CallbackContext,
2117 PRH_INIT_CALLBACK CallbackRoutine)
2118 {
2119 KIRQL OldLevel;
2120
2121 //
2122 // acquire hub controller lock
2123 //
2124 DPRINT(__FUNCTION__ " acquire\n");
2125 KeAcquireSpinLock(&m_Lock, &OldLevel);
2126 DPRINT(__FUNCTION__ " acquired\n");
2127
2128 //
2129 // now set the callback routine and context of the hub
2130 //
2131 m_HubCallbackContext = CallbackContext;
2132 m_HubCallbackRoutine = CallbackRoutine;
2133
2134 //
2135 // release hub controller lock
2136 //
2137 DPRINT(__FUNCTION__ "release\n");
2138 KeReleaseSpinLock(&m_Lock, OldLevel);
2139 }
2140
2141 //=================================================================================================
2142 //
2143 // Generic Interface functions
2144 //
2145 VOID
2146 USB_BUSIFFN
2147 USBI_InterfaceReference(
2148 PVOID BusContext)
2149 {
2150 CHubController * Controller = (CHubController*)BusContext;
2151
2152 DPRINT1("USBH_InterfaceReference\n");
2153
2154 //
2155 // add reference
2156 //
2157 Controller->AddRef();
2158 }
2159
2160 VOID
2161 USB_BUSIFFN
2162 USBI_InterfaceDereference(
2163 PVOID BusContext)
2164 {
2165 CHubController * Controller = (CHubController*)BusContext;
2166
2167 DPRINT1("USBH_InterfaceDereference\n");
2168
2169 //
2170 // release
2171 //
2172 Controller->Release();
2173 }
2174 //=================================================================================================
2175 //
2176 // USB Hub Interface functions
2177 //
2178 NTSTATUS
2179 USB_BUSIFFN
2180 USBHI_CreateUsbDevice(
2181 PVOID BusContext,
2182 PUSB_DEVICE_HANDLE *NewDevice,
2183 PUSB_DEVICE_HANDLE HubDeviceHandle,
2184 USHORT PortStatus,
2185 USHORT PortNumber)
2186 {
2187 PUSBDEVICE NewUsbDevice;
2188 CHubController * Controller;
2189 NTSTATUS Status;
2190
2191 DPRINT1("USBHI_CreateUsbDevice\n");
2192
2193 //
2194 // first get hub controller
2195 //
2196 Controller = (CHubController *)BusContext;
2197
2198 //
2199 // sanity check
2200 //
2201 PC_ASSERT(Controller);
2202 PC_ASSERT(BusContext == HubDeviceHandle);
2203
2204 //
2205 // now allocate usb device
2206 //
2207 Status = CreateUSBDevice(&NewUsbDevice);
2208
2209 //
2210 // check for success
2211 //
2212 if (!NT_SUCCESS(Status))
2213 {
2214 //
2215 // release controller
2216 //
2217 Controller->Release();
2218 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
2219 return Status;
2220 }
2221
2222 //
2223 // now initialize device
2224 //
2225 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
2226
2227 //
2228 // check for success
2229 //
2230 if (!NT_SUCCESS(Status))
2231 {
2232 //
2233 // release usb device
2234 //
2235 NewUsbDevice->Release();
2236 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
2237 return Status;
2238 }
2239
2240 //
2241 // insert into list
2242 //
2243 Status = Controller->AddUsbDevice(NewUsbDevice);
2244 //
2245 // check for success
2246 //
2247 if (!NT_SUCCESS(Status))
2248 {
2249 //
2250 // release usb device
2251 //
2252 NewUsbDevice->Release();
2253
2254 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
2255 return Status;
2256 }
2257
2258 //
2259 // store the handle
2260 //
2261 *NewDevice = NewUsbDevice;
2262
2263 //
2264 // done
2265 //
2266 return STATUS_SUCCESS;
2267 }
2268
2269 NTSTATUS
2270 USB_BUSIFFN
2271 USBHI_InitializeUsbDevice(
2272 PVOID BusContext,
2273 PUSB_DEVICE_HANDLE DeviceHandle)
2274 {
2275 PUSBDEVICE UsbDevice;
2276 CHubController * Controller;
2277 ULONG DeviceAddress;
2278 NTSTATUS Status;
2279 ULONG Index = 0;
2280
2281 DPRINT1("USBHI_InitializeUsbDevice\n");
2282
2283 //
2284 // first get controller
2285 //
2286 Controller = (CHubController *)BusContext;
2287 PC_ASSERT(Controller);
2288
2289 //
2290 // get device object
2291 //
2292 UsbDevice = (PUSBDEVICE)DeviceHandle;
2293 PC_ASSERT(UsbDevice);
2294
2295 //
2296 // validate device handle
2297 //
2298 if (!Controller->ValidateUsbDevice(UsbDevice))
2299 {
2300 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
2301
2302 //
2303 // invalid device handle
2304 //
2305 return STATUS_DEVICE_NOT_CONNECTED;
2306 }
2307
2308 //
2309 // now reserve an address
2310 //
2311 DeviceAddress = Controller->AcquireDeviceAddress();
2312
2313 //
2314 // is the device address valid
2315 //
2316 if (DeviceAddress == MAXULONG)
2317 {
2318 //
2319 // failed to get an device address from the device address pool
2320 //
2321 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2322 return STATUS_DEVICE_DATA_ERROR;
2323 }
2324
2325 do
2326 {
2327 //
2328 // now set the device address
2329 //
2330 Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
2331
2332 if (NT_SUCCESS(Status))
2333 break;
2334
2335 }while(Index++ < 3 );
2336
2337 //
2338 // check for failure
2339 //
2340 if (!NT_SUCCESS(Status))
2341 {
2342 //
2343 // failed to set device address
2344 //
2345 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
2346
2347 //
2348 // release address
2349 //
2350 Controller->ReleaseDeviceAddress(DeviceAddress);
2351
2352 //
2353 // return error
2354 //
2355 return STATUS_DEVICE_DATA_ERROR;
2356 }
2357
2358 //
2359 // done
2360 //
2361 return STATUS_SUCCESS;
2362 }
2363
2364 NTSTATUS
2365 USB_BUSIFFN
2366 USBHI_GetUsbDescriptors(
2367 PVOID BusContext,
2368 PUSB_DEVICE_HANDLE DeviceHandle,
2369 PUCHAR DeviceDescriptorBuffer,
2370 PULONG DeviceDescriptorBufferLength,
2371 PUCHAR ConfigDescriptorBuffer,
2372 PULONG ConfigDescriptorBufferLength)
2373 {
2374 PUSBDEVICE UsbDevice;
2375 CHubController * Controller;
2376
2377 DPRINT1("USBHI_GetUsbDescriptors\n");
2378
2379 //
2380 // sanity check
2381 //
2382 PC_ASSERT(DeviceDescriptorBuffer);
2383 PC_ASSERT(DeviceDescriptorBufferLength);
2384 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
2385 PC_ASSERT(ConfigDescriptorBufferLength);
2386 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
2387
2388 //
2389 // first get controller
2390 //
2391 Controller = (CHubController *)BusContext;
2392 PC_ASSERT(Controller);
2393
2394
2395 //
2396 // get device object
2397 //
2398 UsbDevice = (PUSBDEVICE)DeviceHandle;
2399 PC_ASSERT(UsbDevice);
2400
2401 //
2402 // validate device handle
2403 //
2404 if (!Controller->ValidateUsbDevice(UsbDevice))
2405 {
2406 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
2407
2408 //
2409 // invalid device handle
2410 //
2411 return STATUS_DEVICE_NOT_CONNECTED;
2412 }
2413
2414 //
2415 // get device descriptor
2416 //
2417 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
2418
2419 //
2420 // store result length
2421 //
2422 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
2423
2424 //
2425 // get configuration descriptor
2426 //
2427 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
2428
2429 //
2430 // complete the request
2431 //
2432 return STATUS_SUCCESS;
2433 }
2434
2435 NTSTATUS
2436 USB_BUSIFFN
2437 USBHI_RemoveUsbDevice(
2438 PVOID BusContext,
2439 PUSB_DEVICE_HANDLE DeviceHandle,
2440 ULONG Flags)
2441 {
2442 PUSBDEVICE UsbDevice;
2443 CHubController * Controller;
2444 NTSTATUS Status;
2445
2446 DPRINT1("USBHI_RemoveUsbDevice\n");
2447
2448 //
2449 // first get controller
2450 //
2451 Controller = (CHubController *)BusContext;
2452 PC_ASSERT(Controller);
2453
2454 //
2455 // get device object
2456 //
2457 UsbDevice = (PUSBDEVICE)DeviceHandle;
2458 PC_ASSERT(UsbDevice);
2459
2460 //
2461 // validate device handle
2462 //
2463 if (!Controller->ValidateUsbDevice(UsbDevice))
2464 {
2465 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
2466
2467 //
2468 // invalid device handle
2469 //
2470 return STATUS_DEVICE_NOT_CONNECTED;
2471 }
2472
2473 //
2474 // check if there were flags passed
2475 //
2476 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
2477 {
2478 //
2479 // ignore flags for now
2480 //
2481 return STATUS_SUCCESS;
2482 }
2483
2484 //
2485 // remove device
2486 //
2487 Status = Controller->RemoveUsbDevice(UsbDevice);
2488 if (!NT_SUCCESS(Status))
2489 {
2490 //
2491 // invalid device handle
2492 //
2493 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
2494 PC_ASSERT(0);
2495 return STATUS_DEVICE_NOT_CONNECTED;
2496 }
2497
2498 //
2499 // release usb device
2500 //
2501 UsbDevice->Release();
2502
2503 //
2504 // done
2505 //
2506 return STATUS_SUCCESS;
2507 }
2508
2509 NTSTATUS
2510 USB_BUSIFFN
2511 USBHI_RestoreUsbDevice(
2512 PVOID BusContext,
2513 PUSB_DEVICE_HANDLE OldDeviceHandle,
2514 PUSB_DEVICE_HANDLE NewDeviceHandle)
2515 {
2516 PUSBDEVICE OldUsbDevice, NewUsbDevice;
2517 CHubController * Controller;
2518
2519 DPRINT1("USBHI_RestoreUsbDevice\n");
2520
2521 //
2522 // first get controller
2523 //
2524 Controller = (CHubController *)BusContext;
2525 PC_ASSERT(Controller);
2526
2527 //
2528 // get device object
2529 //
2530 OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
2531 NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
2532 PC_ASSERT(OldUsbDevice);
2533 PC_ASSERT(NewDeviceHandle);
2534
2535 //
2536 // validate device handle
2537 //
2538 PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
2539 PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
2540
2541 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
2542 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
2543
2544 //
2545 // remove old device handle
2546 //
2547 USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
2548
2549 return STATUS_SUCCESS;
2550 }
2551
2552 NTSTATUS
2553 USB_BUSIFFN
2554 USBHI_QueryDeviceInformation(
2555 PVOID BusContext,
2556 PUSB_DEVICE_HANDLE DeviceHandle,
2557 PVOID DeviceInformationBuffer,
2558 ULONG DeviceInformationBufferLength,
2559 PULONG LengthReturned)
2560 {
2561 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
2562 PUSBDEVICE UsbDevice;
2563 CHubController * Controller;
2564
2565 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
2566
2567 //
2568 // sanity check
2569 //
2570 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
2571 PC_ASSERT(DeviceInformationBuffer);
2572 PC_ASSERT(LengthReturned);
2573
2574 //
2575 // get controller object
2576 //
2577 Controller = (CHubController*)BusContext;
2578 PC_ASSERT(Controller);
2579
2580 //
2581 // get device object
2582 //
2583 UsbDevice = (PUSBDEVICE)DeviceHandle;
2584 PC_ASSERT(UsbDevice);
2585
2586 if (BusContext != DeviceHandle)
2587 {
2588 //
2589 // validate device handle
2590 //
2591 if (!Controller->ValidateUsbDevice(UsbDevice))
2592 {
2593 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
2594
2595 //
2596 // invalid device handle
2597 //
2598 return STATUS_DEVICE_NOT_CONNECTED;
2599 }
2600
2601 //
2602 // access information buffer
2603 //
2604 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2605
2606 //
2607 // initialize with default values
2608 //
2609 DeviceInfo->InformationLevel = 0;
2610 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2611 DeviceInfo->PortNumber = UsbDevice->GetPort();
2612 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
2613 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
2614 DeviceInfo->HubAddress = 0; //FIXME
2615 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
2616 DeviceInfo->DeviceType = UsbDevice->GetType();
2617 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2618
2619 //
2620 // get device descriptor
2621 //
2622 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
2623
2624 //
2625 // FIXME return pipe information
2626 //
2627
2628 //
2629 // store result length
2630 //
2631 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
2632
2633 return STATUS_SUCCESS;
2634 }
2635
2636 //
2637 // access information buffer
2638 //
2639 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2640
2641 //
2642 // initialize with default values
2643 //
2644 DeviceInfo->InformationLevel = 0;
2645 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2646 DeviceInfo->PortNumber = 0;
2647 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
2648 DeviceInfo->DeviceAddress = 0;
2649 DeviceInfo->HubAddress = 0; //FIXME
2650 DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
2651 DeviceInfo->DeviceType = Usb20Device; //FIXME
2652 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2653
2654 //
2655 // get device descriptor
2656 //
2657 RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
2658
2659 //
2660 // FIXME return pipe information
2661 //
2662
2663 //
2664 // store result length
2665 //
2666 #ifdef _MSC_VER
2667 *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
2668 #else
2669 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
2670 #endif
2671 //
2672 // done
2673 //
2674 return STATUS_SUCCESS;
2675 }
2676
2677 NTSTATUS
2678 USB_BUSIFFN
2679 USBHI_GetControllerInformation(
2680 PVOID BusContext,
2681 PVOID ControllerInformationBuffer,
2682 ULONG ControllerInformationBufferLength,
2683 PULONG LengthReturned)
2684 {
2685 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
2686
2687 DPRINT1("USBHI_GetControllerInformation\n");
2688
2689 //
2690 // sanity checks
2691 //
2692 PC_ASSERT(ControllerInformationBuffer);
2693 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
2694
2695 //
2696 // get controller info buffer
2697 //
2698 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
2699
2700 //
2701 // FIXME only version 0 is supported for now
2702 //
2703 PC_ASSERT(ControllerInfo->InformationLevel == 0);
2704
2705 //
2706 // fill in information
2707 //
2708 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
2709 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
2710 ControllerInfo->IsHighSpeedController = TRUE;
2711
2712 //
2713 // set length returned
2714 //
2715 *LengthReturned = ControllerInfo->ActualLength;
2716
2717 //
2718 // done
2719 //
2720 return STATUS_SUCCESS;
2721 }
2722
2723 NTSTATUS
2724 USB_BUSIFFN
2725 USBHI_ControllerSelectiveSuspend(
2726 PVOID BusContext,
2727 BOOLEAN Enable)
2728 {
2729 UNIMPLEMENTED
2730 return STATUS_NOT_IMPLEMENTED;
2731 }
2732
2733 NTSTATUS
2734 USB_BUSIFFN
2735 USBHI_GetExtendedHubInformation(
2736 PVOID BusContext,
2737 PDEVICE_OBJECT HubPhysicalDeviceObject,
2738 PVOID HubInformationBuffer,
2739 ULONG HubInformationBufferLength,
2740 PULONG LengthReturned)
2741 {
2742 PUSB_EXTHUB_INFORMATION_0 HubInfo;
2743 CHubController * Controller;
2744 PUSBHARDWAREDEVICE Hardware;
2745 ULONG Index;
2746 ULONG NumPort, Dummy2;
2747 USHORT Dummy1;
2748 NTSTATUS Status;
2749
2750 DPRINT1("USBHI_GetExtendedHubInformation\n");
2751
2752 //
2753 // sanity checks
2754 //
2755 PC_ASSERT(HubInformationBuffer);
2756 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
2757 PC_ASSERT(LengthReturned);
2758
2759 //
2760 // get hub controller
2761 //
2762 Controller = (CHubController *)BusContext;
2763 PC_ASSERT(Controller);
2764
2765 //
2766 // get usb hardware device
2767 //
2768 Hardware = Controller->GetUsbHardware();
2769
2770 //
2771 // retrieve number of ports
2772 //
2773 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
2774 if (!NT_SUCCESS(Status))
2775 {
2776 //
2777 // failed to get hardware details, ouch ;)
2778 //
2779 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
2780 return Status;
2781 }
2782
2783 //
2784 // get hub information buffer
2785 //
2786 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
2787
2788 //
2789 // initialize hub information
2790 //
2791 HubInfo->InformationLevel = 0;
2792
2793 //
2794 // store port count
2795 //
2796 HubInfo->NumberOfPorts = NumPort;
2797
2798 //
2799 // initialize port information
2800 //
2801 for(Index = 0; Index < NumPort; Index++)
2802 {
2803 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
2804 HubInfo->Port[Index].PortLabelNumber = Index + 1;
2805 HubInfo->Port[Index].VidOverride = 0;
2806 HubInfo->Port[Index].PidOverride = 0;
2807 HubInfo->Port[Index].PortAttributes = USB_PORTATTR_SHARED_USB2; //FIXME
2808 }
2809
2810 //
2811 // store result length
2812 //
2813 #ifdef _MSC_VER
2814 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
2815 #else
2816 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
2817 #endif
2818
2819 //
2820 // done
2821 //
2822 return STATUS_SUCCESS;
2823 }
2824
2825 NTSTATUS
2826 USB_BUSIFFN
2827 USBHI_GetRootHubSymbolicName(
2828 PVOID BusContext,
2829 PVOID HubSymNameBuffer,
2830 ULONG HubSymNameBufferLength,
2831 PULONG HubSymNameActualLength)
2832 {
2833 UNIMPLEMENTED
2834 return STATUS_NOT_IMPLEMENTED;
2835 }
2836
2837 PVOID
2838 USB_BUSIFFN
2839 USBHI_GetDeviceBusContext(
2840 PVOID HubBusContext,
2841 PVOID DeviceHandle)
2842 {
2843 UNIMPLEMENTED
2844 return NULL;
2845 }
2846
2847 NTSTATUS
2848 USB_BUSIFFN
2849 USBHI_Initialize20Hub(
2850 PVOID BusContext,
2851 PUSB_DEVICE_HANDLE HubDeviceHandle,
2852 ULONG TtCount)
2853 {
2854 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle, TtCount);
2855 return STATUS_SUCCESS;
2856 }
2857
2858 NTSTATUS
2859 USB_BUSIFFN
2860 USBHI_RootHubInitNotification(
2861 PVOID BusContext,
2862 PVOID CallbackContext,
2863 PRH_INIT_CALLBACK CallbackRoutine)
2864 {
2865 CHubController * Controller;
2866
2867 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
2868
2869 //
2870 // get controller object
2871 //
2872 Controller = (CHubController*)BusContext;
2873 PC_ASSERT(Controller);
2874
2875 //
2876 // set notification routine
2877 //
2878 Controller->SetNotification(CallbackContext, CallbackRoutine);
2879
2880 //
2881 // FIXME: determine when to perform callback
2882 //
2883 CallbackRoutine(CallbackContext);
2884
2885 //
2886 // done
2887 //
2888 return STATUS_SUCCESS;
2889 }
2890
2891 VOID
2892 USB_BUSIFFN
2893 USBHI_FlushTransfers(
2894 PVOID BusContext,
2895 PVOID DeviceHandle)
2896 {
2897 UNIMPLEMENTED
2898 }
2899
2900 VOID
2901 USB_BUSIFFN
2902 USBHI_SetDeviceHandleData(
2903 PVOID BusContext,
2904 PVOID DeviceHandle,
2905 PDEVICE_OBJECT UsbDevicePdo)
2906 {
2907 PUSBDEVICE UsbDevice;
2908 CHubController * Controller;
2909
2910 //
2911 // get controller
2912 //
2913 Controller = (CHubController *)BusContext;
2914 PC_ASSERT(Controller);
2915
2916 //
2917 // get device handle
2918 //
2919 UsbDevice = (PUSBDEVICE)DeviceHandle;
2920
2921 //
2922 // validate device handle
2923 //
2924 if (!Controller->ValidateUsbDevice(UsbDevice))
2925 {
2926 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
2927
2928 //
2929 // invalid handle
2930 //
2931 return;
2932 }
2933 else
2934 {
2935 //
2936 // usbhub sends this request as a part of the Pnp startup sequence
2937 // looks like we need apply a dragon voodoo to fixup the device stack
2938 // otherwise usbhub will cause a bugcheck
2939 //
2940 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo);
2941
2942 //
2943 // sanity check
2944 //
2945 PC_ASSERT(UsbDevicePdo->AttachedDevice);
2946
2947 //
2948 // should be usbstor
2949 // fixup device stack voodoo part #2
2950 //
2951 UsbDevicePdo->AttachedDevice->StackSize++;
2952
2953 //
2954 // set device handle data
2955 //
2956 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
2957 }
2958 }
2959
2960 //=================================================================================================
2961 //
2962 // USB Device Interface functions
2963 //
2964
2965 VOID
2966 USB_BUSIFFN
2967 USBDI_GetUSBDIVersion(
2968 PVOID BusContext,
2969 PUSBD_VERSION_INFORMATION VersionInformation,
2970 PULONG HcdCapabilites)
2971 {
2972 CHubController * Controller;
2973 PUSBHARDWAREDEVICE Device;
2974 ULONG Speed, Dummy2;
2975 USHORT Dummy1;
2976
2977 DPRINT1("USBDI_GetUSBDIVersion\n");
2978
2979 //
2980 // get controller
2981 //
2982 Controller = (CHubController*)BusContext;
2983
2984 //
2985 // get usb hardware
2986 //
2987 Device = Controller->GetUsbHardware();
2988 PC_ASSERT(Device);
2989
2990 if (VersionInformation)
2991 {
2992 //
2993 // windows xp supported
2994 //
2995 VersionInformation->USBDI_Version = 0x00000500;
2996
2997 //
2998 // get device speed
2999 //
3000 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3001
3002 //
3003 // store speed details
3004 //
3005 VersionInformation->Supported_USB_Version = Speed;
3006 }
3007
3008 //
3009 // no flags supported
3010 //
3011 *HcdCapabilites = 0;
3012 }
3013
3014 NTSTATUS
3015 USB_BUSIFFN
3016 USBDI_QueryBusTime(
3017 PVOID BusContext,
3018 PULONG CurrentFrame)
3019 {
3020 UNIMPLEMENTED
3021 return STATUS_NOT_IMPLEMENTED;
3022 }
3023
3024 NTSTATUS
3025 USB_BUSIFFN
3026 USBDI_SubmitIsoOutUrb(
3027 PVOID BusContext,
3028 PURB Urb)
3029 {
3030 UNIMPLEMENTED
3031 return STATUS_NOT_IMPLEMENTED;
3032 }
3033
3034 NTSTATUS
3035 USB_BUSIFFN
3036 USBDI_QueryBusInformation(
3037 PVOID BusContext,
3038 ULONG Level,
3039 PVOID BusInformationBuffer,
3040 PULONG BusInformationBufferLength,
3041 PULONG BusInformationActualLength)
3042 {
3043 UNIMPLEMENTED
3044 return STATUS_NOT_IMPLEMENTED;
3045 }
3046
3047 BOOLEAN
3048 USB_BUSIFFN
3049 USBDI_IsDeviceHighSpeed(
3050 PVOID BusContext)
3051 {
3052 CHubController * Controller;
3053 PUSBHARDWAREDEVICE Device;
3054 ULONG Speed, Dummy2;
3055 USHORT Dummy1;
3056
3057 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3058
3059 //
3060 // get controller
3061 //
3062 Controller = (CHubController*)BusContext;
3063
3064 //
3065 // get usb hardware
3066 //
3067 Device = Controller->GetUsbHardware();
3068 PC_ASSERT(Device);
3069
3070 //
3071 // get device speed
3072 //
3073 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3074
3075 //
3076 // USB 2.0 equals 0x200
3077 //
3078 return (Speed == 0x200);
3079 }
3080
3081 NTSTATUS
3082 USB_BUSIFFN
3083 USBDI_EnumLogEntry(
3084 PVOID BusContext,
3085 ULONG DriverTag,
3086 ULONG EnumTag,
3087 ULONG P1,
3088 ULONG P2)
3089 {
3090 UNIMPLEMENTED
3091 return STATUS_NOT_IMPLEMENTED;
3092 }
3093
3094 NTSTATUS
3095 CHubController::HandleQueryInterface(
3096 PIO_STACK_LOCATION IoStack)
3097 {
3098 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
3099 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
3100 UNICODE_STRING GuidBuffer;
3101 NTSTATUS Status;
3102
3103 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
3104 {
3105 //
3106 // get request parameters
3107 //
3108 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
3109 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
3110
3111 //
3112 // check version
3113 //
3114 if (IoStack->Parameters.QueryInterface.Version >= 6)
3115 {
3116 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3117
3118 //
3119 // version not supported
3120 //
3121 return STATUS_NOT_SUPPORTED;
3122 }
3123
3124 //
3125 // Interface version 0
3126 //
3127 if (IoStack->Parameters.QueryInterface.Version >= 0)
3128 {
3129 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
3130 InterfaceHub->BusContext = PVOID(this);
3131 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
3132 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
3133 }
3134
3135 //
3136 // Interface version 1
3137 //
3138 if (IoStack->Parameters.QueryInterface.Version >= 1)
3139 {
3140 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
3141 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
3142 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
3143 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
3144 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
3145 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
3146 }
3147
3148 //
3149 // Interface version 2
3150 //
3151 if (IoStack->Parameters.QueryInterface.Version >= 2)
3152 {
3153 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
3154 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
3155 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
3156 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
3157 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
3158 InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
3159
3160 }
3161
3162 //
3163 // Interface version 3
3164 //
3165 if (IoStack->Parameters.QueryInterface.Version >= 3)
3166 {
3167 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
3168 }
3169
3170 //
3171 // Interface version 4
3172 //
3173 if (IoStack->Parameters.QueryInterface.Version >= 4)
3174 {
3175 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
3176 }
3177
3178 //
3179 // Interface version 5
3180 //
3181 if (IoStack->Parameters.QueryInterface.Version >= 5)
3182 {
3183 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
3184 }
3185
3186 //
3187 // request completed
3188 //
3189 return STATUS_SUCCESS;
3190 }
3191 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
3192 {
3193 //
3194 // get request parameters
3195 //
3196 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
3197 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
3198
3199 //
3200 // check version
3201 //
3202 if (IoStack->Parameters.QueryInterface.Version >= 3)
3203 {
3204 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3205
3206 //
3207 // version not supported
3208 //
3209 return STATUS_NOT_SUPPORTED;
3210 }
3211
3212 //
3213 // interface version 0
3214 //
3215 if (IoStack->Parameters.QueryInterface.Version >= 0)
3216 {
3217 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
3218 InterfaceDI->BusContext = PVOID(this);
3219 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
3220 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
3221 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
3222 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
3223 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
3224 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
3225 }
3226
3227 //
3228 // interface version 1
3229 //
3230 if (IoStack->Parameters.QueryInterface.Version >= 1)
3231 {
3232 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
3233 }
3234
3235 //
3236 // interface version 2
3237 //
3238 if (IoStack->Parameters.QueryInterface.Version >= 2)
3239 {
3240 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
3241 }
3242
3243 //
3244 // request completed
3245 //
3246 return STATUS_SUCCESS;
3247 }
3248 else
3249 {
3250 //
3251 // convert guid to string
3252 //
3253 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
3254 if (NT_SUCCESS(Status))
3255 {
3256 //
3257 // print interface
3258 //
3259 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
3260
3261 //
3262 // free guid buffer
3263 //
3264 RtlFreeUnicodeString(&GuidBuffer);
3265 }
3266 }
3267 return STATUS_NOT_SUPPORTED;
3268 }
3269
3270 NTSTATUS
3271 CHubController::SetDeviceInterface(
3272 BOOLEAN Enable)
3273 {
3274 NTSTATUS Status = STATUS_SUCCESS;
3275
3276 if (Enable)
3277 {
3278 //
3279 // register device interface
3280 //
3281 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
3282
3283 if (NT_SUCCESS(Status))
3284 {
3285 //
3286 // now enable the device interface
3287 //
3288 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
3289
3290 //
3291 // enable interface
3292 //
3293 m_InterfaceEnabled = TRUE;
3294 }
3295 }
3296 else if (m_InterfaceEnabled)
3297 {
3298 //
3299 // disable device interface
3300 //
3301 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
3302
3303 if (NT_SUCCESS(Status))
3304 {
3305 //
3306 // now delete interface string
3307 //
3308 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
3309 }
3310
3311 //
3312 // disable interface
3313 //
3314 m_InterfaceEnabled = FALSE;
3315 }
3316
3317 //
3318 // done
3319 //
3320 return STATUS_SUCCESS;
3321 }
3322
3323 NTSTATUS
3324 CHubController::CreatePDO(
3325 PDRIVER_OBJECT DriverObject,
3326 PDEVICE_OBJECT * OutDeviceObject)
3327 {
3328 WCHAR CharDeviceName[64];
3329 NTSTATUS Status;
3330 ULONG UsbDeviceNumber = 0;
3331 UNICODE_STRING DeviceName;
3332
3333 while (TRUE)
3334 {
3335 //
3336 // construct device name
3337 //
3338 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
3339
3340 //
3341 // initialize device name
3342 //
3343 RtlInitUnicodeString(&DeviceName, CharDeviceName);
3344
3345 //
3346 // create device
3347 //
3348 Status = IoCreateDevice(DriverObject,
3349 sizeof(COMMON_DEVICE_EXTENSION),
3350 &DeviceName,
3351 FILE_DEVICE_CONTROLLER,
3352 0,
3353 FALSE,
3354 OutDeviceObject);
3355
3356 /* check for success */
3357 if (NT_SUCCESS(Status))
3358 break;
3359
3360 //
3361 // is there a device object with that same name
3362 //
3363 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
3364 {
3365 //
3366 // Try the next name
3367 //
3368 UsbDeviceNumber++;
3369 continue;
3370 }
3371
3372 //
3373 // bail out on other errors
3374 //
3375 if (!NT_SUCCESS(Status))
3376 {
3377 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
3378 return Status;
3379 }
3380 }
3381
3382 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
3383
3384 //
3385 // fixup device stack voodoo part #1
3386 //
3387 (*OutDeviceObject)->StackSize++;
3388
3389 /* done */
3390 return Status;
3391 }
3392
3393
3394
3395 NTSTATUS
3396 CreateHubController(
3397 PHUBCONTROLLER *OutHcdController)
3398 {
3399 PHUBCONTROLLER This;
3400
3401 //
3402 // allocate controller
3403 //
3404 This = new(NonPagedPool, TAG_USBEHCI) CHubController(0);
3405 if (!This)
3406 {
3407 //
3408 // failed to allocate
3409 //
3410 return STATUS_INSUFFICIENT_RESOURCES;
3411 }
3412
3413 //
3414 // add reference count
3415 //
3416 This->AddRef();
3417
3418 //
3419 // return result
3420 //
3421 *OutHcdController = (PHUBCONTROLLER)This;
3422
3423 //
3424 // done
3425 //
3426 return STATUS_SUCCESS;
3427 }
3428
3429 VOID StatusChangeEndpointCallBack(PVOID Context)
3430 {
3431 CHubController* This;
3432 PIRP Irp;
3433 This = (CHubController*)Context;
3434
3435 ASSERT(This);
3436
3437 Irp = This->m_PendingSCEIrp;
3438 if (!Irp)
3439 {
3440 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3441 return;
3442 }
3443
3444 This->m_PendingSCEIrp = NULL;
3445 This->QueryStatusChageEndpoint(Irp);
3446
3447 Irp->IoStatus.Status = STATUS_SUCCESS;
3448 Irp->IoStatus.Information = 0;
3449
3450 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3451 }