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