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