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