[USBOHCI]
[reactos.git] / drivers / usb / usbohci / hub_controller.cpp
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbohci/hub_controller.cpp
5 * PURPOSE: USB OHCI device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #define INITGUID
12 #include "usbohci.h"
13
14 VOID StatusChangeEndpointCallBack(
15 PVOID Context);
16
17 class CHubController : public IHubController,
18 public IDispatchIrp
19 {
20 public:
21 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
22
23 STDMETHODIMP_(ULONG) AddRef()
24 {
25 InterlockedIncrement(&m_Ref);
26 return m_Ref;
27 }
28 STDMETHODIMP_(ULONG) Release()
29 {
30 InterlockedDecrement(&m_Ref);
31
32 if (!m_Ref)
33 {
34 delete this;
35 return 0;
36 }
37 return m_Ref;
38 }
39
40 // IHubController interface functions
41 virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject, IN PHCDCONTROLLER Controller, IN PUSBHARDWAREDEVICE Device, IN BOOLEAN IsRootHubDevice, IN ULONG DeviceAddress);
42 virtual NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject);
43 virtual NTSTATUS GetHubControllerSymbolicLink(ULONG BufferLength, PVOID Buffer, PULONG RequiredLength);
44
45 // IDispatchIrp interface functions
46 virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
47 virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
48 virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
49
50 // local functions
51 NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack);
52 NTSTATUS SetDeviceInterface(BOOLEAN bEnable);
53 NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
54 PUSBHARDWAREDEVICE GetUsbHardware();
55 ULONG AcquireDeviceAddress();
56 VOID ReleaseDeviceAddress(ULONG DeviceAddress);
57 BOOLEAN ValidateUsbDevice(PUSBDEVICE UsbDevice);
58 NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice);
59 NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice);
60 VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
61 // internal ioctl routines
62 NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
63 NTSTATUS HandleGetDescriptorFromInterface(IN OUT PIRP Irp, PURB Urb);
64 NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
65 NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
66 NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
67 NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb);
68 NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
69 NTSTATUS HandleClassInterface(IN OUT PIRP Irp, PURB Urb);
70 NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb);
71 NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
72 NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb);
73
74 friend VOID StatusChangeEndpointCallBack(PVOID Context);
75
76 // constructor / destructor
77 CHubController(IUnknown *OuterUnknown){}
78 virtual ~CHubController(){}
79
80 protected:
81 LONG m_Ref;
82 PHCDCONTROLLER m_Controller;
83 PUSBHARDWAREDEVICE m_Hardware;
84 BOOLEAN m_IsRootHubDevice;
85 ULONG m_DeviceAddress;
86
87 BOOLEAN m_InterfaceEnabled;
88 UNICODE_STRING m_HubDeviceInterfaceString;
89
90 PDEVICE_OBJECT m_HubControllerDeviceObject;
91 PDRIVER_OBJECT m_DriverObject;
92
93 PVOID m_HubCallbackContext;
94 PRH_INIT_CALLBACK m_HubCallbackRoutine;
95
96 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
97
98 KSPIN_LOCK m_Lock;
99 RTL_BITMAP m_DeviceAddressBitmap;
100 PULONG m_DeviceAddressBitmapBuffer;
101 LIST_ENTRY m_UsbDeviceList;
102 PIRP m_PendingSCEIrp;
103
104 //Internal Functions
105 BOOLEAN QueryStatusChageEndpoint(PIRP Irp);
106 };
107
108 typedef struct
109 {
110 LIST_ENTRY Entry;
111 PUSBDEVICE Device;
112 }USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY;
113
114 /* Lifted from Linux with slight changes */
115 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
116 {
117 0x12, /* bLength; */
118 USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */
119 0x00, 0x20, /* bcdUSB; v1.1 */
120 USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */
121 0x01, /* bDeviceSubClass; */
122 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
123 0x08, /* bMaxPacketSize0; 8 Bytes */
124 /* Fill Vendor and Product in when init root hub */
125 0x00, 0x00, /* idVendor; */
126 0x00, 0x00, /* idProduct; */
127 0x00, 0x00, /* bcdDevice */
128 0x00, /* iManufacturer; */
129 0x00, /* iProduct; */
130 0x00, /* iSerialNumber; */
131 0x01 /* bNumConfigurations; */
132
133 };
134
135 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR =
136 {
137 sizeof(USB_CONFIGURATION_DESCRIPTOR),
138 USB_CONFIGURATION_DESCRIPTOR_TYPE,
139 sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
140 1,
141 1,
142 0,
143 0x40, /* self powered */
144 0x0
145 };
146
147 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR =
148 {
149 sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */
150 USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType; Interface */
151 0, /* bInterfaceNumber; */
152 0, /* bAlternateSetting; */
153 0x1, /* bNumEndpoints; */
154 0x09, /* bInterfaceClass; HUB_CLASSCODE */
155 0x01, /* bInterfaceSubClass; */
156 0x00, /* bInterfaceProtocol: */
157 0x00, /* iInterface; */
158 };
159
160 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR =
161 {
162 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */
163 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
164 0x81, /* bEndPointAddress */
165 USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
166 0x01, /* wMaxPacketSize */
167 0xC /* bInterval */
168 };
169
170 //----------------------------------------------------------------------------------------
171 NTSTATUS
172 STDMETHODCALLTYPE
173 CHubController::QueryInterface(
174 IN REFIID refiid,
175 OUT PVOID* Output)
176 {
177 return STATUS_UNSUCCESSFUL;
178 }
179 //----------------------------------------------------------------------------------------
180 NTSTATUS
181 CHubController::Initialize(
182 IN PDRIVER_OBJECT DriverObject,
183 IN PHCDCONTROLLER Controller,
184 IN PUSBHARDWAREDEVICE Device,
185 IN BOOLEAN IsRootHubDevice,
186 IN ULONG DeviceAddress)
187 {
188 NTSTATUS Status;
189 PCOMMON_DEVICE_EXTENSION DeviceExtension;
190 USHORT VendorID, DeviceID;
191 ULONG Dummy1;
192
193 DPRINT1("CHubController::Initialize\n");
194
195 //
196 // initialize members
197 //
198 m_Controller = Controller;
199 m_Hardware = Device;
200 m_IsRootHubDevice = IsRootHubDevice;
201 m_DeviceAddress = DeviceAddress;
202 m_DriverObject = DriverObject;
203 KeInitializeSpinLock(&m_Lock);
204 InitializeListHead(&m_UsbDeviceList);
205
206 //
207 // allocate device address bitmap buffer
208 //
209 m_DeviceAddressBitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, 16, TAG_USBOHCI);
210 if (!m_DeviceAddressBitmapBuffer)
211 {
212 //
213 // no memory
214 //
215 return STATUS_INSUFFICIENT_RESOURCES;
216 }
217
218 //
219 // initialize device address bitmap
220 //
221 RtlInitializeBitMap(&m_DeviceAddressBitmap, m_DeviceAddressBitmapBuffer, 128);
222 RtlClearAllBits(&m_DeviceAddressBitmap);
223
224
225 //
226 // create PDO
227 //
228 Status = CreatePDO(m_DriverObject, &m_HubControllerDeviceObject);
229 if (!NT_SUCCESS(Status))
230 {
231 //
232 // failed to create hub device object
233 //
234 return Status;
235 }
236
237 //
238 // get device extension
239 //
240 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_HubControllerDeviceObject->DeviceExtension;
241
242 //
243 // initialize device extension
244 //
245 DeviceExtension->IsFDO = FALSE;
246 DeviceExtension->IsHub = TRUE; //FIXME
247 DeviceExtension->Dispatcher = PDISPATCHIRP(this);
248
249 //
250 // intialize device descriptor
251 //
252 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
253 RtlMoveMemory(&m_DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
254
255 if (NT_SUCCESS(m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &Dummy1, &Dummy1)))
256 {
257 //
258 // update device descriptor
259 //
260 m_DeviceDescriptor.idVendor = VendorID;
261 m_DeviceDescriptor.idProduct = DeviceID;
262 m_DeviceDescriptor.bcdUSB = 0x110; //FIXME
263 }
264
265 //
266 // Set the SCE Callback that the Hardware Device will call on port status change
267 //
268 Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this);
269
270 //
271 // clear init flag
272 //
273 m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
274
275 return STATUS_SUCCESS;
276 }
277
278 //
279 // Queries the ports to see if there has been a device connected or removed.
280 //
281 BOOLEAN
282 CHubController::QueryStatusChageEndpoint(
283 PIRP Irp)
284 {
285 ULONG PortCount, PortId;
286 PIO_STACK_LOCATION IoStack;
287 USHORT PortStatus, PortChange;
288 PURB Urb;
289 PUCHAR TransferBuffer;
290 UCHAR Changed = FALSE;
291
292 //
293 // get current stack location
294 //
295 IoStack = IoGetCurrentIrpStackLocation(Irp);
296 ASSERT(IoStack);
297
298 //
299 // Get the Urb
300 //
301 Urb = (PURB)IoStack->Parameters.Others.Argument1;
302 ASSERT(Urb);
303
304 //
305 // Get the number of ports and check each one for device connected
306 //
307 m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
308 DPRINT1("SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, Urb->UrbBulkOrInterruptTransfer.TransferFlags, Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
309
310 TransferBuffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer;
311
312 //
313 // Loop the ports
314 //
315 for (PortId = 0; PortId < PortCount; PortId++)
316 {
317 m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
318
319 DPRINT1("Port %d: Status %x, Change %x\n", PortId, PortStatus, PortChange);
320
321
322 //
323 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
324 //
325 if (PortChange != 0)
326 {
327 DPRINT1("Change state on port %d\n", PortId);
328 // Set the value for the port number
329 *TransferBuffer = 1 << ((PortId + 1) & 7);
330 Changed = TRUE;
331 }
332 }
333
334 return Changed;
335 }
336
337 //-----------------------------------------------------------------------------------------
338 NTSTATUS
339 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject)
340 {
341 //
342 // store controller object
343 //
344 *HubDeviceObject = m_HubControllerDeviceObject;
345
346 return STATUS_SUCCESS;
347 }
348 //-----------------------------------------------------------------------------------------
349 NTSTATUS
350 CHubController::GetHubControllerSymbolicLink(
351 ULONG BufferLength,
352 PVOID Buffer,
353 PULONG RequiredLength)
354 {
355 if (!m_InterfaceEnabled)
356 {
357 //
358 // device interface not yet enabled
359 //
360 return STATUS_UNSUCCESSFUL;
361 }
362
363 if (BufferLength < (ULONG)m_HubDeviceInterfaceString.Length - 8)
364 {
365 //
366 // buffer too small
367 // length is without '\??\'
368 //
369 *RequiredLength = m_HubDeviceInterfaceString.Length- 8;
370
371 //
372 // done
373 //
374 return STATUS_BUFFER_OVERFLOW;
375 }
376
377 //
378 // copy symbolic link
379 //
380 RtlCopyMemory(Buffer, &m_HubDeviceInterfaceString.Buffer[4], m_HubDeviceInterfaceString.Length - 8);
381
382 //
383 // store length, length is without '\??\'
384 //
385 *RequiredLength = m_HubDeviceInterfaceString.Length - 8;
386
387 //
388 // done
389 //
390 return STATUS_SUCCESS;
391 }
392
393 //-----------------------------------------------------------------------------------------
394 NTSTATUS
395 CHubController::HandlePnp(
396 IN PDEVICE_OBJECT DeviceObject,
397 IN OUT PIRP Irp)
398 {
399 PIO_STACK_LOCATION IoStack;
400 PCOMMON_DEVICE_EXTENSION DeviceExtension;
401 PDEVICE_CAPABILITIES DeviceCapabilities;
402 PPNP_BUS_INFORMATION BusInformation;
403 PDEVICE_RELATIONS DeviceRelations;
404 NTSTATUS Status;
405 ULONG Index = 0, Length;
406 USHORT VendorID, DeviceID;
407 ULONG HiSpeed, NumPorts;
408 WCHAR Buffer[300];
409 LPWSTR DeviceName;
410
411 //
412 // get device extension
413 //
414 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
415
416 //
417 // sanity check
418 //
419 ASSERT(DeviceExtension->IsFDO == FALSE);
420
421 //
422 // get current stack location
423 //
424 IoStack = IoGetCurrentIrpStackLocation(Irp);
425
426 switch(IoStack->MinorFunction)
427 {
428 case IRP_MN_START_DEVICE:
429 {
430 DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
431 //
432 // register device interface
433 //
434 Status = SetDeviceInterface(TRUE);
435 break;
436 }
437 case IRP_MN_QUERY_ID:
438 {
439 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack->Parameters.QueryId.IdType);
440
441 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
442 {
443 if (m_Hardware)
444 {
445 //
446 // query device id
447 //
448 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
449
450 if (HiSpeed == 0x200)
451 {
452 //
453 // USB 2.0 hub
454 //
455 swprintf(Buffer, L"USB\\ROOT_HUB20");
456 }
457 else
458 {
459 //
460 // USB 1.1 hub
461 //
462 swprintf(Buffer, L"USB\\ROOT_HUB");
463 }
464
465 DPRINT1("Name %S\n", Buffer);
466
467 //
468 // calculate length
469 //
470 Length = (wcslen(Buffer) + 1);
471
472 //
473 // allocate buffer
474 //
475 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_USBOHCI);
476
477 if (!DeviceName)
478 {
479 //
480 // no memory
481 //
482 Status = STATUS_INSUFFICIENT_RESOURCES;
483 break;
484 }
485
486 //
487 // copy device name
488 //
489 wcscpy(DeviceName, Buffer);
490
491 //
492 // store result
493 //
494 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
495 Status = STATUS_SUCCESS;
496 break;
497 }
498 Status = STATUS_UNSUCCESSFUL;
499 PC_ASSERT(0);
500 break;
501 }
502
503 if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
504 {
505 if (m_Hardware)
506 {
507 //
508 // query device id
509 //
510 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
511
512 if (!NT_SUCCESS(Status))
513 {
514 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status);
515 VendorID = 0x8086;
516 DeviceID = 0x3A37;
517 }
518
519 if (HiSpeed == 0x200)
520 {
521 //
522 // USB 2.0 hub
523 //
524 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
525 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID, DeviceID) + 1;
526 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
527 }
528 else
529 {
530 //
531 // USB 1.1 hub
532 //
533 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
534 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID, DeviceID) + 1;
535 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB") + 1;
536 }
537
538 Buffer[Index] = UNICODE_NULL;
539 Index++;
540
541
542 DPRINT1("Name %S\n", Buffer);
543
544 //
545 // allocate buffer
546 //
547 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Index * sizeof(WCHAR), TAG_USBOHCI);
548
549 if (!DeviceName)
550 {
551 //
552 // no memory
553 //
554 Status = STATUS_INSUFFICIENT_RESOURCES;
555 break;
556 }
557
558 //
559 // copy device name
560 //
561 RtlMoveMemory(DeviceName, Buffer, Index * sizeof(WCHAR));
562
563 //
564 // store result
565 //
566 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
567 Status = STATUS_SUCCESS;
568 break;
569 }
570 }
571 Status = STATUS_SUCCESS;
572 break;
573 }
574 case IRP_MN_QUERY_CAPABILITIES:
575 {
576 DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
577
578 DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
579
580 DeviceCapabilities->LockSupported = FALSE;
581 DeviceCapabilities->EjectSupported = FALSE;
582 DeviceCapabilities->Removable = FALSE;
583 DeviceCapabilities->DockDevice = FALSE;
584 DeviceCapabilities->UniqueID = FALSE;
585 DeviceCapabilities->SilentInstall = FALSE;
586 DeviceCapabilities->RawDeviceOK = FALSE;
587 DeviceCapabilities->SurpriseRemovalOK = FALSE;
588 DeviceCapabilities->Address = 0;
589 DeviceCapabilities->UINumber = 0;
590 DeviceCapabilities->DeviceD2 = 1;
591
592 /* FIXME */
593 DeviceCapabilities->HardwareDisabled = FALSE;
594 DeviceCapabilities->NoDisplayInUI = FALSE;
595 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
596 for (Index = 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 = 0x22; //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 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1670 {
1671 //
1672 // data direction is device to host
1673 //
1674 CtrlSetup.bmRequestType.B |= 0x80;
1675 }
1676
1677
1678 //
1679 // issue request
1680 //
1681 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1682
1683 //
1684 // assert on failure
1685 //
1686 PC_ASSERT(NT_SUCCESS(Status));
1687
1688
1689 //
1690 // done
1691 //
1692 return Status;
1693 }
1694
1695 //-----------------------------------------------------------------------------------------
1696 NTSTATUS
1697 CHubController::HandleClassInterface(
1698 IN OUT PIRP Irp,
1699 IN OUT PURB Urb)
1700 {
1701 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1702 NTSTATUS Status;
1703 PUSBDEVICE UsbDevice;
1704
1705 //
1706 // sanity check
1707 //
1708 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1709 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1710 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1711
1712 //
1713 // check if this is a valid usb device handle
1714 //
1715 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1716 {
1717 DPRINT1("HandleClassInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1718
1719 //
1720 // invalid device handle
1721 //
1722 return STATUS_DEVICE_NOT_CONNECTED;
1723 }
1724
1725 //
1726 // get device
1727 //
1728 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1729
1730
1731 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1732 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
1733 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
1734 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
1735 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1736 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
1737 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1738 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
1739 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
1740
1741 //
1742 // initialize setup packet
1743 //
1744 CtrlSetup.bmRequestType.B = 0x21;
1745 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1746 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1747 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1748 CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
1749
1750 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1751 {
1752 //
1753 // data direction is device to host
1754 //
1755 CtrlSetup.bmRequestType.B |= 0x80;
1756 }
1757
1758 //
1759 // issue request
1760 //
1761 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1762
1763 //
1764 // assert on failure
1765 //
1766 if (!NT_SUCCESS(Status))
1767 {
1768 //
1769 // display error
1770 //
1771 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status);
1772 }
1773
1774 //
1775 // done
1776 //
1777 return Status;
1778 }
1779
1780 //-----------------------------------------------------------------------------------------
1781 NTSTATUS
1782 CHubController::HandleDeviceControl(
1783 IN PDEVICE_OBJECT DeviceObject,
1784 IN OUT PIRP Irp)
1785 {
1786 PIO_STACK_LOCATION IoStack;
1787 PCOMMON_DEVICE_EXTENSION DeviceExtension;
1788 PURB Urb;
1789 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1790
1791 //
1792 // get current stack location
1793 //
1794 IoStack = IoGetCurrentIrpStackLocation(Irp);
1795
1796 //
1797 // get device extension
1798 //
1799 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1800
1801 //
1802 // determine which request should be performed
1803 //
1804 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
1805 {
1806 case IOCTL_INTERNAL_USB_SUBMIT_URB:
1807 {
1808 //
1809 // get urb
1810 //
1811 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1812 PC_ASSERT(Urb);
1813
1814 switch (Urb->UrbHeader.Function)
1815 {
1816 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
1817 Status = HandleGetDescriptorFromInterface(Irp, Urb);
1818 break;
1819 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
1820 Status = HandleGetDescriptor(Irp, Urb);
1821 break;
1822 case URB_FUNCTION_CLASS_DEVICE:
1823 Status = HandleClassDevice(Irp, Urb);
1824 break;
1825 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
1826 Status = HandleGetStatusFromDevice(Irp, Urb);
1827 break;
1828 case URB_FUNCTION_SELECT_CONFIGURATION:
1829 Status = HandleSelectConfiguration(Irp, Urb);
1830 break;
1831 case URB_FUNCTION_SELECT_INTERFACE:
1832 Status = HandleSelectInterface(Irp, Urb);
1833 break;
1834 case URB_FUNCTION_CLASS_OTHER:
1835 Status = HandleClassOther(Irp, Urb);
1836 break;
1837 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
1838 Status = HandleBulkOrInterruptTransfer(Irp, Urb);
1839 break;
1840 case URB_FUNCTION_ISOCH_TRANSFER:
1841 Status = HandleIsochronousTransfer(Irp, Urb);
1842 break;
1843 case URB_FUNCTION_CLASS_INTERFACE:
1844 Status = HandleClassInterface(Irp, Urb);
1845 break;
1846 case URB_FUNCTION_CLASS_ENDPOINT:
1847 Status = HandleClassEndpoint(Irp, Urb);
1848 break;
1849 default:
1850 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
1851 break;
1852 }
1853 //
1854 // request completed
1855 //
1856 break;
1857 }
1858 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
1859 {
1860 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
1861
1862 if (IoStack->Parameters.Others.Argument1)
1863 {
1864 //
1865 // store object as device handle
1866 //
1867 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
1868 Status = STATUS_SUCCESS;
1869 }
1870 else
1871 {
1872 //
1873 // mis-behaving hub driver
1874 //
1875 Status = STATUS_INVALID_DEVICE_REQUEST;
1876 }
1877
1878 //
1879 // request completed
1880 //
1881 break;
1882 }
1883 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
1884 {
1885 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
1886
1887 //
1888 // this is the first request send, it delivers the PDO to the caller
1889 //
1890 if (IoStack->Parameters.Others.Argument1)
1891 {
1892 //
1893 // store root hub pdo object
1894 //
1895 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
1896 }
1897
1898 if (IoStack->Parameters.Others.Argument2)
1899 {
1900 //
1901 // documentation claims to deliver the hcd controller object, although it is wrong
1902 //
1903 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
1904 }
1905
1906 //
1907 // request completed
1908 //
1909 Status = STATUS_SUCCESS;
1910 break;
1911 }
1912 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
1913 {
1914 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
1915
1916 //
1917 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
1918 // requests this ioctl to deliver the number of presents.
1919
1920 if (IoStack->Parameters.Others.Argument1)
1921 {
1922 //
1923 // FIXME / verify: there is only one hub
1924 //
1925 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
1926 }
1927
1928 //
1929 // request completed
1930 //
1931 Status = STATUS_SUCCESS;
1932 Irp->IoStatus.Information = sizeof(ULONG);
1933 break;
1934 }
1935 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
1936 {
1937 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
1938 Status = STATUS_SUCCESS;
1939 break;
1940 }
1941 default:
1942 {
1943 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
1944 IoStack->Parameters.DeviceIoControl.IoControlCode,
1945 IoStack->Parameters.DeviceIoControl.InputBufferLength,
1946 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
1947 break;
1948 }
1949 }
1950 if (Status != STATUS_PENDING)
1951 {
1952 Irp->IoStatus.Status = Status;
1953 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1954 }
1955
1956 return Status;
1957 }
1958
1959 //-----------------------------------------------------------------------------------------
1960 PUSBHARDWAREDEVICE
1961 CHubController::GetUsbHardware()
1962 {
1963 return m_Hardware;
1964 }
1965
1966 //-----------------------------------------------------------------------------------------
1967 ULONG
1968 CHubController::AcquireDeviceAddress()
1969 {
1970 KIRQL OldLevel;
1971 ULONG DeviceAddress;
1972
1973 //
1974 // acquire device lock
1975 //
1976 KeAcquireSpinLock(&m_Lock, &OldLevel);
1977
1978 //
1979 // find address
1980 //
1981 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
1982 if (DeviceAddress != MAXULONG)
1983 {
1984 //
1985 // reserve address
1986 //
1987 RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
1988
1989 //
1990 // device addresses start from 0x1 - 0xFF
1991 //
1992 DeviceAddress++;
1993 }
1994
1995 //
1996 // release spin lock
1997 //
1998 KeReleaseSpinLock(&m_Lock, OldLevel);
1999
2000 //
2001 // return device address
2002 //
2003 return DeviceAddress;
2004 }
2005 //-----------------------------------------------------------------------------------------
2006 VOID
2007 CHubController::ReleaseDeviceAddress(
2008 ULONG DeviceAddress)
2009 {
2010 KIRQL OldLevel;
2011
2012 //
2013 // acquire device lock
2014 //
2015 KeAcquireSpinLock(&m_Lock, &OldLevel);
2016
2017 //
2018 // sanity check
2019 //
2020 PC_ASSERT(DeviceAddress != 0);
2021
2022 //
2023 // convert back to bit number
2024 //
2025 DeviceAddress--;
2026
2027 //
2028 // clear bit
2029 //
2030 RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2031
2032 //
2033 // release lock
2034 //
2035 KeReleaseSpinLock(&m_Lock, OldLevel);
2036 }
2037 //-----------------------------------------------------------------------------------------
2038 NTSTATUS
2039 CHubController::RemoveUsbDevice(
2040 PUSBDEVICE UsbDevice)
2041 {
2042 PUSBDEVICE_ENTRY DeviceEntry;
2043 PLIST_ENTRY Entry;
2044 NTSTATUS Status = STATUS_UNSUCCESSFUL;
2045 KIRQL OldLevel;
2046
2047 //
2048 // acquire lock
2049 //
2050 KeAcquireSpinLock(&m_Lock, &OldLevel);
2051
2052 //
2053 // point to first entry
2054 //
2055 Entry = m_UsbDeviceList.Flink;
2056
2057 //
2058 // find matching entry
2059 //
2060 while(Entry != &m_UsbDeviceList)
2061 {
2062 //
2063 // get entry
2064 //
2065 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2066
2067 //
2068 // is it current entry
2069 //
2070 if (DeviceEntry->Device == UsbDevice)
2071 {
2072 //
2073 // remove entry
2074 //
2075 RemoveEntryList(Entry);
2076
2077 //
2078 // free entry
2079 //
2080 ExFreePoolWithTag(DeviceEntry, TAG_USBOHCI);
2081
2082 //
2083 // done
2084 //
2085 Status = STATUS_SUCCESS;
2086 break;
2087 }
2088
2089 //
2090 // goto next device
2091 //
2092 Entry = Entry->Flink;
2093 }
2094
2095 //
2096 // release lock
2097 //
2098 KeReleaseSpinLock(&m_Lock, OldLevel);
2099
2100 //
2101 // return result
2102 //
2103 return Status;
2104 }
2105 //-----------------------------------------------------------------------------------------
2106 BOOLEAN
2107 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
2108 {
2109 PUSBDEVICE_ENTRY DeviceEntry;
2110 PLIST_ENTRY Entry;
2111 KIRQL OldLevel;
2112 BOOLEAN Result = FALSE;
2113
2114 //
2115 // acquire lock
2116 //
2117 KeAcquireSpinLock(&m_Lock, &OldLevel);
2118
2119 //
2120 // point to first entry
2121 //
2122 Entry = m_UsbDeviceList.Flink;
2123
2124 //
2125 // find matching entry
2126 //
2127 while(Entry != &m_UsbDeviceList)
2128 {
2129 //
2130 // get entry
2131 //
2132 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2133
2134 //
2135 // is it current entry
2136 //
2137 if (DeviceEntry->Device == UsbDevice)
2138 {
2139 //
2140 // device is valid
2141 //
2142 Result = TRUE;
2143 break;
2144 }
2145
2146 //
2147 // goto next device
2148 //
2149 Entry = Entry->Flink;
2150 }
2151
2152 //
2153 // release lock
2154 //
2155 KeReleaseSpinLock(&m_Lock, OldLevel);
2156
2157 //
2158 // return result
2159 //
2160 return Result;
2161
2162 }
2163
2164 //-----------------------------------------------------------------------------------------
2165 NTSTATUS
2166 CHubController::AddUsbDevice(
2167 PUSBDEVICE UsbDevice)
2168 {
2169 PUSBDEVICE_ENTRY DeviceEntry;
2170 KIRQL OldLevel;
2171
2172 //
2173 // allocate device entry
2174 //
2175 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBOHCI);
2176 if (!DeviceEntry)
2177 {
2178 //
2179 // no memory
2180 //
2181 return STATUS_INSUFFICIENT_RESOURCES;
2182 }
2183
2184 //
2185 // initialize entry
2186 //
2187 DeviceEntry->Device = UsbDevice;
2188
2189 //
2190 // acquire lock
2191 //
2192 KeAcquireSpinLock(&m_Lock, &OldLevel);
2193
2194 //
2195 // insert entry
2196 //
2197 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
2198
2199 //
2200 // release spin lock
2201 //
2202 KeReleaseSpinLock(&m_Lock, OldLevel);
2203
2204 //
2205 // done
2206 //
2207 return STATUS_SUCCESS;
2208 }
2209
2210 //-----------------------------------------------------------------------------------------
2211 VOID
2212 CHubController::SetNotification(
2213 PVOID CallbackContext,
2214 PRH_INIT_CALLBACK CallbackRoutine)
2215 {
2216 KIRQL OldLevel;
2217
2218 //
2219 // acquire hub controller lock
2220 //
2221 KeAcquireSpinLock(&m_Lock, &OldLevel);
2222
2223 //
2224 // now set the callback routine and context of the hub
2225 //
2226 m_HubCallbackContext = CallbackContext;
2227 m_HubCallbackRoutine = CallbackRoutine;
2228
2229 //
2230 // release hub controller lock
2231 //
2232 KeReleaseSpinLock(&m_Lock, OldLevel);
2233 }
2234
2235 //=================================================================================================
2236 //
2237 // Generic Interface functions
2238 //
2239 VOID
2240 USB_BUSIFFN
2241 USBI_InterfaceReference(
2242 PVOID BusContext)
2243 {
2244 CHubController * Controller = (CHubController*)BusContext;
2245
2246 DPRINT1("USBH_InterfaceReference\n");
2247
2248 //
2249 // add reference
2250 //
2251 Controller->AddRef();
2252 }
2253
2254 VOID
2255 USB_BUSIFFN
2256 USBI_InterfaceDereference(
2257 PVOID BusContext)
2258 {
2259 CHubController * Controller = (CHubController*)BusContext;
2260
2261 DPRINT1("USBH_InterfaceDereference\n");
2262
2263 //
2264 // release
2265 //
2266 Controller->Release();
2267 }
2268 //=================================================================================================
2269 //
2270 // USB Hub Interface functions
2271 //
2272 NTSTATUS
2273 USB_BUSIFFN
2274 USBHI_CreateUsbDevice(
2275 PVOID BusContext,
2276 PUSB_DEVICE_HANDLE *NewDevice,
2277 PUSB_DEVICE_HANDLE HubDeviceHandle,
2278 USHORT PortStatus,
2279 USHORT PortNumber)
2280 {
2281 PUSBDEVICE NewUsbDevice;
2282 CHubController * Controller;
2283 NTSTATUS Status;
2284
2285 DPRINT1("USBHI_CreateUsbDevice\n");
2286
2287 //
2288 // first get hub controller
2289 //
2290 Controller = (CHubController *)BusContext;
2291
2292 //
2293 // sanity check
2294 //
2295 PC_ASSERT(Controller);
2296 PC_ASSERT(BusContext == HubDeviceHandle);
2297
2298 //
2299 // now allocate usb device
2300 //
2301 Status = CreateUSBDevice(&NewUsbDevice);
2302
2303 //
2304 // check for success
2305 //
2306 if (!NT_SUCCESS(Status))
2307 {
2308 //
2309 // release controller
2310 //
2311 Controller->Release();
2312 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
2313 return Status;
2314 }
2315
2316 //
2317 // now initialize device
2318 //
2319 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
2320
2321 //
2322 // check for success
2323 //
2324 if (!NT_SUCCESS(Status))
2325 {
2326 //
2327 // release usb device
2328 //
2329 NewUsbDevice->Release();
2330 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
2331 return Status;
2332 }
2333
2334 //
2335 // insert into list
2336 //
2337 Status = Controller->AddUsbDevice(NewUsbDevice);
2338 //
2339 // check for success
2340 //
2341 if (!NT_SUCCESS(Status))
2342 {
2343 //
2344 // release usb device
2345 //
2346 NewUsbDevice->Release();
2347
2348 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
2349 return Status;
2350 }
2351
2352 //
2353 // store the handle
2354 //
2355 *NewDevice = NewUsbDevice;
2356
2357 //
2358 // done
2359 //
2360 return STATUS_SUCCESS;
2361 }
2362
2363 NTSTATUS
2364 USB_BUSIFFN
2365 USBHI_InitializeUsbDevice(
2366 PVOID BusContext,
2367 PUSB_DEVICE_HANDLE DeviceHandle)
2368 {
2369 PUSBDEVICE UsbDevice;
2370 CHubController * Controller;
2371 ULONG DeviceAddress;
2372 NTSTATUS Status;
2373 ULONG Index = 0;
2374
2375 DPRINT1("USBHI_InitializeUsbDevice\n");
2376
2377 //
2378 // first get controller
2379 //
2380 Controller = (CHubController *)BusContext;
2381 PC_ASSERT(Controller);
2382
2383 //
2384 // get device object
2385 //
2386 UsbDevice = (PUSBDEVICE)DeviceHandle;
2387 PC_ASSERT(UsbDevice);
2388
2389 //
2390 // validate device handle
2391 //
2392 if (!Controller->ValidateUsbDevice(UsbDevice))
2393 {
2394 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
2395
2396 //
2397 // invalid device handle
2398 //
2399 return STATUS_DEVICE_NOT_CONNECTED;
2400 }
2401
2402 //
2403 // now reserve an address
2404 //
2405 DeviceAddress = Controller->AcquireDeviceAddress();
2406
2407 //
2408 // is the device address valid
2409 //
2410 if (DeviceAddress == MAXULONG)
2411 {
2412 //
2413 // failed to get an device address from the device address pool
2414 //
2415 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2416 return STATUS_DEVICE_DATA_ERROR;
2417 }
2418
2419 do
2420 {
2421 //
2422 // now set the device address
2423 //
2424 Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
2425
2426 if (NT_SUCCESS(Status))
2427 break;
2428
2429 }while(Index++ < 3 );
2430
2431 //
2432 // check for failure
2433 //
2434 if (!NT_SUCCESS(Status))
2435 {
2436 //
2437 // failed to set device address
2438 //
2439 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
2440
2441 //
2442 // release address
2443 //
2444 Controller->ReleaseDeviceAddress(DeviceAddress);
2445
2446 //
2447 // return error
2448 //
2449 return STATUS_DEVICE_DATA_ERROR;
2450 }
2451
2452 //
2453 // done
2454 //
2455 return STATUS_SUCCESS;
2456 }
2457
2458 NTSTATUS
2459 USB_BUSIFFN
2460 USBHI_GetUsbDescriptors(
2461 PVOID BusContext,
2462 PUSB_DEVICE_HANDLE DeviceHandle,
2463 PUCHAR DeviceDescriptorBuffer,
2464 PULONG DeviceDescriptorBufferLength,
2465 PUCHAR ConfigDescriptorBuffer,
2466 PULONG ConfigDescriptorBufferLength)
2467 {
2468 PUSBDEVICE UsbDevice;
2469 CHubController * Controller;
2470
2471 DPRINT1("USBHI_GetUsbDescriptors\n");
2472
2473 //
2474 // sanity check
2475 //
2476 PC_ASSERT(DeviceDescriptorBuffer);
2477 PC_ASSERT(DeviceDescriptorBufferLength);
2478 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
2479 PC_ASSERT(ConfigDescriptorBufferLength);
2480 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
2481
2482 //
2483 // first get controller
2484 //
2485 Controller = (CHubController *)BusContext;
2486 PC_ASSERT(Controller);
2487
2488
2489 //
2490 // get device object
2491 //
2492 UsbDevice = (PUSBDEVICE)DeviceHandle;
2493 PC_ASSERT(UsbDevice);
2494
2495 //
2496 // validate device handle
2497 //
2498 if (!Controller->ValidateUsbDevice(UsbDevice))
2499 {
2500 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
2501
2502 //
2503 // invalid device handle
2504 //
2505 return STATUS_DEVICE_NOT_CONNECTED;
2506 }
2507
2508 //
2509 // get device descriptor
2510 //
2511 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
2512
2513 //
2514 // store result length
2515 //
2516 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
2517
2518 //
2519 // get configuration descriptor
2520 //
2521 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
2522
2523 //
2524 // complete the request
2525 //
2526 return STATUS_SUCCESS;
2527 }
2528
2529 NTSTATUS
2530 USB_BUSIFFN
2531 USBHI_RemoveUsbDevice(
2532 PVOID BusContext,
2533 PUSB_DEVICE_HANDLE DeviceHandle,
2534 ULONG Flags)
2535 {
2536 PUSBDEVICE UsbDevice;
2537 CHubController * Controller;
2538 NTSTATUS Status;
2539
2540 DPRINT1("USBHI_RemoveUsbDevice\n");
2541
2542 //
2543 // first get controller
2544 //
2545 Controller = (CHubController *)BusContext;
2546 PC_ASSERT(Controller);
2547
2548 //
2549 // get device object
2550 //
2551 UsbDevice = (PUSBDEVICE)DeviceHandle;
2552 PC_ASSERT(UsbDevice);
2553
2554 //
2555 // validate device handle
2556 //
2557 if (!Controller->ValidateUsbDevice(UsbDevice))
2558 {
2559 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
2560
2561 //
2562 // invalid device handle
2563 //
2564 return STATUS_DEVICE_NOT_CONNECTED;
2565 }
2566
2567 //
2568 // check if there were flags passed
2569 //
2570 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
2571 {
2572 //
2573 // ignore flags for now
2574 //
2575 return STATUS_SUCCESS;
2576 }
2577
2578 //
2579 // remove device
2580 //
2581 Status = Controller->RemoveUsbDevice(UsbDevice);
2582 if (!NT_SUCCESS(Status))
2583 {
2584 //
2585 // invalid device handle
2586 //
2587 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
2588 PC_ASSERT(0);
2589 return STATUS_DEVICE_NOT_CONNECTED;
2590 }
2591
2592 //
2593 // release usb device
2594 //
2595 UsbDevice->Release();
2596
2597 //
2598 // done
2599 //
2600 return STATUS_SUCCESS;
2601 }
2602
2603 NTSTATUS
2604 USB_BUSIFFN
2605 USBHI_RestoreUsbDevice(
2606 PVOID BusContext,
2607 PUSB_DEVICE_HANDLE OldDeviceHandle,
2608 PUSB_DEVICE_HANDLE NewDeviceHandle)
2609 {
2610 PUSBDEVICE OldUsbDevice, NewUsbDevice;
2611 CHubController * Controller;
2612
2613 DPRINT1("USBHI_RestoreUsbDevice\n");
2614
2615 //
2616 // first get controller
2617 //
2618 Controller = (CHubController *)BusContext;
2619 PC_ASSERT(Controller);
2620
2621 //
2622 // get device object
2623 //
2624 OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
2625 NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
2626 PC_ASSERT(OldUsbDevice);
2627 PC_ASSERT(NewDeviceHandle);
2628
2629 //
2630 // validate device handle
2631 //
2632 PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
2633 PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
2634
2635 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
2636 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
2637
2638 //
2639 // remove old device handle
2640 //
2641 USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
2642
2643 return STATUS_SUCCESS;
2644 }
2645
2646 NTSTATUS
2647 USB_BUSIFFN
2648 USBHI_QueryDeviceInformation(
2649 PVOID BusContext,
2650 PUSB_DEVICE_HANDLE DeviceHandle,
2651 PVOID DeviceInformationBuffer,
2652 ULONG DeviceInformationBufferLength,
2653 PULONG LengthReturned)
2654 {
2655 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
2656 PUSBDEVICE UsbDevice;
2657 CHubController * Controller;
2658
2659 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
2660
2661 //
2662 // sanity check
2663 //
2664 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
2665 PC_ASSERT(DeviceInformationBuffer);
2666 PC_ASSERT(LengthReturned);
2667
2668 //
2669 // get controller object
2670 //
2671 Controller = (CHubController*)BusContext;
2672 PC_ASSERT(Controller);
2673
2674 //
2675 // get device object
2676 //
2677 UsbDevice = (PUSBDEVICE)DeviceHandle;
2678 PC_ASSERT(UsbDevice);
2679
2680 if (BusContext != DeviceHandle)
2681 {
2682 //
2683 // validate device handle
2684 //
2685 if (!Controller->ValidateUsbDevice(UsbDevice))
2686 {
2687 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
2688
2689 //
2690 // invalid device handle
2691 //
2692 return STATUS_DEVICE_NOT_CONNECTED;
2693 }
2694
2695 //
2696 // access information buffer
2697 //
2698 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2699
2700 //
2701 // initialize with default values
2702 //
2703 DeviceInfo->InformationLevel = 0;
2704 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2705 DeviceInfo->PortNumber = UsbDevice->GetPort();
2706 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
2707 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
2708 DeviceInfo->HubAddress = 0; //FIXME
2709 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
2710 DeviceInfo->DeviceType = UsbDevice->GetType();
2711 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2712
2713 //
2714 // get device descriptor
2715 //
2716 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
2717
2718 //
2719 // FIXME return pipe information
2720 //
2721
2722 //
2723 // store result length
2724 //
2725 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
2726
2727 return STATUS_SUCCESS;
2728 }
2729
2730 //
2731 // access information buffer
2732 //
2733 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2734
2735 //
2736 // initialize with default values
2737 //
2738 DeviceInfo->InformationLevel = 0;
2739 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2740 DeviceInfo->PortNumber = 0;
2741 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
2742 DeviceInfo->DeviceAddress = 0;
2743 DeviceInfo->HubAddress = 0; //FIXME
2744 DeviceInfo->DeviceSpeed = UsbFullSpeed; //FIXME
2745 DeviceInfo->DeviceType = Usb11Device; //FIXME
2746 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2747
2748 //
2749 // get device descriptor
2750 //
2751 RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
2752
2753 //
2754 // FIXME return pipe information
2755 //
2756
2757 //
2758 // store result length
2759 //
2760 #ifdef _MSC_VER
2761 *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
2762 #else
2763 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
2764 #endif
2765 //
2766 // done
2767 //
2768 return STATUS_SUCCESS;
2769 }
2770
2771 NTSTATUS
2772 USB_BUSIFFN
2773 USBHI_GetControllerInformation(
2774 PVOID BusContext,
2775 PVOID ControllerInformationBuffer,
2776 ULONG ControllerInformationBufferLength,
2777 PULONG LengthReturned)
2778 {
2779 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
2780
2781 DPRINT1("USBHI_GetControllerInformation\n");
2782
2783 //
2784 // sanity checks
2785 //
2786 PC_ASSERT(ControllerInformationBuffer);
2787 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
2788
2789 //
2790 // get controller info buffer
2791 //
2792 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
2793
2794 //
2795 // FIXME only version 0 is supported for now
2796 //
2797 PC_ASSERT(ControllerInfo->InformationLevel == 0);
2798
2799 //
2800 // fill in information
2801 //
2802 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
2803 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
2804 ControllerInfo->IsHighSpeedController = FALSE;
2805
2806 //
2807 // set length returned
2808 //
2809 *LengthReturned = ControllerInfo->ActualLength;
2810
2811 //
2812 // done
2813 //
2814 return STATUS_SUCCESS;
2815 }
2816
2817 NTSTATUS
2818 USB_BUSIFFN
2819 USBHI_ControllerSelectiveSuspend(
2820 PVOID BusContext,
2821 BOOLEAN Enable)
2822 {
2823 UNIMPLEMENTED
2824 return STATUS_NOT_IMPLEMENTED;
2825 }
2826
2827 NTSTATUS
2828 USB_BUSIFFN
2829 USBHI_GetExtendedHubInformation(
2830 PVOID BusContext,
2831 PDEVICE_OBJECT HubPhysicalDeviceObject,
2832 PVOID HubInformationBuffer,
2833 ULONG HubInformationBufferLength,
2834 PULONG LengthReturned)
2835 {
2836 PUSB_EXTHUB_INFORMATION_0 HubInfo;
2837 CHubController * Controller;
2838 PUSBHARDWAREDEVICE Hardware;
2839 ULONG Index;
2840 ULONG NumPort, Dummy2;
2841 USHORT Dummy1;
2842 NTSTATUS Status;
2843
2844 DPRINT1("USBHI_GetExtendedHubInformation\n");
2845
2846 //
2847 // sanity checks
2848 //
2849 PC_ASSERT(HubInformationBuffer);
2850 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
2851 PC_ASSERT(LengthReturned);
2852
2853 //
2854 // get hub controller
2855 //
2856 Controller = (CHubController *)BusContext;
2857 PC_ASSERT(Controller);
2858
2859 //
2860 // get usb hardware device
2861 //
2862 Hardware = Controller->GetUsbHardware();
2863
2864 //
2865 // retrieve number of ports
2866 //
2867 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
2868 if (!NT_SUCCESS(Status))
2869 {
2870 //
2871 // failed to get hardware details, ouch ;)
2872 //
2873 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
2874 return Status;
2875 }
2876
2877 //
2878 // get hub information buffer
2879 //
2880 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
2881
2882 //
2883 // initialize hub information
2884 //
2885 HubInfo->InformationLevel = 0;
2886
2887 //
2888 // store port count
2889 //
2890 HubInfo->NumberOfPorts = NumPort;
2891
2892 //
2893 // initialize port information
2894 //
2895 for(Index = 0; Index < NumPort; Index++)
2896 {
2897 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
2898 HubInfo->Port[Index].PortLabelNumber = Index + 1;
2899 HubInfo->Port[Index].VidOverride = 0;
2900 HubInfo->Port[Index].PidOverride = 0;
2901 HubInfo->Port[Index].PortAttributes = 0; //FIXME
2902 }
2903
2904 //
2905 // store result length
2906 //
2907 #ifdef _MSC_VER
2908 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
2909 #else
2910 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
2911 #endif
2912
2913 //
2914 // done
2915 //
2916 return STATUS_SUCCESS;
2917 }
2918
2919 NTSTATUS
2920 USB_BUSIFFN
2921 USBHI_GetRootHubSymbolicName(
2922 PVOID BusContext,
2923 PVOID HubSymNameBuffer,
2924 ULONG HubSymNameBufferLength,
2925 PULONG HubSymNameActualLength)
2926 {
2927 UNIMPLEMENTED
2928 return STATUS_NOT_IMPLEMENTED;
2929 }
2930
2931 PVOID
2932 USB_BUSIFFN
2933 USBHI_GetDeviceBusContext(
2934 PVOID HubBusContext,
2935 PVOID DeviceHandle)
2936 {
2937 UNIMPLEMENTED
2938 return NULL;
2939 }
2940
2941 NTSTATUS
2942 USB_BUSIFFN
2943 USBHI_RootHubInitNotification(
2944 PVOID BusContext,
2945 PVOID CallbackContext,
2946 PRH_INIT_CALLBACK CallbackRoutine)
2947 {
2948 CHubController * Controller;
2949
2950 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
2951
2952 //
2953 // get controller object
2954 //
2955 Controller = (CHubController*)BusContext;
2956 PC_ASSERT(Controller);
2957
2958 //
2959 // set notification routine
2960 //
2961 Controller->SetNotification(CallbackContext, CallbackRoutine);
2962
2963 //
2964 // FIXME: determine when to perform callback
2965 //
2966 CallbackRoutine(CallbackContext);
2967
2968 //
2969 // done
2970 //
2971 return STATUS_SUCCESS;
2972 }
2973
2974 VOID
2975 USB_BUSIFFN
2976 USBHI_FlushTransfers(
2977 PVOID BusContext,
2978 PVOID DeviceHandle)
2979 {
2980 UNIMPLEMENTED
2981 }
2982
2983 VOID
2984 USB_BUSIFFN
2985 USBHI_SetDeviceHandleData(
2986 PVOID BusContext,
2987 PVOID DeviceHandle,
2988 PDEVICE_OBJECT UsbDevicePdo)
2989 {
2990 PUSBDEVICE UsbDevice;
2991 CHubController * Controller;
2992
2993 //
2994 // get controller
2995 //
2996 Controller = (CHubController *)BusContext;
2997 PC_ASSERT(Controller);
2998
2999 //
3000 // get device handle
3001 //
3002 UsbDevice = (PUSBDEVICE)DeviceHandle;
3003
3004 //
3005 // validate device handle
3006 //
3007 if (!Controller->ValidateUsbDevice(UsbDevice))
3008 {
3009 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
3010
3011 //
3012 // invalid handle
3013 //
3014 return;
3015 }
3016 else
3017 {
3018 //
3019 // usbhub sends this request as a part of the Pnp startup sequence
3020 // looks like we need apply a dragon voodoo to fixup the device stack
3021 // otherwise usbhub will cause a bugcheck
3022 //
3023 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo);
3024
3025 //
3026 // sanity check
3027 //
3028 PC_ASSERT(UsbDevicePdo->AttachedDevice);
3029
3030 //
3031 // should be usbstor
3032 // fixup device stack voodoo part #2
3033 //
3034 UsbDevicePdo->AttachedDevice->StackSize++;
3035
3036 //
3037 // set device handle data
3038 //
3039 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
3040 }
3041 }
3042
3043 //=================================================================================================
3044 //
3045 // USB Device Interface functions
3046 //
3047
3048 VOID
3049 USB_BUSIFFN
3050 USBDI_GetUSBDIVersion(
3051 PVOID BusContext,
3052 PUSBD_VERSION_INFORMATION VersionInformation,
3053 PULONG HcdCapabilites)
3054 {
3055 CHubController * Controller;
3056 PUSBHARDWAREDEVICE Device;
3057 ULONG Speed, Dummy2;
3058 USHORT Dummy1;
3059
3060 DPRINT1("USBDI_GetUSBDIVersion\n");
3061
3062 //
3063 // get controller
3064 //
3065 Controller = (CHubController*)BusContext;
3066
3067 //
3068 // get usb hardware
3069 //
3070 Device = Controller->GetUsbHardware();
3071 PC_ASSERT(Device);
3072
3073 if (VersionInformation)
3074 {
3075 //
3076 // windows xp supported
3077 //
3078 VersionInformation->USBDI_Version = 0x00000500;
3079
3080 //
3081 // get device speed
3082 //
3083 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3084
3085 //
3086 // store speed details
3087 //
3088 VersionInformation->Supported_USB_Version = Speed;
3089 }
3090
3091 //
3092 // no flags supported
3093 //
3094 *HcdCapabilites = 0;
3095 }
3096
3097 NTSTATUS
3098 USB_BUSIFFN
3099 USBDI_QueryBusTime(
3100 PVOID BusContext,
3101 PULONG CurrentFrame)
3102 {
3103 UNIMPLEMENTED
3104 return STATUS_NOT_IMPLEMENTED;
3105 }
3106
3107 NTSTATUS
3108 USB_BUSIFFN
3109 USBDI_SubmitIsoOutUrb(
3110 PVOID BusContext,
3111 PURB Urb)
3112 {
3113 UNIMPLEMENTED
3114 return STATUS_NOT_IMPLEMENTED;
3115 }
3116
3117 NTSTATUS
3118 USB_BUSIFFN
3119 USBDI_QueryBusInformation(
3120 PVOID BusContext,
3121 ULONG Level,
3122 PVOID BusInformationBuffer,
3123 PULONG BusInformationBufferLength,
3124 PULONG BusInformationActualLength)
3125 {
3126 UNIMPLEMENTED
3127 return STATUS_NOT_IMPLEMENTED;
3128 }
3129
3130 BOOLEAN
3131 USB_BUSIFFN
3132 USBDI_IsDeviceHighSpeed(
3133 PVOID BusContext)
3134 {
3135 CHubController * Controller;
3136 PUSBHARDWAREDEVICE Device;
3137 ULONG Speed, Dummy2;
3138 USHORT Dummy1;
3139
3140 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3141
3142 //
3143 // get controller
3144 //
3145 Controller = (CHubController*)BusContext;
3146
3147 //
3148 // get usb hardware
3149 //
3150 Device = Controller->GetUsbHardware();
3151 PC_ASSERT(Device);
3152
3153 //
3154 // get device speed
3155 //
3156 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3157
3158 //
3159 // USB 2.0 equals 0x200
3160 //
3161 return (Speed == 0x200);
3162 }
3163
3164 NTSTATUS
3165 USB_BUSIFFN
3166 USBDI_EnumLogEntry(
3167 PVOID BusContext,
3168 ULONG DriverTag,
3169 ULONG EnumTag,
3170 ULONG P1,
3171 ULONG P2)
3172 {
3173 UNIMPLEMENTED
3174 return STATUS_NOT_IMPLEMENTED;
3175 }
3176
3177 NTSTATUS
3178 CHubController::HandleQueryInterface(
3179 PIO_STACK_LOCATION IoStack)
3180 {
3181 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
3182 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
3183 UNICODE_STRING GuidBuffer;
3184 NTSTATUS Status;
3185
3186 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
3187 {
3188 //
3189 // get request parameters
3190 //
3191 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
3192 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
3193
3194 //
3195 // check version
3196 //
3197 if (IoStack->Parameters.QueryInterface.Version >= 6)
3198 {
3199 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3200
3201 //
3202 // version not supported
3203 //
3204 return STATUS_NOT_SUPPORTED;
3205 }
3206
3207 //
3208 // Interface version 0
3209 //
3210 if (IoStack->Parameters.QueryInterface.Version >= 0)
3211 {
3212 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
3213 InterfaceHub->BusContext = PVOID(this);
3214 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
3215 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
3216 }
3217
3218 //
3219 // Interface version 1
3220 //
3221 if (IoStack->Parameters.QueryInterface.Version >= 1)
3222 {
3223 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
3224 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
3225 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
3226 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
3227 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
3228 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
3229 }
3230
3231 //
3232 // Interface version 2
3233 //
3234 if (IoStack->Parameters.QueryInterface.Version >= 2)
3235 {
3236 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
3237 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
3238 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
3239 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
3240 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
3241 }
3242
3243 //
3244 // Interface version 3
3245 //
3246 if (IoStack->Parameters.QueryInterface.Version >= 3)
3247 {
3248 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
3249 }
3250
3251 //
3252 // Interface version 4
3253 //
3254 if (IoStack->Parameters.QueryInterface.Version >= 4)
3255 {
3256 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
3257 }
3258
3259 //
3260 // Interface version 5
3261 //
3262 if (IoStack->Parameters.QueryInterface.Version >= 5)
3263 {
3264 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
3265 }
3266
3267 //
3268 // request completed
3269 //
3270 return STATUS_SUCCESS;
3271 }
3272 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
3273 {
3274 //
3275 // get request parameters
3276 //
3277 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
3278 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
3279
3280 //
3281 // check version
3282 //
3283 if (IoStack->Parameters.QueryInterface.Version >= 3)
3284 {
3285 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3286
3287 //
3288 // version not supported
3289 //
3290 return STATUS_NOT_SUPPORTED;
3291 }
3292
3293 //
3294 // interface version 0
3295 //
3296 if (IoStack->Parameters.QueryInterface.Version >= 0)
3297 {
3298 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
3299 InterfaceDI->BusContext = PVOID(this);
3300 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
3301 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
3302 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
3303 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
3304 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
3305 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
3306 }
3307
3308 //
3309 // interface version 1
3310 //
3311 if (IoStack->Parameters.QueryInterface.Version >= 1)
3312 {
3313 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
3314 }
3315
3316 //
3317 // interface version 2
3318 //
3319 if (IoStack->Parameters.QueryInterface.Version >= 2)
3320 {
3321 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
3322 }
3323
3324 //
3325 // request completed
3326 //
3327 return STATUS_SUCCESS;
3328 }
3329 else
3330 {
3331 //
3332 // convert guid to string
3333 //
3334 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
3335 if (NT_SUCCESS(Status))
3336 {
3337 //
3338 // print interface
3339 //
3340 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
3341
3342 //
3343 // free guid buffer
3344 //
3345 RtlFreeUnicodeString(&GuidBuffer);
3346 }
3347 }
3348 return STATUS_NOT_SUPPORTED;
3349 }
3350
3351 NTSTATUS
3352 CHubController::SetDeviceInterface(
3353 BOOLEAN Enable)
3354 {
3355 NTSTATUS Status = STATUS_SUCCESS;
3356
3357 if (Enable)
3358 {
3359 //
3360 // register device interface
3361 //
3362 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
3363
3364 if (NT_SUCCESS(Status))
3365 {
3366 //
3367 // now enable the device interface
3368 //
3369 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
3370
3371 //
3372 // enable interface
3373 //
3374 m_InterfaceEnabled = TRUE;
3375 }
3376 }
3377 else if (m_InterfaceEnabled)
3378 {
3379 //
3380 // disable device interface
3381 //
3382 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
3383
3384 if (NT_SUCCESS(Status))
3385 {
3386 //
3387 // now delete interface string
3388 //
3389 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
3390 }
3391
3392 //
3393 // disable interface
3394 //
3395 m_InterfaceEnabled = FALSE;
3396 }
3397
3398 //
3399 // done
3400 //
3401 return STATUS_SUCCESS;
3402 }
3403
3404 NTSTATUS