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