c89cf5afd5dd9f24c469d63472733465aea0d7f0
[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 PC_ASSERT(NT_SUCCESS(Status));
1767
1768
1769 //
1770 // done
1771 //
1772 return Status;
1773 }
1774
1775 //-----------------------------------------------------------------------------------------
1776 NTSTATUS
1777 CHubController::HandleDeviceControl(
1778 IN PDEVICE_OBJECT DeviceObject,
1779 IN OUT PIRP Irp)
1780 {
1781 PIO_STACK_LOCATION IoStack;
1782 PCOMMON_DEVICE_EXTENSION DeviceExtension;
1783 PURB Urb;
1784 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1785
1786 //
1787 // get current stack location
1788 //
1789 IoStack = IoGetCurrentIrpStackLocation(Irp);
1790
1791 //
1792 // get device extension
1793 //
1794 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1795
1796 //
1797 // determine which request should be performed
1798 //
1799 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
1800 {
1801 case IOCTL_INTERNAL_USB_SUBMIT_URB:
1802 {
1803 //
1804 // get urb
1805 //
1806 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1807 PC_ASSERT(Urb);
1808
1809 switch (Urb->UrbHeader.Function)
1810 {
1811 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
1812 Status = HandleGetDescriptorFromInterface(Irp, Urb);
1813 break;
1814 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
1815 Status = HandleGetDescriptor(Irp, Urb);
1816 break;
1817 case URB_FUNCTION_CLASS_DEVICE:
1818 Status = HandleClassDevice(Irp, Urb);
1819 break;
1820 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
1821 Status = HandleGetStatusFromDevice(Irp, Urb);
1822 break;
1823 case URB_FUNCTION_SELECT_CONFIGURATION:
1824 Status = HandleSelectConfiguration(Irp, Urb);
1825 break;
1826 case URB_FUNCTION_SELECT_INTERFACE:
1827 Status = HandleSelectInterface(Irp, Urb);
1828 break;
1829 case URB_FUNCTION_CLASS_OTHER:
1830 Status = HandleClassOther(Irp, Urb);
1831 break;
1832 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
1833 Status = HandleBulkOrInterruptTransfer(Irp, Urb);
1834 break;
1835 case URB_FUNCTION_ISOCH_TRANSFER:
1836 Status = HandleIsochronousTransfer(Irp, Urb);
1837 break;
1838 case URB_FUNCTION_CLASS_INTERFACE:
1839 Status = HandleClassInterface(Irp, Urb);
1840 break;
1841 case URB_FUNCTION_CLASS_ENDPOINT:
1842 Status = HandleClassEndpoint(Irp, Urb);
1843 break;
1844 default:
1845 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
1846 break;
1847 }
1848 //
1849 // request completed
1850 //
1851 break;
1852 }
1853 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
1854 {
1855 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
1856
1857 if (IoStack->Parameters.Others.Argument1)
1858 {
1859 //
1860 // store object as device handle
1861 //
1862 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
1863 Status = STATUS_SUCCESS;
1864 }
1865 else
1866 {
1867 //
1868 // mis-behaving hub driver
1869 //
1870 Status = STATUS_INVALID_DEVICE_REQUEST;
1871 }
1872
1873 //
1874 // request completed
1875 //
1876 break;
1877 }
1878 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
1879 {
1880 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
1881
1882 //
1883 // this is the first request send, it delivers the PDO to the caller
1884 //
1885 if (IoStack->Parameters.Others.Argument1)
1886 {
1887 //
1888 // store root hub pdo object
1889 //
1890 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
1891 }
1892
1893 if (IoStack->Parameters.Others.Argument2)
1894 {
1895 //
1896 // documentation claims to deliver the hcd controller object, although it is wrong
1897 //
1898 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
1899 }
1900
1901 //
1902 // request completed
1903 //
1904 Status = STATUS_SUCCESS;
1905 break;
1906 }
1907 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
1908 {
1909 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
1910
1911 //
1912 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
1913 // requests this ioctl to deliver the number of presents.
1914
1915 if (IoStack->Parameters.Others.Argument1)
1916 {
1917 //
1918 // FIXME / verify: there is only one hub
1919 //
1920 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
1921 }
1922
1923 //
1924 // request completed
1925 //
1926 Status = STATUS_SUCCESS;
1927 Irp->IoStatus.Information = sizeof(ULONG);
1928 break;
1929 }
1930 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
1931 {
1932 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
1933 Status = STATUS_SUCCESS;
1934 break;
1935 }
1936 default:
1937 {
1938 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
1939 IoStack->Parameters.DeviceIoControl.IoControlCode,
1940 IoStack->Parameters.DeviceIoControl.InputBufferLength,
1941 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
1942 break;
1943 }
1944 }
1945 if (Status != STATUS_PENDING)
1946 {
1947 Irp->IoStatus.Status = Status;
1948 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1949 }
1950
1951 return Status;
1952 }
1953
1954 //-----------------------------------------------------------------------------------------
1955 PUSBHARDWAREDEVICE
1956 CHubController::GetUsbHardware()
1957 {
1958 return m_Hardware;
1959 }
1960
1961 //-----------------------------------------------------------------------------------------
1962 ULONG
1963 CHubController::AcquireDeviceAddress()
1964 {
1965 KIRQL OldLevel;
1966 ULONG DeviceAddress;
1967
1968 //
1969 // acquire device lock
1970 //
1971 KeAcquireSpinLock(&m_Lock, &OldLevel);
1972
1973 //
1974 // find address
1975 //
1976 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
1977 if (DeviceAddress != MAXULONG)
1978 {
1979 //
1980 // reserve address
1981 //
1982 RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
1983
1984 //
1985 // device addresses start from 0x1 - 0xFF
1986 //
1987 DeviceAddress++;
1988 }
1989
1990 //
1991 // release spin lock
1992 //
1993 KeReleaseSpinLock(&m_Lock, OldLevel);
1994
1995 //
1996 // return device address
1997 //
1998 return DeviceAddress;
1999 }
2000 //-----------------------------------------------------------------------------------------
2001 VOID
2002 CHubController::ReleaseDeviceAddress(
2003 ULONG DeviceAddress)
2004 {
2005 KIRQL OldLevel;
2006
2007 //
2008 // acquire device lock
2009 //
2010 KeAcquireSpinLock(&m_Lock, &OldLevel);
2011
2012 //
2013 // sanity check
2014 //
2015 PC_ASSERT(DeviceAddress != 0);
2016
2017 //
2018 // convert back to bit number
2019 //
2020 DeviceAddress--;
2021
2022 //
2023 // clear bit
2024 //
2025 RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2026
2027 //
2028 // release lock
2029 //
2030 KeReleaseSpinLock(&m_Lock, OldLevel);
2031 }
2032 //-----------------------------------------------------------------------------------------
2033 NTSTATUS
2034 CHubController::RemoveUsbDevice(
2035 PUSBDEVICE UsbDevice)
2036 {
2037 PUSBDEVICE_ENTRY DeviceEntry;
2038 PLIST_ENTRY Entry;
2039 NTSTATUS Status = STATUS_UNSUCCESSFUL;
2040 KIRQL OldLevel;
2041
2042 //
2043 // acquire lock
2044 //
2045 KeAcquireSpinLock(&m_Lock, &OldLevel);
2046
2047 //
2048 // point to first entry
2049 //
2050 Entry = m_UsbDeviceList.Flink;
2051
2052 //
2053 // find matching entry
2054 //
2055 while(Entry != &m_UsbDeviceList)
2056 {
2057 //
2058 // get entry
2059 //
2060 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2061
2062 //
2063 // is it current entry
2064 //
2065 if (DeviceEntry->Device == UsbDevice)
2066 {
2067 //
2068 // remove entry
2069 //
2070 RemoveEntryList(Entry);
2071
2072 //
2073 // free entry
2074 //
2075 ExFreePoolWithTag(DeviceEntry, TAG_USBOHCI);
2076
2077 //
2078 // done
2079 //
2080 Status = STATUS_SUCCESS;
2081 break;
2082 }
2083
2084 //
2085 // goto next device
2086 //
2087 Entry = Entry->Flink;
2088 }
2089
2090 //
2091 // release lock
2092 //
2093 KeReleaseSpinLock(&m_Lock, OldLevel);
2094
2095 //
2096 // return result
2097 //
2098 return Status;
2099 }
2100 //-----------------------------------------------------------------------------------------
2101 BOOLEAN
2102 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
2103 {
2104 PUSBDEVICE_ENTRY DeviceEntry;
2105 PLIST_ENTRY Entry;
2106 KIRQL OldLevel;
2107 BOOLEAN Result = FALSE;
2108
2109 //
2110 // acquire lock
2111 //
2112 KeAcquireSpinLock(&m_Lock, &OldLevel);
2113
2114 //
2115 // point to first entry
2116 //
2117 Entry = m_UsbDeviceList.Flink;
2118
2119 //
2120 // find matching entry
2121 //
2122 while(Entry != &m_UsbDeviceList)
2123 {
2124 //
2125 // get entry
2126 //
2127 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2128
2129 //
2130 // is it current entry
2131 //
2132 if (DeviceEntry->Device == UsbDevice)
2133 {
2134 //
2135 // device is valid
2136 //
2137 Result = TRUE;
2138 break;
2139 }
2140
2141 //
2142 // goto next device
2143 //
2144 Entry = Entry->Flink;
2145 }
2146
2147 //
2148 // release lock
2149 //
2150 KeReleaseSpinLock(&m_Lock, OldLevel);
2151
2152 //
2153 // return result
2154 //
2155 return Result;
2156
2157 }
2158
2159 //-----------------------------------------------------------------------------------------
2160 NTSTATUS
2161 CHubController::AddUsbDevice(
2162 PUSBDEVICE UsbDevice)
2163 {
2164 PUSBDEVICE_ENTRY DeviceEntry;
2165 KIRQL OldLevel;
2166
2167 //
2168 // allocate device entry
2169 //
2170 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBOHCI);
2171 if (!DeviceEntry)
2172 {
2173 //
2174 // no memory
2175 //
2176 return STATUS_INSUFFICIENT_RESOURCES;
2177 }
2178
2179 //
2180 // initialize entry
2181 //
2182 DeviceEntry->Device = UsbDevice;
2183
2184 //
2185 // acquire lock
2186 //
2187 KeAcquireSpinLock(&m_Lock, &OldLevel);
2188
2189 //
2190 // insert entry
2191 //
2192 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
2193
2194 //
2195 // release spin lock
2196 //
2197 KeReleaseSpinLock(&m_Lock, OldLevel);
2198
2199 //
2200 // done
2201 //
2202 return STATUS_SUCCESS;
2203 }
2204
2205 //-----------------------------------------------------------------------------------------
2206 VOID
2207 CHubController::SetNotification(
2208 PVOID CallbackContext,
2209 PRH_INIT_CALLBACK CallbackRoutine)
2210 {
2211 KIRQL OldLevel;
2212
2213 //
2214 // acquire hub controller lock
2215 //
2216 KeAcquireSpinLock(&m_Lock, &OldLevel);
2217
2218 //
2219 // now set the callback routine and context of the hub
2220 //
2221 m_HubCallbackContext = CallbackContext;
2222 m_HubCallbackRoutine = CallbackRoutine;
2223
2224 //
2225 // release hub controller lock
2226 //
2227 KeReleaseSpinLock(&m_Lock, OldLevel);
2228 }
2229
2230 //=================================================================================================
2231 //
2232 // Generic Interface functions
2233 //
2234 VOID
2235 USB_BUSIFFN
2236 USBI_InterfaceReference(
2237 PVOID BusContext)
2238 {
2239 CHubController * Controller = (CHubController*)BusContext;
2240
2241 DPRINT1("USBH_InterfaceReference\n");
2242
2243 //
2244 // add reference
2245 //
2246 Controller->AddRef();
2247 }
2248
2249 VOID
2250 USB_BUSIFFN
2251 USBI_InterfaceDereference(
2252 PVOID BusContext)
2253 {
2254 CHubController * Controller = (CHubController*)BusContext;
2255
2256 DPRINT1("USBH_InterfaceDereference\n");
2257
2258 //
2259 // release
2260 //
2261 Controller->Release();
2262 }
2263 //=================================================================================================
2264 //
2265 // USB Hub Interface functions
2266 //
2267 NTSTATUS
2268 USB_BUSIFFN
2269 USBHI_CreateUsbDevice(
2270 PVOID BusContext,
2271 PUSB_DEVICE_HANDLE *NewDevice,
2272 PUSB_DEVICE_HANDLE HubDeviceHandle,
2273 USHORT PortStatus,
2274 USHORT PortNumber)
2275 {
2276 PUSBDEVICE NewUsbDevice;
2277 CHubController * Controller;
2278 NTSTATUS Status;
2279
2280 DPRINT1("USBHI_CreateUsbDevice\n");
2281
2282 //
2283 // first get hub controller
2284 //
2285 Controller = (CHubController *)BusContext;
2286
2287 //
2288 // sanity check
2289 //
2290 PC_ASSERT(Controller);
2291 PC_ASSERT(BusContext == HubDeviceHandle);
2292
2293 //
2294 // now allocate usb device
2295 //
2296 Status = CreateUSBDevice(&NewUsbDevice);
2297
2298 //
2299 // check for success
2300 //
2301 if (!NT_SUCCESS(Status))
2302 {
2303 //
2304 // release controller
2305 //
2306 Controller->Release();
2307 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
2308 return Status;
2309 }
2310
2311 //
2312 // now initialize device
2313 //
2314 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
2315
2316 //
2317 // check for success
2318 //
2319 if (!NT_SUCCESS(Status))
2320 {
2321 //
2322 // release usb device
2323 //
2324 NewUsbDevice->Release();
2325 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
2326 return Status;
2327 }
2328
2329 //
2330 // insert into list
2331 //
2332 Status = Controller->AddUsbDevice(NewUsbDevice);
2333 //
2334 // check for success
2335 //
2336 if (!NT_SUCCESS(Status))
2337 {
2338 //
2339 // release usb device
2340 //
2341 NewUsbDevice->Release();
2342
2343 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
2344 return Status;
2345 }
2346
2347 //
2348 // store the handle
2349 //
2350 *NewDevice = NewUsbDevice;
2351
2352 //
2353 // done
2354 //
2355 return STATUS_SUCCESS;
2356 }
2357
2358 NTSTATUS
2359 USB_BUSIFFN
2360 USBHI_InitializeUsbDevice(
2361 PVOID BusContext,
2362 PUSB_DEVICE_HANDLE DeviceHandle)
2363 {
2364 PUSBDEVICE UsbDevice;
2365 CHubController * Controller;
2366 ULONG DeviceAddress;
2367 NTSTATUS Status;
2368 ULONG Index = 0;
2369
2370 DPRINT1("USBHI_InitializeUsbDevice\n");
2371
2372 //
2373 // first get controller
2374 //
2375 Controller = (CHubController *)BusContext;
2376 PC_ASSERT(Controller);
2377
2378 //
2379 // get device object
2380 //
2381 UsbDevice = (PUSBDEVICE)DeviceHandle;
2382 PC_ASSERT(UsbDevice);
2383
2384 //
2385 // validate device handle
2386 //
2387 if (!Controller->ValidateUsbDevice(UsbDevice))
2388 {
2389 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
2390
2391 //
2392 // invalid device handle
2393 //
2394 return STATUS_DEVICE_NOT_CONNECTED;
2395 }
2396
2397 //
2398 // now reserve an address
2399 //
2400 DeviceAddress = Controller->AcquireDeviceAddress();
2401
2402 //
2403 // is the device address valid
2404 //
2405 if (DeviceAddress == MAXULONG)
2406 {
2407 //
2408 // failed to get an device address from the device address pool
2409 //
2410 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2411 return STATUS_DEVICE_DATA_ERROR;
2412 }
2413
2414 do
2415 {
2416 //
2417 // now set the device address
2418 //
2419 Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
2420
2421 if (NT_SUCCESS(Status))
2422 break;
2423
2424 }while(Index++ < 3 );
2425
2426 //
2427 // check for failure
2428 //
2429 if (!NT_SUCCESS(Status))
2430 {
2431 //
2432 // failed to set device address
2433 //
2434 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
2435
2436 //
2437 // release address
2438 //
2439 Controller->ReleaseDeviceAddress(DeviceAddress);
2440
2441 //
2442 // return error
2443 //
2444 return STATUS_DEVICE_DATA_ERROR;
2445 }
2446
2447 //
2448 // done
2449 //
2450 return STATUS_SUCCESS;
2451 }
2452
2453 NTSTATUS
2454 USB_BUSIFFN
2455 USBHI_GetUsbDescriptors(
2456 PVOID BusContext,
2457 PUSB_DEVICE_HANDLE DeviceHandle,
2458 PUCHAR DeviceDescriptorBuffer,
2459 PULONG DeviceDescriptorBufferLength,
2460 PUCHAR ConfigDescriptorBuffer,
2461 PULONG ConfigDescriptorBufferLength)
2462 {
2463 PUSBDEVICE UsbDevice;
2464 CHubController * Controller;
2465
2466 DPRINT1("USBHI_GetUsbDescriptors\n");
2467
2468 //
2469 // sanity check
2470 //
2471 PC_ASSERT(DeviceDescriptorBuffer);
2472 PC_ASSERT(DeviceDescriptorBufferLength);
2473 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
2474 PC_ASSERT(ConfigDescriptorBufferLength);
2475 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
2476
2477 //
2478 // first get controller
2479 //
2480 Controller = (CHubController *)BusContext;
2481 PC_ASSERT(Controller);
2482
2483
2484 //
2485 // get device object
2486 //
2487 UsbDevice = (PUSBDEVICE)DeviceHandle;
2488 PC_ASSERT(UsbDevice);
2489
2490 //
2491 // validate device handle
2492 //
2493 if (!Controller->ValidateUsbDevice(UsbDevice))
2494 {
2495 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
2496
2497 //
2498 // invalid device handle
2499 //
2500 return STATUS_DEVICE_NOT_CONNECTED;
2501 }
2502
2503 //
2504 // get device descriptor
2505 //
2506 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
2507
2508 //
2509 // store result length
2510 //
2511 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
2512
2513 //
2514 // get configuration descriptor
2515 //
2516 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
2517
2518 //
2519 // complete the request
2520 //
2521 return STATUS_SUCCESS;
2522 }
2523
2524 NTSTATUS
2525 USB_BUSIFFN
2526 USBHI_RemoveUsbDevice(
2527 PVOID BusContext,
2528 PUSB_DEVICE_HANDLE DeviceHandle,
2529 ULONG Flags)
2530 {
2531 PUSBDEVICE UsbDevice;
2532 CHubController * Controller;
2533 NTSTATUS Status;
2534
2535 DPRINT1("USBHI_RemoveUsbDevice\n");
2536
2537 //
2538 // first get controller
2539 //
2540 Controller = (CHubController *)BusContext;
2541 PC_ASSERT(Controller);
2542
2543 //
2544 // get device object
2545 //
2546 UsbDevice = (PUSBDEVICE)DeviceHandle;
2547 PC_ASSERT(UsbDevice);
2548
2549 //
2550 // validate device handle
2551 //
2552 if (!Controller->ValidateUsbDevice(UsbDevice))
2553 {
2554 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
2555
2556 //
2557 // invalid device handle
2558 //
2559 return STATUS_DEVICE_NOT_CONNECTED;
2560 }
2561
2562 //
2563 // check if there were flags passed
2564 //
2565 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
2566 {
2567 //
2568 // ignore flags for now
2569 //
2570 return STATUS_SUCCESS;
2571 }
2572
2573 //
2574 // remove device
2575 //
2576 Status = Controller->RemoveUsbDevice(UsbDevice);
2577 if (!NT_SUCCESS(Status))
2578 {
2579 //
2580 // invalid device handle
2581 //
2582 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
2583 PC_ASSERT(0);
2584 return STATUS_DEVICE_NOT_CONNECTED;
2585 }
2586
2587 //
2588 // release usb device
2589 //
2590 UsbDevice->Release();
2591
2592 //
2593 // done
2594 //
2595 return STATUS_SUCCESS;
2596 }
2597
2598 NTSTATUS
2599 USB_BUSIFFN
2600 USBHI_RestoreUsbDevice(
2601 PVOID BusContext,
2602 PUSB_DEVICE_HANDLE OldDeviceHandle,
2603 PUSB_DEVICE_HANDLE NewDeviceHandle)
2604 {
2605 PUSBDEVICE OldUsbDevice, NewUsbDevice;
2606 CHubController * Controller;
2607
2608 DPRINT1("USBHI_RestoreUsbDevice\n");
2609
2610 //
2611 // first get controller
2612 //
2613 Controller = (CHubController *)BusContext;
2614 PC_ASSERT(Controller);
2615
2616 //
2617 // get device object
2618 //
2619 OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
2620 NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
2621 PC_ASSERT(OldUsbDevice);
2622 PC_ASSERT(NewDeviceHandle);
2623
2624 //
2625 // validate device handle
2626 //
2627 PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
2628 PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
2629
2630 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
2631 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
2632
2633 //
2634 // remove old device handle
2635 //
2636 USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
2637
2638 return STATUS_SUCCESS;
2639 }
2640
2641 NTSTATUS
2642 USB_BUSIFFN
2643 USBHI_QueryDeviceInformation(
2644 PVOID BusContext,
2645 PUSB_DEVICE_HANDLE DeviceHandle,
2646 PVOID DeviceInformationBuffer,
2647 ULONG DeviceInformationBufferLength,
2648 PULONG LengthReturned)
2649 {
2650 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
2651 PUSBDEVICE UsbDevice;
2652 CHubController * Controller;
2653
2654 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
2655
2656 //
2657 // sanity check
2658 //
2659 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
2660 PC_ASSERT(DeviceInformationBuffer);
2661 PC_ASSERT(LengthReturned);
2662
2663 //
2664 // get controller object
2665 //
2666 Controller = (CHubController*)BusContext;
2667 PC_ASSERT(Controller);
2668
2669 //
2670 // get device object
2671 //
2672 UsbDevice = (PUSBDEVICE)DeviceHandle;
2673 PC_ASSERT(UsbDevice);
2674
2675 if (BusContext != DeviceHandle)
2676 {
2677 //
2678 // validate device handle
2679 //
2680 if (!Controller->ValidateUsbDevice(UsbDevice))
2681 {
2682 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
2683
2684 //
2685 // invalid device handle
2686 //
2687 return STATUS_DEVICE_NOT_CONNECTED;
2688 }
2689
2690 //
2691 // access information buffer
2692 //
2693 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2694
2695 //
2696 // initialize with default values
2697 //
2698 DeviceInfo->InformationLevel = 0;
2699 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2700 DeviceInfo->PortNumber = UsbDevice->GetPort();
2701 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
2702 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
2703 DeviceInfo->HubAddress = 0; //FIXME
2704 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
2705 DeviceInfo->DeviceType = UsbDevice->GetType();
2706 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2707
2708 //
2709 // get device descriptor
2710 //
2711 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
2712
2713 //
2714 // FIXME return pipe information
2715 //
2716
2717 //
2718 // store result length
2719 //
2720 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
2721
2722 return STATUS_SUCCESS;
2723 }
2724
2725 //
2726 // access information buffer
2727 //
2728 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2729
2730 //
2731 // initialize with default values
2732 //
2733 DeviceInfo->InformationLevel = 0;
2734 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2735 DeviceInfo->PortNumber = 0;
2736 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
2737 DeviceInfo->DeviceAddress = 0;
2738 DeviceInfo->HubAddress = 0; //FIXME
2739 DeviceInfo->DeviceSpeed = UsbFullSpeed; //FIXME
2740 DeviceInfo->DeviceType = Usb11Device; //FIXME
2741 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2742
2743 //
2744 // get device descriptor
2745 //
2746 RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
2747
2748 //
2749 // FIXME return pipe information
2750 //
2751
2752 //
2753 // store result length
2754 //
2755 #ifdef _MSC_VER
2756 *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
2757 #else
2758 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
2759 #endif
2760 //
2761 // done
2762 //
2763 return STATUS_SUCCESS;
2764 }
2765
2766 NTSTATUS
2767 USB_BUSIFFN
2768 USBHI_GetControllerInformation(
2769 PVOID BusContext,
2770 PVOID ControllerInformationBuffer,
2771 ULONG ControllerInformationBufferLength,
2772 PULONG LengthReturned)
2773 {
2774 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
2775
2776 DPRINT1("USBHI_GetControllerInformation\n");
2777
2778 //
2779 // sanity checks
2780 //
2781 PC_ASSERT(ControllerInformationBuffer);
2782 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
2783
2784 //
2785 // get controller info buffer
2786 //
2787 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
2788
2789 //
2790 // FIXME only version 0 is supported for now
2791 //
2792 PC_ASSERT(ControllerInfo->InformationLevel == 0);
2793
2794 //
2795 // fill in information
2796 //
2797 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
2798 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
2799 ControllerInfo->IsHighSpeedController = FALSE;
2800
2801 //
2802 // set length returned
2803 //
2804 *LengthReturned = ControllerInfo->ActualLength;
2805
2806 //
2807 // done
2808 //
2809 return STATUS_SUCCESS;
2810 }
2811
2812 NTSTATUS
2813 USB_BUSIFFN
2814 USBHI_ControllerSelectiveSuspend(
2815 PVOID BusContext,
2816 BOOLEAN Enable)
2817 {
2818 UNIMPLEMENTED
2819 return STATUS_NOT_IMPLEMENTED;
2820 }
2821
2822 NTSTATUS
2823 USB_BUSIFFN
2824 USBHI_GetExtendedHubInformation(
2825 PVOID BusContext,
2826 PDEVICE_OBJECT HubPhysicalDeviceObject,
2827 PVOID HubInformationBuffer,
2828 ULONG HubInformationBufferLength,
2829 PULONG LengthReturned)
2830 {
2831 PUSB_EXTHUB_INFORMATION_0 HubInfo;
2832 CHubController * Controller;
2833 PUSBHARDWAREDEVICE Hardware;
2834 ULONG Index;
2835 ULONG NumPort, Dummy2;
2836 USHORT Dummy1;
2837 NTSTATUS Status;
2838
2839 DPRINT1("USBHI_GetExtendedHubInformation\n");
2840
2841 //
2842 // sanity checks
2843 //
2844 PC_ASSERT(HubInformationBuffer);
2845 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
2846 PC_ASSERT(LengthReturned);
2847
2848 //
2849 // get hub controller
2850 //
2851 Controller = (CHubController *)BusContext;
2852 PC_ASSERT(Controller);
2853
2854 //
2855 // get usb hardware device
2856 //
2857 Hardware = Controller->GetUsbHardware();
2858
2859 //
2860 // retrieve number of ports
2861 //
2862 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
2863 if (!NT_SUCCESS(Status))
2864 {
2865 //
2866 // failed to get hardware details, ouch ;)
2867 //
2868 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
2869 return Status;
2870 }
2871
2872 //
2873 // get hub information buffer
2874 //
2875 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
2876
2877 //
2878 // initialize hub information
2879 //
2880 HubInfo->InformationLevel = 0;
2881
2882 //
2883 // store port count
2884 //
2885 HubInfo->NumberOfPorts = NumPort;
2886
2887 //
2888 // initialize port information
2889 //
2890 for(Index = 0; Index < NumPort; Index++)
2891 {
2892 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
2893 HubInfo->Port[Index].PortLabelNumber = Index + 1;
2894 HubInfo->Port[Index].VidOverride = 0;
2895 HubInfo->Port[Index].PidOverride = 0;
2896 HubInfo->Port[Index].PortAttributes = 0; //FIXME
2897 }
2898
2899 //
2900 // store result length
2901 //
2902 #ifdef _MSC_VER
2903 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
2904 #else
2905 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
2906 #endif
2907
2908 //
2909 // done
2910 //
2911 return STATUS_SUCCESS;
2912 }
2913
2914 NTSTATUS
2915 USB_BUSIFFN
2916 USBHI_GetRootHubSymbolicName(
2917 PVOID BusContext,
2918 PVOID HubSymNameBuffer,
2919 ULONG HubSymNameBufferLength,
2920 PULONG HubSymNameActualLength)
2921 {
2922 UNIMPLEMENTED
2923 return STATUS_NOT_IMPLEMENTED;
2924 }
2925
2926 PVOID
2927 USB_BUSIFFN
2928 USBHI_GetDeviceBusContext(
2929 PVOID HubBusContext,
2930 PVOID DeviceHandle)
2931 {
2932 UNIMPLEMENTED
2933 return NULL;
2934 }
2935
2936 NTSTATUS
2937 USB_BUSIFFN
2938 USBHI_RootHubInitNotification(
2939 PVOID BusContext,
2940 PVOID CallbackContext,
2941 PRH_INIT_CALLBACK CallbackRoutine)
2942 {
2943 CHubController * Controller;
2944
2945 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
2946
2947 //
2948 // get controller object
2949 //
2950 Controller = (CHubController*)BusContext;
2951 PC_ASSERT(Controller);
2952
2953 //
2954 // set notification routine
2955 //
2956 Controller->SetNotification(CallbackContext, CallbackRoutine);
2957
2958 //
2959 // FIXME: determine when to perform callback
2960 //
2961 CallbackRoutine(CallbackContext);
2962
2963 //
2964 // done
2965 //
2966 return STATUS_SUCCESS;
2967 }
2968
2969 VOID
2970 USB_BUSIFFN
2971 USBHI_FlushTransfers(
2972 PVOID BusContext,
2973 PVOID DeviceHandle)
2974 {
2975 UNIMPLEMENTED
2976 }
2977
2978 VOID
2979 USB_BUSIFFN
2980 USBHI_SetDeviceHandleData(
2981 PVOID BusContext,
2982 PVOID DeviceHandle,
2983 PDEVICE_OBJECT UsbDevicePdo)
2984 {
2985 PUSBDEVICE UsbDevice;
2986 CHubController * Controller;
2987
2988 //
2989 // get controller
2990 //
2991 Controller = (CHubController *)BusContext;
2992 PC_ASSERT(Controller);
2993
2994 //
2995 // get device handle
2996 //
2997 UsbDevice = (PUSBDEVICE)DeviceHandle;
2998
2999 //
3000 // validate device handle
3001 //
3002 if (!Controller->ValidateUsbDevice(UsbDevice))
3003 {
3004 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
3005
3006 //
3007 // invalid handle
3008 //
3009 return;
3010 }
3011 else
3012 {
3013 //
3014 // usbhub sends this request as a part of the Pnp startup sequence
3015 // looks like we need apply a dragon voodoo to fixup the device stack
3016 // otherwise usbhub will cause a bugcheck
3017 //
3018 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo);
3019
3020 //
3021 // sanity check
3022 //
3023 PC_ASSERT(UsbDevicePdo->AttachedDevice);
3024
3025 //
3026 // should be usbstor
3027 // fixup device stack voodoo part #2
3028 //
3029 UsbDevicePdo->AttachedDevice->StackSize++;
3030
3031 //
3032 // set device handle data
3033 //
3034 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
3035 }
3036 }
3037
3038 //=================================================================================================
3039 //
3040 // USB Device Interface functions
3041 //
3042
3043 VOID
3044 USB_BUSIFFN
3045 USBDI_GetUSBDIVersion(
3046 PVOID BusContext,
3047 PUSBD_VERSION_INFORMATION VersionInformation,
3048 PULONG HcdCapabilites)
3049 {
3050 CHubController * Controller;
3051 PUSBHARDWAREDEVICE Device;
3052 ULONG Speed, Dummy2;
3053 USHORT Dummy1;
3054
3055 DPRINT1("USBDI_GetUSBDIVersion\n");
3056
3057 //
3058 // get controller
3059 //
3060 Controller = (CHubController*)BusContext;
3061
3062 //
3063 // get usb hardware
3064 //
3065 Device = Controller->GetUsbHardware();
3066 PC_ASSERT(Device);
3067
3068 if (VersionInformation)
3069 {
3070 //
3071 // windows xp supported
3072 //
3073 VersionInformation->USBDI_Version = 0x00000500;
3074
3075 //
3076 // get device speed
3077 //
3078 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3079
3080 //
3081 // store speed details
3082 //
3083 VersionInformation->Supported_USB_Version = Speed;
3084 }
3085
3086 //
3087 // no flags supported
3088 //
3089 *HcdCapabilites = 0;
3090 }
3091
3092 NTSTATUS
3093 USB_BUSIFFN
3094 USBDI_QueryBusTime(
3095 PVOID BusContext,
3096 PULONG CurrentFrame)
3097 {
3098 UNIMPLEMENTED
3099 return STATUS_NOT_IMPLEMENTED;
3100 }
3101
3102 NTSTATUS
3103 USB_BUSIFFN
3104 USBDI_SubmitIsoOutUrb(
3105 PVOID BusContext,
3106 PURB Urb)
3107 {
3108 UNIMPLEMENTED
3109 return STATUS_NOT_IMPLEMENTED;
3110 }
3111
3112 NTSTATUS
3113 USB_BUSIFFN
3114 USBDI_QueryBusInformation(
3115 PVOID BusContext,
3116 ULONG Level,
3117 PVOID BusInformationBuffer,
3118 PULONG BusInformationBufferLength,
3119 PULONG BusInformationActualLength)
3120 {
3121 UNIMPLEMENTED
3122 return STATUS_NOT_IMPLEMENTED;
3123 }
3124
3125 BOOLEAN
3126 USB_BUSIFFN
3127 USBDI_IsDeviceHighSpeed(
3128 PVOID BusContext)
3129 {
3130 CHubController * Controller;
3131 PUSBHARDWAREDEVICE Device;
3132 ULONG Speed, Dummy2;
3133 USHORT Dummy1;
3134
3135 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3136
3137 //
3138 // get controller
3139 //
3140 Controller = (CHubController*)BusContext;
3141
3142 //
3143 // get usb hardware
3144 //
3145 Device = Controller->GetUsbHardware();
3146 PC_ASSERT(Device);
3147
3148 //
3149 // get device speed
3150 //
3151 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3152
3153 //
3154 // USB 2.0 equals 0x200
3155 //
3156 return (Speed == 0x200);
3157 }
3158
3159 NTSTATUS
3160 USB_BUSIFFN
3161 USBDI_EnumLogEntry(
3162 PVOID BusContext,
3163 ULONG DriverTag,
3164 ULONG EnumTag,
3165 ULONG P1,
3166 ULONG P2)
3167 {
3168 UNIMPLEMENTED
3169 return STATUS_NOT_IMPLEMENTED;
3170 }
3171
3172 NTSTATUS
3173 CHubController::HandleQueryInterface(
3174 PIO_STACK_LOCATION IoStack)
3175 {
3176 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
3177 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
3178 UNICODE_STRING GuidBuffer;
3179 NTSTATUS Status;
3180
3181 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
3182 {
3183 //
3184 // get request parameters
3185 //
3186 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
3187 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
3188
3189 //
3190 // check version
3191 //
3192 if (IoStack->Parameters.QueryInterface.Version >= 6)
3193 {
3194 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3195
3196 //
3197 // version not supported
3198 //
3199 return STATUS_NOT_SUPPORTED;
3200 }
3201
3202 //
3203 // Interface version 0
3204 //
3205 if (IoStack->Parameters.QueryInterface.Version >= 0)
3206 {
3207 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
3208 InterfaceHub->BusContext = PVOID(this);
3209 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
3210 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
3211 }
3212
3213 //
3214 // Interface version 1
3215 //
3216 if (IoStack->Parameters.QueryInterface.Version >= 1)
3217 {
3218 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
3219 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
3220 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
3221 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
3222 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
3223 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
3224 }
3225
3226 //
3227 // Interface version 2
3228 //
3229 if (IoStack->Parameters.QueryInterface.Version >= 2)
3230 {
3231 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
3232 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
3233 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
3234 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
3235 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
3236 }
3237
3238 //
3239 // Interface version 3
3240 //
3241 if (IoStack->Parameters.QueryInterface.Version >= 3)
3242 {
3243 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
3244 }
3245
3246 //
3247 // Interface version 4
3248 //
3249 if (IoStack->Parameters.QueryInterface.Version >= 4)
3250 {
3251 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
3252 }
3253
3254 //
3255 // Interface version 5
3256 //
3257 if (IoStack->Parameters.QueryInterface.Version >= 5)
3258 {
3259 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
3260 }
3261
3262 //
3263 // request completed
3264 //
3265 return STATUS_SUCCESS;
3266 }
3267 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
3268 {
3269 //
3270 // get request parameters
3271 //
3272 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
3273 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
3274
3275 //
3276 // check version
3277 //
3278 if (IoStack->Parameters.QueryInterface.Version >= 3)
3279 {
3280 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3281
3282 //
3283 // version not supported
3284 //
3285 return STATUS_NOT_SUPPORTED;
3286 }
3287
3288 //
3289 // interface version 0
3290 //
3291 if (IoStack->Parameters.QueryInterface.Version >= 0)
3292 {
3293 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
3294 InterfaceDI->BusContext = PVOID(this);
3295 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
3296 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
3297 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
3298 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
3299 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
3300 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
3301 }
3302
3303 //
3304 // interface version 1
3305 //
3306 if (IoStack->Parameters.QueryInterface.Version >= 1)
3307 {
3308 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
3309 }
3310
3311 //
3312 // interface version 2
3313 //
3314 if (IoStack->Parameters.QueryInterface.Version >= 2)
3315 {
3316 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
3317 }
3318
3319 //
3320 // request completed
3321 //
3322 return STATUS_SUCCESS;
3323 }
3324 else
3325 {
3326 //
3327 // convert guid to string
3328 //
3329 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
3330 if (NT_SUCCESS(Status))
3331 {
3332 //
3333 // print interface
3334 //
3335 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
3336
3337 //
3338 // free guid buffer
3339 //
3340 RtlFreeUnicodeString(&GuidBuffer);
3341 }
3342 }
3343 return STATUS_NOT_SUPPORTED;
3344 }
3345
3346 NTSTATUS
3347 CHubController::SetDeviceInterface(
3348 BOOLEAN Enable)
3349 {
3350 NTSTATUS Status = STATUS_SUCCESS;
3351
3352 if (Enable)
3353 {
3354 //
3355 // register device interface
3356 //
3357 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
3358
3359 if (NT_SUCCESS(Status))
3360 {
3361 //
3362 // now enable the device interface
3363 //
3364 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
3365
3366 //
3367 // enable interface
3368 //
3369 m_InterfaceEnabled = TRUE;
3370 }
3371 }
3372 else if (m_InterfaceEnabled)
3373 {
3374 //
3375 // disable device interface
3376 //
3377 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
3378
3379 if (NT_SUCCESS(Status))
3380 {
3381 //
3382 // now delete interface string
3383 //
3384 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
3385 }
3386
3387 //
3388 // disable interface
3389 //
3390 m_InterfaceEnabled = FALSE;
3391 }
3392
3393 //
3394 // done
3395 //
3396 return STATUS_SUCCESS;
3397 }
3398
3399 NTSTATUS
3400 CHubController::CreatePDO(
3401 PDRIVER_OBJECT DriverObject,
3402 PDEVICE_OBJECT * OutDeviceObject)
3403 {
3404 WCHAR CharDeviceName[64];
3405 NTSTATUS Status;
3406 ULONG UsbDeviceNumber = 0;
3407 UNICODE_STRING DeviceName;
3408
3409 while (TRUE)
3410 {
3411 //
3412 // construct device name
3413 //
3414 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
3415
3416 //
3417 // initialize device name
3418 //
3419 RtlInitUnicodeString(&DeviceName, CharDeviceName);
3420
3421 //
3422 // create device
3423 //
3424 Status = IoCreateDevice(DriverObject,
3425 sizeof(COMMON_DEVICE_EXTENSION),
3426 &DeviceName,
3427 FILE_DEVICE_CONTROLLER,
3428 0,
3429 FALSE,
3430 OutDeviceObject);
3431
3432 /* check for success */
3433 if (NT_SUCCESS(Status))
3434 break;
3435
3436 //
3437 // is there a device object with that same name
3438 //
3439 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
3440 {
3441 //
3442 // Try the next name
3443 //
3444 UsbDeviceNumber++;
3445 continue;
3446 }
3447
3448 //
3449 // bail out on other errors
3450 //
3451 if (!NT_SUCCESS(Status))
3452 {
3453 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
3454 return Status;
3455 }
3456 }
3457
3458 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
3459
3460 //
3461 // fixup device stack voodoo part #1
3462 //
3463 (*OutDeviceObject)->StackSize++;
3464
3465 /* done */
3466 return Status;
3467 }
3468
3469
3470
3471 NTSTATUS
3472 CreateHubController(
3473 PHUBCONTROLLER *OutHcdController)
3474 {
3475 PHUBCONTROLLER This;
3476
3477 //
3478 // allocate controller
3479 //
3480 This = new(NonPagedPool, TAG_USBOHCI) CHubController(0);
3481 if (!This)
3482 {
3483 //
3484 // failed to allocate
3485 //
3486 return STATUS_INSUFFICIENT_RESOURCES;
3487 }
3488
3489 //
3490 // add reference count
3491 //
3492 This->AddRef();
3493
3494 //
3495 // return result
3496 //
3497 *OutHcdController = (PHUBCONTROLLER)This;
3498
3499 //
3500 // done
3501 //
3502 return STATUS_SUCCESS;
3503 }
3504
3505 VOID StatusChangeEndpointCallBack(PVOID Context)
3506 {
3507 CHubController* This;
3508 PIRP Irp;
3509 This = (CHubController*)Context;
3510
3511 ASSERT(This);
3512
3513 Irp = This->m_PendingSCEIrp;
3514 if (!Irp)
3515 {
3516 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3517 return;
3518 }
3519
3520 This->m_PendingSCEIrp = NULL;
3521 This->QueryStatusChageEndpoint(Irp);
3522
3523 Irp->IoStatus.Status = STATUS_SUCCESS;
3524 Irp->IoStatus.Information = 0;
3525
3526 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3527 }