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