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