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