[LIBUSB]
[reactos.git] / reactos / lib / drivers / libusb / hub_controller.cpp
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/libusb/hub_controller.cpp
5 * PURPOSE: USB Common Driver Library.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11
12 #define INITGUID
13 #include "libusb.h"
14
15 VOID StatusChangeEndpointCallBack(
16 PVOID Context);
17
18 class CHubController : public IHubController,
19 public IDispatchIrp
20 {
21 public:
22 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
23
24 STDMETHODIMP_(ULONG) AddRef()
25 {
26 InterlockedIncrement(&m_Ref);
27 return m_Ref;
28 }
29 STDMETHODIMP_(ULONG) Release()
30 {
31 InterlockedDecrement(&m_Ref);
32
33 if (!m_Ref)
34 {
35 delete this;
36 return 0;
37 }
38 return m_Ref;
39 }
40
41 // IHubController interface functions
42 virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject, IN PHCDCONTROLLER Controller, IN PUSBHARDWAREDEVICE Device, IN BOOLEAN IsRootHubDevice, IN ULONG DeviceAddress);
43 virtual NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject);
44 virtual NTSTATUS GetHubControllerSymbolicLink(ULONG BufferLength, PVOID Buffer, PULONG RequiredLength);
45
46 // IDispatchIrp interface functions
47 virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
48 virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
49 virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
50
51 // local functions
52 NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack);
53 NTSTATUS SetDeviceInterface(BOOLEAN bEnable);
54 NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
55 PUSBHARDWAREDEVICE GetUsbHardware();
56 ULONG AcquireDeviceAddress();
57 VOID ReleaseDeviceAddress(ULONG DeviceAddress);
58 BOOLEAN ValidateUsbDevice(PUSBDEVICE UsbDevice);
59 NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice);
60 NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice);
61 VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
62 // internal ioctl routines
63 NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
64 NTSTATUS HandleGetDescriptorFromInterface(IN OUT PIRP Irp, PURB Urb);
65 NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
66 NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
67 NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
68 NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb);
69 NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
70 NTSTATUS HandleClassInterface(IN OUT PIRP Irp, PURB Urb);
71 NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb);
72 NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
73 NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb);
74 NTSTATUS HandleClearStall(IN OUT PIRP Irp, PURB Urb);
75 NTSTATUS HandleSyncResetAndClearStall(IN OUT PIRP Irp, PURB Urb);
76 NTSTATUS HandleAbortPipe(IN OUT PIRP Irp, PURB Urb);
77
78 friend VOID StatusChangeEndpointCallBack(PVOID Context);
79
80 // constructor / destructor
81 CHubController(IUnknown *OuterUnknown){}
82 virtual ~CHubController(){}
83
84 protected:
85 LONG m_Ref;
86 PHCDCONTROLLER m_Controller;
87 PUSBHARDWAREDEVICE m_Hardware;
88 BOOLEAN m_IsRootHubDevice;
89 ULONG m_DeviceAddress;
90
91 BOOLEAN m_InterfaceEnabled;
92 UNICODE_STRING m_HubDeviceInterfaceString;
93
94 PDEVICE_OBJECT m_HubControllerDeviceObject;
95 PDRIVER_OBJECT m_DriverObject;
96
97 PVOID m_HubCallbackContext;
98 PRH_INIT_CALLBACK m_HubCallbackRoutine;
99
100 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
101
102 KSPIN_LOCK m_Lock;
103 RTL_BITMAP m_DeviceAddressBitmap;
104 PULONG m_DeviceAddressBitmapBuffer;
105 LIST_ENTRY m_UsbDeviceList;
106 PIRP m_PendingSCEIrp;
107
108 //Internal Functions
109 BOOLEAN QueryStatusChageEndpoint(PIRP Irp);
110 };
111
112 typedef struct
113 {
114 LIST_ENTRY Entry;
115 PUSBDEVICE Device;
116 }USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY;
117
118 /* Lifted from Linux with slight changes */
119 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
120 {
121 0x12, /* bLength; */
122 USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */
123 0x00, 0x20, /* bcdUSB; v1.1 */
124 USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */
125 0x01, /* bDeviceSubClass; */
126 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
127 0x08, /* bMaxPacketSize0; 8 Bytes */
128 /* Fill Vendor and Product in when init root hub */
129 0x00, 0x00, /* idVendor; */
130 0x00, 0x00, /* idProduct; */
131 0x00, 0x00, /* bcdDevice */
132 0x00, /* iManufacturer; */
133 0x00, /* iProduct; */
134 0x00, /* iSerialNumber; */
135 0x01 /* bNumConfigurations; */
136
137 };
138
139 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR =
140 {
141 sizeof(USB_CONFIGURATION_DESCRIPTOR),
142 USB_CONFIGURATION_DESCRIPTOR_TYPE,
143 sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
144 1,
145 1,
146 0,
147 0x40, /* self powered */
148 0x0
149 };
150
151 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR =
152 {
153 sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */
154 USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType; Interface */
155 0, /* bInterfaceNumber; */
156 0, /* bAlternateSetting; */
157 0x1, /* bNumEndpoints; */
158 0x09, /* bInterfaceClass; HUB_CLASSCODE */
159 0x01, /* bInterfaceSubClass; */
160 0x00, /* bInterfaceProtocol: */
161 0x00, /* iInterface; */
162 };
163
164 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR =
165 {
166 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */
167 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
168 0x81, /* bEndPointAddress */
169 USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
170 0x01, /* wMaxPacketSize */
171 0xC /* bInterval */
172 };
173
174 //----------------------------------------------------------------------------------------
175 NTSTATUS
176 STDMETHODCALLTYPE
177 CHubController::QueryInterface(
178 IN REFIID refiid,
179 OUT PVOID* Output)
180 {
181 return STATUS_UNSUCCESSFUL;
182 }
183 //----------------------------------------------------------------------------------------
184 NTSTATUS
185 CHubController::Initialize(
186 IN PDRIVER_OBJECT DriverObject,
187 IN PHCDCONTROLLER Controller,
188 IN PUSBHARDWAREDEVICE Device,
189 IN BOOLEAN IsRootHubDevice,
190 IN ULONG DeviceAddress)
191 {
192 NTSTATUS Status;
193 PCOMMON_DEVICE_EXTENSION DeviceExtension;
194 USHORT VendorID, DeviceID;
195 ULONG Dummy1;
196
197 DPRINT1("CHubController::Initialize\n");
198
199 //
200 // initialize members
201 //
202 m_Controller = Controller;
203 m_Hardware = Device;
204 m_IsRootHubDevice = IsRootHubDevice;
205 m_DeviceAddress = DeviceAddress;
206 m_DriverObject = DriverObject;
207 KeInitializeSpinLock(&m_Lock);
208 InitializeListHead(&m_UsbDeviceList);
209
210 //
211 // allocate device address bitmap buffer
212 //
213 m_DeviceAddressBitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, 16, TAG_USBLIB);
214 if (!m_DeviceAddressBitmapBuffer)
215 {
216 //
217 // no memory
218 //
219 return STATUS_INSUFFICIENT_RESOURCES;
220 }
221
222 //
223 // initialize device address bitmap
224 //
225 RtlInitializeBitMap(&m_DeviceAddressBitmap, m_DeviceAddressBitmapBuffer, 128);
226 RtlClearAllBits(&m_DeviceAddressBitmap);
227
228
229 //
230 // create PDO
231 //
232 Status = CreatePDO(m_DriverObject, &m_HubControllerDeviceObject);
233 if (!NT_SUCCESS(Status))
234 {
235 //
236 // failed to create hub device object
237 //
238 return Status;
239 }
240
241 //
242 // get device extension
243 //
244 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_HubControllerDeviceObject->DeviceExtension;
245
246 //
247 // initialize device extension
248 //
249 DeviceExtension->IsFDO = FALSE;
250 DeviceExtension->IsHub = TRUE; //FIXME
251 DeviceExtension->Dispatcher = PDISPATCHIRP(this);
252
253 //
254 // intialize device descriptor
255 //
256 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
257 RtlMoveMemory(&m_DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
258
259 if (NT_SUCCESS(m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &Dummy1, &Dummy1)))
260 {
261 //
262 // update device descriptor
263 //
264 m_DeviceDescriptor.idVendor = VendorID;
265 m_DeviceDescriptor.idProduct = DeviceID;
266 m_DeviceDescriptor.bcdUSB = 0x200; //FIXME
267 }
268
269 //
270 // Set the SCE Callback that the Hardware Device will call on port status change
271 //
272 Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this);
273
274 //
275 // clear init flag
276 //
277 m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
278
279 return STATUS_SUCCESS;
280 }
281
282 //
283 // Queries the ports to see if there has been a device connected or removed.
284 //
285 BOOLEAN
286 CHubController::QueryStatusChageEndpoint(
287 PIRP Irp)
288 {
289 ULONG PortCount, PortId;
290 PIO_STACK_LOCATION IoStack;
291 USHORT PortStatus, PortChange;
292 PURB Urb;
293 PUCHAR TransferBuffer;
294 UCHAR Changed = FALSE;
295
296 //
297 // get current stack location
298 //
299 IoStack = IoGetCurrentIrpStackLocation(Irp);
300 ASSERT(IoStack);
301
302 //
303 // Get the Urb
304 //
305 Urb = (PURB)IoStack->Parameters.Others.Argument1;
306 ASSERT(Urb);
307
308 //
309 // Get the number of ports and check each one for device connected
310 //
311 m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
312 DPRINT1("[USBLIB] SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, Urb->UrbBulkOrInterruptTransfer.TransferFlags, Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
313
314 TransferBuffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer;
315
316 //
317 // Loop the ports
318 //
319 for (PortId = 0; PortId < PortCount; PortId++)
320 {
321 m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
322
323 DPRINT1("[USBLIB] Port %d: Status %x, Change %x\n", PortId, PortStatus, PortChange);
324
325
326 //
327 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
328 //
329 if (PortChange != 0)
330 {
331 DPRINT1("[USBLIB] Change state on port %d\n", PortId);
332 // Set the value for the port number
333 *TransferBuffer = 1 << ((PortId + 1) & 7);
334 Changed = TRUE;
335 }
336 }
337
338 return Changed;
339 }
340
341 //-----------------------------------------------------------------------------------------
342 NTSTATUS
343 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject)
344 {
345 //
346 // store controller object
347 //
348 *HubDeviceObject = m_HubControllerDeviceObject;
349
350 return STATUS_SUCCESS;
351 }
352 //-----------------------------------------------------------------------------------------
353 NTSTATUS
354 CHubController::GetHubControllerSymbolicLink(
355 ULONG BufferLength,
356 PVOID Buffer,
357 PULONG RequiredLength)
358 {
359 if (!m_InterfaceEnabled)
360 {
361 //
362 // device interface not yet enabled
363 //
364 return STATUS_UNSUCCESSFUL;
365 }
366
367 if (BufferLength < (ULONG)m_HubDeviceInterfaceString.Length - 8)
368 {
369 //
370 // buffer too small
371 // length is without '\??\'
372 //
373 *RequiredLength = m_HubDeviceInterfaceString.Length- 8;
374
375 //
376 // done
377 //
378 return STATUS_BUFFER_OVERFLOW;
379 }
380
381 //
382 // copy symbolic link
383 //
384 RtlCopyMemory(Buffer, &m_HubDeviceInterfaceString.Buffer[4], m_HubDeviceInterfaceString.Length - 8);
385
386 //
387 // store length, length is without '\??\'
388 //
389 *RequiredLength = m_HubDeviceInterfaceString.Length - 8;
390
391 //
392 // done
393 //
394 return STATUS_SUCCESS;
395 }
396
397 //-----------------------------------------------------------------------------------------
398 NTSTATUS
399 CHubController::HandlePnp(
400 IN PDEVICE_OBJECT DeviceObject,
401 IN OUT PIRP Irp)
402 {
403 PIO_STACK_LOCATION IoStack;
404 PCOMMON_DEVICE_EXTENSION DeviceExtension;
405 PDEVICE_CAPABILITIES DeviceCapabilities;
406 PPNP_BUS_INFORMATION BusInformation;
407 PDEVICE_RELATIONS DeviceRelations;
408 NTSTATUS Status;
409 ULONG Index = 0, Length;
410 USHORT VendorID, DeviceID;
411 ULONG HiSpeed, NumPorts;
412 WCHAR Buffer[300];
413 LPWSTR DeviceName;
414
415 //
416 // get device extension
417 //
418 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
419
420 //
421 // sanity check
422 //
423 ASSERT(DeviceExtension->IsFDO == FALSE);
424
425 //
426 // get current stack location
427 //
428 IoStack = IoGetCurrentIrpStackLocation(Irp);
429
430 switch(IoStack->MinorFunction)
431 {
432 case IRP_MN_START_DEVICE:
433 {
434 DPRINT("[USBLIB] HandlePnp IRP_MN_START_DEVICE\n");
435 //
436 // register device interface
437 //
438 Status = SetDeviceInterface(TRUE);
439 break;
440 }
441 case IRP_MN_QUERY_STOP_DEVICE:
442 case IRP_MN_QUERY_REMOVE_DEVICE:
443 {
444 //
445 // sure
446 //
447 Status = STATUS_SUCCESS;
448 break;
449 }
450 case IRP_MN_QUERY_ID:
451 {
452 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack->Parameters.QueryId.IdType);
453
454 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
455 {
456 if (m_Hardware)
457 {
458 //
459 // query device id
460 //
461 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
462
463 if (HiSpeed == 0x200)
464 {
465 //
466 // USB 2.0 hub
467 //
468 swprintf(Buffer, L"USB\\ROOT_HUB20");
469 }
470 else
471 {
472 //
473 // USB 1.1 hub
474 //
475 swprintf(Buffer, L"USB\\ROOT_HUB");
476 }
477
478 DPRINT("Name %S\n", Buffer);
479
480 //
481 // calculate length
482 //
483 Length = (wcslen(Buffer) + 1);
484
485 //
486 // allocate buffer
487 //
488 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_USBLIB);
489
490 if (!DeviceName)
491 {
492 //
493 // no memory
494 //
495 Status = STATUS_INSUFFICIENT_RESOURCES;
496 break;
497 }
498
499 //
500 // copy device name
501 //
502 wcscpy(DeviceName, Buffer);
503
504 //
505 // store result
506 //
507 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
508 Status = STATUS_SUCCESS;
509 break;
510 }
511 Status = STATUS_UNSUCCESSFUL;
512 PC_ASSERT(0);
513 break;
514 }
515
516 if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
517 {
518 if (m_Hardware)
519 {
520 //
521 // query device id
522 //
523 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
524
525 if (!NT_SUCCESS(Status))
526 {
527 DPRINT1("[USBLIB] HandlePnp> failed to get hardware id %x\n", Status);
528 VendorID = 0x8086;
529 DeviceID = 0x3A37;
530 }
531
532 if (HiSpeed == 0x200)
533 {
534 //
535 // USB 2.0 hub
536 //
537 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
538 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID, DeviceID) + 1;
539 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
540 }
541 else
542 {
543 //
544 // USB 1.1 hub
545 //
546 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
547 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID, DeviceID) + 1;
548 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB") + 1;
549 }
550
551 Buffer[Index] = UNICODE_NULL;
552 Index++;
553
554
555 DPRINT1("[USBLIB] Name %S\n", Buffer);
556
557 //
558 // allocate buffer
559 //
560 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Index * sizeof(WCHAR), TAG_USBLIB);
561
562 if (!DeviceName)
563 {
564 //
565 // no memory
566 //
567 Status = STATUS_INSUFFICIENT_RESOURCES;
568 break;
569 }
570
571 //
572 // copy device name
573 //
574 RtlMoveMemory(DeviceName, Buffer, Index * sizeof(WCHAR));
575
576 //
577 // store result
578 //
579 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
580 Status = STATUS_SUCCESS;
581 break;
582 }
583 }
584 Status = STATUS_SUCCESS;
585 break;
586 }
587 case IRP_MN_QUERY_CAPABILITIES:
588 {
589 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
590
591 DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
592
593 DeviceCapabilities->LockSupported = FALSE;
594 DeviceCapabilities->EjectSupported = FALSE;
595 DeviceCapabilities->Removable = FALSE;
596 DeviceCapabilities->DockDevice = FALSE;
597 DeviceCapabilities->UniqueID = FALSE;
598 DeviceCapabilities->SilentInstall = FALSE;
599 DeviceCapabilities->RawDeviceOK = FALSE;
600 DeviceCapabilities->SurpriseRemovalOK = FALSE;
601 DeviceCapabilities->Address = 0;
602 DeviceCapabilities->UINumber = 0;
603 DeviceCapabilities->DeviceD2 = 1;
604
605 /* FIXME */
606 DeviceCapabilities->HardwareDisabled = FALSE;
607 DeviceCapabilities->NoDisplayInUI = FALSE;
608 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
609 for (Index = 1; Index < PowerSystemMaximum; Index++)
610 DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
611 DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
612 DeviceCapabilities->D1Latency = 0;
613 DeviceCapabilities->D2Latency = 0;
614 DeviceCapabilities->D3Latency = 0;
615
616 Status = STATUS_SUCCESS;
617 break;
618 }
619 case IRP_MN_QUERY_INTERFACE:
620 {
621 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_INTERFACE\n");
622
623 //
624 // handle device interface requests
625 //
626 Status = HandleQueryInterface(IoStack);
627 break;
628 }
629 case IRP_MN_REMOVE_DEVICE:
630 {
631 DPRINT("[USBLIB] HandlePnp IRP_MN_REMOVE_DEVICE\n");
632
633 //
634 // deactivate device interface for BUS PDO
635 //
636 SetDeviceInterface(FALSE);
637
638 //
639 // complete the request first
640 //
641 Irp->IoStatus.Status = STATUS_SUCCESS;
642 IoCompleteRequest(Irp, IO_NO_INCREMENT);
643
644 //
645 // now delete device
646 //
647 IoDeleteDevice(m_HubControllerDeviceObject);
648
649 //
650 // nullify pointer
651 //
652 m_HubControllerDeviceObject = 0;
653
654 //
655 // done
656 //
657 return STATUS_SUCCESS;
658 }
659 case IRP_MN_QUERY_DEVICE_RELATIONS:
660 {
661 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack->Parameters.QueryDeviceRelations.Type);
662
663 if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
664 {
665 //
666 // allocate device relations
667 //
668 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_USBLIB);
669 if (!DeviceRelations)
670 {
671 //
672 // no memory
673 //
674 Status = STATUS_INSUFFICIENT_RESOURCES;
675 break;
676 }
677
678 //
679 // initialize device relations
680 //
681 DeviceRelations->Count = 1;
682 DeviceRelations->Objects[0] = DeviceObject;
683 ObReferenceObject(DeviceObject);
684
685 //
686 // done
687 //
688 Status = STATUS_SUCCESS;
689 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
690 }
691 else
692 {
693 //
694 // not handled
695 //
696 Status = Irp->IoStatus.Status;
697 }
698 break;
699 }
700 case IRP_MN_QUERY_BUS_INFORMATION:
701 {
702 DPRINT("[USBLIB] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
703
704 //
705 // allocate buffer for bus information
706 //
707 BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
708 if (BusInformation)
709 {
710 //
711 // copy BUS guid
712 //
713 RtlMoveMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_USB, sizeof(GUID));
714
715 //
716 // set bus type
717 //
718 BusInformation->LegacyBusType = PNPBus;
719 BusInformation->BusNumber = 0;
720
721 Status = STATUS_SUCCESS;
722 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
723 }
724 else
725 {
726 //
727 // no memory
728 //
729 Status = STATUS_INSUFFICIENT_RESOURCES;
730 }
731 break;
732 }
733 case IRP_MN_STOP_DEVICE:
734 {
735 DPRINT("[USBLIB] HandlePnp IRP_MN_STOP_DEVICE\n");
736 //
737 // stop device
738 //
739 Status = STATUS_SUCCESS;
740 break;
741 }
742 default:
743 {
744 //
745 // ignore request with default status
746 //
747 Status = Irp->IoStatus.Status;
748 break;
749 }
750 }
751
752 //
753 // complete request
754 //
755 Irp->IoStatus.Status = Status;
756 IoCompleteRequest(Irp, IO_NO_INCREMENT);
757
758 //
759 // done
760 //
761 return Status;
762 }
763
764 //-----------------------------------------------------------------------------------------
765 NTSTATUS
766 CHubController::HandlePower(
767 IN PDEVICE_OBJECT DeviceObject,
768 IN OUT PIRP Irp)
769 {
770 UNIMPLEMENTED
771 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
772 IoCompleteRequest(Irp, IO_NO_INCREMENT);
773 return STATUS_NOT_IMPLEMENTED;
774 }
775
776 //-----------------------------------------------------------------------------------------
777 NTSTATUS
778 CHubController::HandleIsochronousTransfer(
779 IN OUT PIRP Irp,
780 PURB Urb)
781 {
782 PUSBDEVICE UsbDevice;
783 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
784
785 //
786 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
787 //
788 EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle;
789
790 if (!EndPointDesc)
791 {
792 DPRINT1("[USBLIB] Error No EndpointDesc\n");
793 Urb->UrbIsochronousTransfer.Hdr.Status = USBD_STATUS_INVALID_PIPE_HANDLE;
794 return STATUS_INVALID_PARAMETER;
795 }
796
797 //
798 // sanity checks
799 //
800 ASSERT(EndPointDesc);
801 ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS);
802
803 //
804 // check if this is a valid usb device handle
805 //
806 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
807 {
808 DPRINT1("[USBLIB] HandleIsochronousTransfer invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
809
810 //
811 // invalid device handle
812 //
813 return STATUS_DEVICE_NOT_CONNECTED;
814 }
815
816 //
817 // get device
818 //
819 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
820
821 return UsbDevice->SubmitIrp(Irp);
822 }
823
824 //-----------------------------------------------------------------------------------------
825 NTSTATUS
826 CHubController::HandleBulkOrInterruptTransfer(
827 IN OUT PIRP Irp,
828 PURB Urb)
829 {
830 PUSBDEVICE UsbDevice;
831 PUSB_ENDPOINT EndPointDesc = NULL;
832 //
833 // First check if the request is for the Status Change Endpoint
834 //
835
836 //
837 // Is the Request for the root hub
838 //
839 if (Urb->UrbHeader.UsbdDeviceHandle == 0)
840 {
841 ASSERT(m_PendingSCEIrp == NULL);
842 if (QueryStatusChageEndpoint(Irp))
843 {
844 StatusChangeEndpointCallBack(this);
845 return STATUS_SUCCESS;
846 }
847
848 //
849 // Else pend the IRP, to be completed when a device connects or disconnects.
850 //
851 DPRINT("[USBLIB] Pending SCE Irp\n");
852 m_PendingSCEIrp = Irp;
853 IoMarkIrpPending(Irp);
854 return STATUS_PENDING;
855 }
856
857 //
858 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
859 //
860 EndPointDesc = (PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
861
862 //
863 // sanity checks
864 //
865 ASSERT(EndPointDesc);
866 ASSERT((EndPointDesc->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK || (EndPointDesc->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT);
867
868 //
869 // check if this is a valid usb device handle
870 //
871 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
872 {
873 DPRINT1("[USBLIB] HandleBulkOrInterruptTransfer invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
874
875 //
876 // invalid device handle
877 //
878 return STATUS_DEVICE_NOT_CONNECTED;
879 }
880
881 //
882 // get device
883 //
884 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
885 return UsbDevice->SubmitIrp(Irp);
886 }
887
888 //-----------------------------------------------------------------------------------------
889 NTSTATUS
890 CHubController::HandleClassOther(
891 IN OUT PIRP Irp,
892 PURB Urb)
893 {
894 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
895 USHORT PortStatus = 0, PortChange = 0;
896 PUSHORT Buffer;
897 ULONG NumPort;
898 ULONG PortId;
899
900 DPRINT("[USBLIB] HandleClassOther> Request %x Value %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
901
902 //
903 // get number of ports available
904 //
905 Status = m_Hardware->GetDeviceDetails(NULL, NULL, &NumPort, NULL);
906 PC_ASSERT(Status == STATUS_SUCCESS);
907
908 //
909 // sanity check
910 //
911 PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < (USHORT)NumPort);
912
913 //
914 // port range reported start from 1 -n
915 // convert back port id so it matches the hardware
916 //
917 PortId = Urb->UrbControlVendorClassRequest.Index - 1;
918
919 //
920 // check request code
921 //
922 switch(Urb->UrbControlVendorClassRequest.Request)
923 {
924 case USB_REQUEST_GET_STATUS:
925 {
926 //
927 // sanity check
928 //
929 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength == sizeof(USHORT) * 2);
930 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
931
932 //
933 // get port status
934 //
935 Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
936
937 if (NT_SUCCESS(Status))
938 {
939 //
940 // request contains buffer of 2 ushort which are used from submitting port status and port change status
941 //
942 DPRINT("[USBLIB] PortId %x PortStatus %x PortChange %x\n", PortId, PortStatus, PortChange);
943 Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer;
944
945 //
946 // store status, then port change
947 //
948 *Buffer = PortStatus;
949 Buffer++;
950 *Buffer = PortChange;
951 }
952
953 //
954 // done
955 //
956 break;
957 }
958 case USB_REQUEST_CLEAR_FEATURE:
959 {
960 switch (Urb->UrbControlVendorClassRequest.Value)
961 {
962 case C_PORT_CONNECTION:
963 Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
964 break;
965 case C_PORT_RESET:
966 Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
967 break;
968 default:
969 DPRINT("[USBLIB] Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
970 break;
971 }
972
973 break;
974 }
975 case USB_REQUEST_SET_FEATURE:
976 {
977 //
978 // request set feature
979 //
980 switch(Urb->UrbControlVendorClassRequest.Value)
981 {
982 case PORT_ENABLE:
983 {
984 //
985 // port enable is a no-op for EHCI
986 //
987 Status = STATUS_SUCCESS;
988 break;
989 }
990
991 case PORT_SUSPEND:
992 {
993 //
994 // set suspend port feature
995 //
996 Status = m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
997 break;
998 }
999 case PORT_POWER:
1000 {
1001 //
1002 // set power feature on port
1003 //
1004 Status = m_Hardware->SetPortFeature(PortId, PORT_POWER);
1005 break;
1006 }
1007
1008 case PORT_RESET:
1009 {
1010 //
1011 // reset port feature
1012 //
1013 Status = m_Hardware->SetPortFeature(PortId, PORT_RESET);
1014 PC_ASSERT(Status == STATUS_SUCCESS);
1015 break;
1016 }
1017 default:
1018 DPRINT1("[USBLIB] Unsupported request id %x\n", Urb->UrbControlVendorClassRequest.Value);
1019 PC_ASSERT(FALSE);
1020 }
1021 break;
1022 }
1023 default:
1024 DPRINT1("[USBLIB] HandleClassOther Unknown request code %x\n", Urb->UrbControlVendorClassRequest.Request);
1025 PC_ASSERT(0);
1026 Status = STATUS_INVALID_DEVICE_REQUEST;
1027 }
1028 return Status;
1029 }
1030
1031 //-----------------------------------------------------------------------------------------
1032 NTSTATUS
1033 CHubController::HandleSelectConfiguration(
1034 IN OUT PIRP Irp,
1035 PURB Urb)
1036 {
1037 PUSBDEVICE UsbDevice;
1038 PUSBD_INTERFACE_INFORMATION InterfaceInfo;
1039
1040 //
1041 // is the request for the Root Hub
1042 //
1043 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1044 {
1045 //
1046 // FIXME: support setting device to unconfigured state
1047 //
1048 PC_ASSERT(Urb->UrbSelectConfiguration.ConfigurationDescriptor);
1049
1050 //
1051 // set device handle
1052 //
1053 Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&ROOTHUB2_CONFIGURATION_DESCRIPTOR;
1054
1055 //
1056 // copy interface info
1057 //
1058 InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
1059
1060 InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&ROOTHUB2_INTERFACE_DESCRIPTOR;
1061 InterfaceInfo->Class = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceClass;
1062 InterfaceInfo->SubClass = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceSubClass;
1063 InterfaceInfo->Protocol = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceProtocol;
1064 InterfaceInfo->Reserved = 0;
1065
1066 //
1067 // sanity check
1068 //
1069 PC_ASSERT(InterfaceInfo->NumberOfPipes == 1);
1070
1071 //
1072 // copy pipe info
1073 //
1074 InterfaceInfo->Pipes[0].MaximumPacketSize = ROOTHUB2_ENDPOINT_DESCRIPTOR.wMaxPacketSize;
1075 InterfaceInfo->Pipes[0].EndpointAddress = ROOTHUB2_ENDPOINT_DESCRIPTOR.bEndpointAddress;
1076 InterfaceInfo->Pipes[0].Interval = ROOTHUB2_ENDPOINT_DESCRIPTOR.bInterval;
1077 InterfaceInfo->Pipes[0].PipeType = (USBD_PIPE_TYPE)(ROOTHUB2_ENDPOINT_DESCRIPTOR.bmAttributes & USB_ENDPOINT_TYPE_MASK);
1078 InterfaceInfo->Pipes[0].PipeHandle = (PVOID)&ROOTHUB2_ENDPOINT_DESCRIPTOR;
1079
1080 return STATUS_SUCCESS;
1081 }
1082 else
1083 {
1084 //
1085 // check if this is a valid usb device handle
1086 //
1087 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1088 {
1089 DPRINT1("[USBLIB] HandleSelectConfiguration invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1090
1091 //
1092 // invalid device handle
1093 //
1094 return STATUS_DEVICE_NOT_CONNECTED;
1095 }
1096
1097 //
1098 // get device
1099 //
1100 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1101
1102 //
1103 // select configuration
1104 //
1105 return UsbDevice->SelectConfiguration(Urb->UrbSelectConfiguration.ConfigurationDescriptor, &Urb->UrbSelectConfiguration.Interface, &Urb->UrbSelectConfiguration.ConfigurationHandle);
1106 }
1107 }
1108
1109 //-----------------------------------------------------------------------------------------
1110 NTSTATUS
1111 CHubController::HandleSelectInterface(
1112 IN OUT PIRP Irp,
1113 PURB Urb)
1114 {
1115 PUSBDEVICE UsbDevice;
1116
1117 //
1118 // sanity check
1119 //
1120 PC_ASSERT(Urb->UrbSelectInterface.ConfigurationHandle);
1121
1122 //
1123 // is the request for the Root Hub
1124 //
1125 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1126 {
1127 //
1128 // no op for root hub
1129 //
1130 return STATUS_SUCCESS;
1131 }
1132 else
1133 {
1134 //
1135 // check if this is a valid usb device handle
1136 //
1137 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1138 {
1139 DPRINT1("[USBLIB] HandleSelectInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1140
1141 //
1142 // invalid device handle
1143 //
1144 return STATUS_DEVICE_NOT_CONNECTED;
1145 }
1146
1147 //
1148 // get device
1149 //
1150 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1151
1152 //
1153 // select interface
1154 //
1155 return UsbDevice->SelectInterface(Urb->UrbSelectInterface.ConfigurationHandle, &Urb->UrbSelectInterface.Interface);
1156 }
1157 }
1158
1159 //-----------------------------------------------------------------------------------------
1160 NTSTATUS
1161 CHubController::HandleGetStatusFromDevice(
1162 IN OUT PIRP Irp,
1163 PURB Urb)
1164 {
1165 PUSHORT DeviceStatus;
1166 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1167 NTSTATUS Status;
1168 PUSBDEVICE UsbDevice;
1169
1170 //
1171 // sanity checks
1172 //
1173 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
1174 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
1175
1176 //
1177 // get status buffer
1178 //
1179 DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
1180
1181
1182 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1183 {
1184 //
1185 // FIXME need more flags ?
1186 //
1187 *DeviceStatus = USB_PORT_STATUS_CONNECT;
1188 return STATUS_SUCCESS;
1189 }
1190
1191 //
1192 // check if this is a valid usb device handle
1193 //
1194 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1195 {
1196 DPRINT1("[USBLIB] HandleGetStatusFromDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1197
1198 //
1199 // invalid device handle
1200 //
1201 return STATUS_DEVICE_NOT_CONNECTED;
1202 }
1203
1204 //
1205 // get device
1206 //
1207 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1208
1209
1210 //
1211 // generate setup packet
1212 //
1213 CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
1214 CtrlSetup.wValue.LowByte = 0;
1215 CtrlSetup.wValue.HiByte = 0;
1216 CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1217 CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
1218 CtrlSetup.bmRequestType.B = 0x80;
1219
1220
1221 if (Urb->UrbHeader.Function == URB_FUNCTION_GET_STATUS_FROM_INTERFACE)
1222 {
1223 //
1224 // add interface type
1225 //
1226 CtrlSetup.bmRequestType.B |= 0x01;
1227 }
1228 else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_STATUS_FROM_ENDPOINT)
1229 {
1230 //
1231 // add interface type
1232 //
1233 CtrlSetup.bmRequestType.B |= 0x02;
1234 }
1235
1236 //
1237 // submit setup packet
1238 //
1239 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1240 ASSERT(Status == STATUS_SUCCESS);
1241 DPRINT1("[USBLIB] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
1242
1243 //
1244 // done
1245 //
1246 return Status;
1247 }
1248
1249 //-----------------------------------------------------------------------------------------
1250 NTSTATUS
1251 CHubController::HandleClassDevice(
1252 IN OUT PIRP Irp,
1253 IN OUT PURB Urb)
1254 {
1255 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1256 PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
1257 ULONG PortCount, Dummy2;
1258 USHORT Dummy1;
1259 PUSBDEVICE UsbDevice;
1260 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1261
1262 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
1263
1264 //
1265 // check class request type
1266 //
1267 switch(Urb->UrbControlVendorClassRequest.Request)
1268 {
1269 case USB_REQUEST_GET_STATUS:
1270 {
1271 //
1272 // check if this is a valid usb device handle
1273 //
1274 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1275 {
1276 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1277
1278 //
1279 // invalid device handle
1280 //
1281 return STATUS_DEVICE_NOT_CONNECTED;
1282 }
1283
1284 //
1285 // get device
1286 //
1287 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1288
1289
1290 //
1291 // generate setup packet
1292 //
1293 CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
1294 CtrlSetup.wValue.LowByte = Urb->UrbControlVendorClassRequest.Index;
1295 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1296 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1297 CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
1298 CtrlSetup.bmRequestType.B = 0xA0;
1299
1300 //
1301 // submit setup packet
1302 //
1303 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1304 ASSERT(Status == STATUS_SUCCESS);
1305 break;
1306 }
1307 case USB_REQUEST_GET_DESCRIPTOR:
1308 {
1309 switch (Urb->UrbControlVendorClassRequest.Value >> 8)
1310 {
1311 case USB_DEVICE_CLASS_RESERVED: // FALL THROUGH
1312 case USB_DEVICE_CLASS_HUB:
1313 {
1314 //
1315 // sanity checks
1316 //
1317 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1318 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR));
1319
1320 //
1321 // get hub descriptor
1322 //
1323 UsbHubDescriptor = (PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer;
1324
1325 //
1326 // one hub is handled
1327 //
1328 UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
1329 Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR);
1330
1331 //
1332 // type should 0x29 according to msdn
1333 //
1334 UsbHubDescriptor->bDescriptorType = 0x29;
1335
1336 //
1337 // get port count
1338 //
1339 Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &PortCount, &Dummy2);
1340 PC_ASSERT(Status == STATUS_SUCCESS);
1341
1342 //
1343 // FIXME: retrieve values
1344 //
1345 UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount;
1346 UsbHubDescriptor->wHubCharacteristics = 0x00;
1347 UsbHubDescriptor->bPowerOnToPowerGood = 0x01;
1348 UsbHubDescriptor->bHubControlCurrent = 0x00;
1349
1350 //
1351 // done
1352 //
1353 Status = STATUS_SUCCESS;
1354 break;
1355 }
1356 default:
1357 DPRINT1("[USBLIB] HandleClassDevice Class %x not implemented\n", Urb->UrbControlVendorClassRequest.Value >> 8);
1358 break;
1359 }
1360 break;
1361 }
1362 default:
1363 DPRINT1("[USBLIB] HandleClassDevice Type %x not implemented\n", Urb->UrbControlVendorClassRequest.Request);
1364 }
1365
1366 return Status;
1367 }
1368
1369 //-----------------------------------------------------------------------------------------
1370 NTSTATUS
1371 CHubController::HandleGetDescriptorFromInterface(
1372 IN OUT PIRP Irp,
1373 IN OUT PURB Urb)
1374 {
1375 PUSBDEVICE UsbDevice;
1376 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1377 NTSTATUS Status;
1378
1379 //
1380 // sanity check
1381 //
1382 ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
1383 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1384
1385 //
1386 // check if this is a valid usb device handle
1387 //
1388 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1389 {
1390 DPRINT1("[USBLIB] HandleGetDescriptorFromInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1391
1392 //
1393 // invalid device handle
1394 //
1395 return STATUS_DEVICE_NOT_CONNECTED;
1396 }
1397
1398 //
1399 // get device
1400 //
1401 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1402
1403 //
1404 // generate setup packet
1405 //
1406 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1407 CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1408 CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1409 CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1410 CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1411 CtrlSetup.bmRequestType.B = 0x81;
1412
1413 //
1414 // submit setup packet
1415 //
1416 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1417 ASSERT(Status == STATUS_SUCCESS);
1418
1419 //
1420 // done
1421 //
1422 return Status;
1423 }
1424
1425 //-----------------------------------------------------------------------------------------
1426 NTSTATUS
1427 CHubController::HandleGetDescriptor(
1428 IN OUT PIRP Irp,
1429 IN OUT PURB Urb)
1430 {
1431 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1432 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
1433 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1434 PUCHAR Buffer;
1435 PUSBDEVICE UsbDevice;
1436 ULONG Length;
1437
1438 DPRINT("[USBLIB] HandleGetDescriptor\n");
1439
1440 //
1441 // check descriptor type
1442 //
1443 switch(Urb->UrbControlDescriptorRequest.DescriptorType)
1444 {
1445 case USB_DEVICE_DESCRIPTOR_TYPE:
1446 {
1447 //
1448 // sanity check
1449 //
1450 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1451 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1452
1453 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1454 {
1455 //
1456 // copy root hub device descriptor
1457 //
1458 RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
1459 Status = STATUS_SUCCESS;
1460 }
1461 else
1462 {
1463 //
1464 // check if this is a valid usb device handle
1465 //
1466 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1467 {
1468 DPRINT1("[USBLIB] HandleGetDescriptor invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1469
1470 //
1471 // invalid device handle
1472 //
1473 return STATUS_DEVICE_NOT_CONNECTED;
1474 }
1475
1476 //
1477 // get device
1478 //
1479 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1480
1481 //
1482 // retrieve device descriptor from device
1483 //
1484 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
1485 Status = STATUS_SUCCESS;
1486 }
1487 break;
1488 }
1489 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
1490 {
1491 //
1492 // sanity checks
1493 //
1494 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1495 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
1496
1497 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1498 {
1499 //
1500 // request is for the root bus controller
1501 //
1502 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR));
1503
1504 //
1505 // get configuration descriptor, very retarded!
1506 //
1507 ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer;
1508
1509 //
1510 // check if buffer can hold interface and endpoint descriptor
1511 //
1512 if (ConfigurationDescriptor->wTotalLength > Urb->UrbControlDescriptorRequest.TransferBufferLength)
1513 {
1514 //
1515 // buffer too small
1516 //
1517 Status = STATUS_SUCCESS;
1518 ASSERT(FALSE);
1519 break;
1520 }
1521
1522 //
1523 // copy interface descriptor template
1524 //
1525 Buffer = (PUCHAR)(ConfigurationDescriptor + 1);
1526 RtlCopyMemory(Buffer, &ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR));
1527
1528 //
1529 // copy end point descriptor template
1530 //
1531 Buffer += sizeof(USB_INTERFACE_DESCRIPTOR);
1532 RtlCopyMemory(Buffer, &ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR));
1533
1534 //
1535 // done
1536 //
1537 Status = STATUS_SUCCESS;
1538
1539 }
1540 else
1541 {
1542 //
1543 // check if this is a valid usb device handle
1544 //
1545 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1546 {
1547 DPRINT1("[USBLIB] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1548
1549 //
1550 // invalid device handle
1551 //
1552 return STATUS_DEVICE_NOT_CONNECTED;
1553 }
1554
1555 //
1556 // get device
1557 //
1558 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1559
1560 if (sizeof(USB_CONFIGURATION_DESCRIPTOR) > Urb->UrbControlDescriptorRequest.TransferBufferLength)
1561 {
1562 //
1563 // buffer too small
1564 //
1565 Urb->UrbControlDescriptorRequest.TransferBufferLength = UsbDevice->GetConfigurationDescriptorsLength();
1566
1567 //
1568 // bail out
1569 //
1570 Status = STATUS_SUCCESS;
1571 break;
1572 }
1573
1574 //
1575 // perform work in IUSBDevice
1576 //
1577 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength, &Length);
1578
1579 //
1580 // store result size
1581 //
1582 Urb->UrbControlDescriptorRequest.TransferBufferLength = Length;
1583 Status = STATUS_SUCCESS;
1584 }
1585 break;
1586 }
1587 case USB_STRING_DESCRIPTOR_TYPE:
1588 {
1589 //
1590 // sanity check
1591 //
1592 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1593 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
1594
1595
1596 //
1597 // check if this is a valid usb device handle
1598 //
1599 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1600 {
1601 DPRINT1("[USBLIB] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1602
1603 //
1604 // invalid device handle
1605 //
1606 return STATUS_DEVICE_NOT_CONNECTED;
1607 }
1608
1609 //
1610 // get device
1611 //
1612 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1613
1614 //
1615 // generate setup packet
1616 //
1617 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1618 CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1619 CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1620 CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1621 CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1622 CtrlSetup.bmRequestType.B = 0x80;
1623
1624 //
1625 // submit setup packet
1626 //
1627 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1628 break;
1629 }
1630 default:
1631 DPRINT1("[USBLIB] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb->UrbControlDescriptorRequest.DescriptorType);
1632 break;
1633 }
1634
1635 //
1636 // done
1637 //
1638 return Status;
1639 }
1640
1641 //-----------------------------------------------------------------------------------------
1642 NTSTATUS
1643 CHubController::HandleClassEndpoint(
1644 IN OUT PIRP Irp,
1645 IN OUT PURB Urb)
1646 {
1647 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1648 NTSTATUS Status;
1649 PUSBDEVICE UsbDevice;
1650
1651 //
1652 // sanity check
1653 //
1654 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1655 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1656 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1657
1658 //
1659 // check if this is a valid usb device handle
1660 //
1661 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1662 {
1663 DPRINT1("[USBLIB] HandleClassEndpoint invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1664
1665 //
1666 // invalid device handle
1667 //
1668 return STATUS_DEVICE_NOT_CONNECTED;
1669 }
1670
1671 //
1672 // get device
1673 //
1674 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1675
1676
1677 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1678 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
1679 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
1680 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
1681 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1682 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
1683 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1684 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
1685 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
1686
1687 //
1688 // initialize setup packet
1689 //
1690 CtrlSetup.bmRequestType.B = 0x22; //FIXME: Const.
1691 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1692 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1693 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1694 CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
1695
1696 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1697 {
1698 //
1699 // data direction is device to host
1700 //
1701 CtrlSetup.bmRequestType.B |= 0x80;
1702 }
1703
1704
1705 //
1706 // issue request
1707 //
1708 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1709
1710 //
1711 // assert on failure
1712 //
1713 PC_ASSERT(NT_SUCCESS(Status));
1714
1715
1716 //
1717 // done
1718 //
1719 return Status;
1720 }
1721
1722 NTSTATUS
1723 CHubController::HandleSyncResetAndClearStall(
1724 IN OUT PIRP Irp,
1725 IN OUT PURB Urb)
1726 {
1727 NTSTATUS Status = STATUS_SUCCESS;
1728 PUSB_ENDPOINT EndpointDescriptor;
1729 ULONG Type;
1730
1731 //
1732 // sanity check
1733 //
1734 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1735 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1736 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1737
1738 //
1739 // check if this is a valid usb device handle
1740 //
1741 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1742 {
1743 DPRINT1("[USBLIB] HandleSyncResetAndClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1744
1745 //
1746 // invalid device handle
1747 //
1748 return STATUS_DEVICE_NOT_CONNECTED;
1749 }
1750
1751 //
1752 // abort pipe
1753 //
1754 Status = HandleAbortPipe(Irp, Urb);
1755 if (!NT_SUCCESS(Status))
1756 {
1757 //
1758 // failed
1759 //
1760 DPRINT1("[USBLIB] failed to reset pipe %x\n", Status);
1761 }
1762
1763
1764 //
1765 // get endpoint descriptor
1766 //
1767 EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbPipeRequest.PipeHandle;
1768
1769 //
1770 // get type
1771 //
1772 Type = (EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK);
1773 if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
1774 {
1775 //
1776 // clear stall
1777 //
1778 Status = HandleClearStall(Irp, Urb);
1779 }
1780 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
1781
1782 //
1783 // reset data toggle
1784 //
1785 ASSERT(NT_SUCCESS(Status));
1786 EndpointDescriptor->DataToggle = 0x0;
1787
1788 //
1789 // done
1790 //
1791 return Status;
1792 }
1793
1794 NTSTATUS
1795 CHubController::HandleAbortPipe(
1796 IN OUT PIRP Irp,
1797 IN OUT PURB Urb)
1798 {
1799 NTSTATUS Status;
1800 PUSBDEVICE UsbDevice;
1801 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1802
1803 //
1804 // sanity check
1805 //
1806 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1807 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1808 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1809
1810 //
1811 // check if this is a valid usb device handle
1812 //
1813 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1814 {
1815 DPRINT1("[USBLIB] HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1816
1817 //
1818 // invalid device handle
1819 //
1820 return STATUS_DEVICE_NOT_CONNECTED;
1821 }
1822
1823 //
1824 // get endpoint descriptor
1825 //
1826 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
1827
1828 //
1829 // get device
1830 //
1831 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1832
1833
1834 //
1835 // issue request
1836 //
1837 Status = UsbDevice->AbortPipe(EndpointDescriptor);
1838 DPRINT1("[USBLIB] URB_FUNCTION_ABORT_PIPE Status %x\n", Status);
1839
1840 //
1841 // done
1842 //
1843 return Status;
1844 }
1845
1846
1847 //-----------------------------------------------------------------------------------------
1848 NTSTATUS
1849 CHubController::HandleClearStall(
1850 IN OUT PIRP Irp,
1851 IN OUT PURB Urb)
1852 {
1853 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1854 NTSTATUS Status;
1855 PUSBDEVICE UsbDevice;
1856 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1857
1858
1859 //
1860 // sanity check
1861 //
1862 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1863 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1864 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1865
1866 //
1867 // check if this is a valid usb device handle
1868 //
1869 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1870 {
1871 DPRINT1("[USBLIB] HandleClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1872
1873 //
1874 // invalid device handle
1875 //
1876 return STATUS_DEVICE_NOT_CONNECTED;
1877 }
1878
1879 //
1880 // get endpoint descriptor
1881 //
1882 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
1883
1884 //
1885 // get device
1886 //
1887 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1888 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_CLEAR_STALL\n");
1889
1890 //
1891 // initialize setup packet
1892 //
1893 CtrlSetup.bmRequestType.B = 0x02;
1894 CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE;
1895 CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL;
1896 CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress;
1897 CtrlSetup.wLength = 0;
1898 CtrlSetup.wValue.W = 0;
1899
1900 //
1901 // issue request
1902 //
1903 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0);
1904
1905 DPRINT1("[USBLIB] URB_FUNCTION_CLEAR_STALL Status %x\n", Status);
1906
1907 //
1908 // done
1909 //
1910 return Status;
1911 }
1912
1913
1914 //-----------------------------------------------------------------------------------------
1915 NTSTATUS
1916 CHubController::HandleClassInterface(
1917 IN OUT PIRP Irp,
1918 IN OUT PURB Urb)
1919 {
1920 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1921 NTSTATUS Status;
1922 PUSBDEVICE UsbDevice;
1923
1924 //
1925 // sanity check
1926 //
1927 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1928 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1929 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1930
1931 //
1932 // check if this is a valid usb device handle
1933 //
1934 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1935 {
1936 DPRINT1("[USBLIB] HandleClassInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1937
1938 //
1939 // invalid device handle
1940 //
1941 return STATUS_DEVICE_NOT_CONNECTED;
1942 }
1943
1944 //
1945 // get device
1946 //
1947 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1948
1949
1950 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1951 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
1952 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
1953 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
1954 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1955 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
1956 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1957 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
1958 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
1959
1960 //
1961 // initialize setup packet
1962 //
1963 CtrlSetup.bmRequestType.B = 0x21;
1964 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1965 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1966 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1967 CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
1968
1969 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1970 {
1971 //
1972 // data direction is device to host
1973 //
1974 CtrlSetup.bmRequestType.B |= 0x80;
1975 }
1976
1977 //
1978 // issue request
1979 //
1980 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1981
1982 //
1983 // assert on failure
1984 //
1985 if (!NT_SUCCESS(Status))
1986 {
1987 //
1988 // display error
1989 //
1990 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status);
1991 }
1992
1993 //
1994 // done
1995 //
1996 return Status;
1997 }
1998
1999 //-----------------------------------------------------------------------------------------
2000 NTSTATUS
2001 CHubController::HandleDeviceControl(
2002 IN PDEVICE_OBJECT DeviceObject,
2003 IN OUT PIRP Irp)
2004 {
2005 PIO_STACK_LOCATION IoStack;
2006 PCOMMON_DEVICE_EXTENSION DeviceExtension;
2007 PURB Urb;
2008 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
2009
2010 //
2011 // get current stack location
2012 //
2013 IoStack = IoGetCurrentIrpStackLocation(Irp);
2014
2015 //
2016 // get device extension
2017 //
2018 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
2019
2020 //
2021 // determine which request should be performed
2022 //
2023 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
2024 {
2025 case IOCTL_INTERNAL_USB_SUBMIT_URB:
2026 {
2027 //
2028 // get urb
2029 //
2030 Urb = (PURB)IoStack->Parameters.Others.Argument1;
2031 PC_ASSERT(Urb);
2032
2033 switch (Urb->UrbHeader.Function)
2034 {
2035 case URB_FUNCTION_SYNC_RESET_PIPE:
2036 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
2037 Status = HandleSyncResetAndClearStall(Irp, Urb);
2038 break;
2039 case URB_FUNCTION_ABORT_PIPE:
2040 Status = HandleAbortPipe(Irp, Urb);
2041 break;
2042 case URB_FUNCTION_SYNC_CLEAR_STALL:
2043 Status = HandleClearStall(Irp, Urb);
2044 break;
2045 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
2046 Status = HandleGetDescriptorFromInterface(Irp, Urb);
2047 break;
2048 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
2049 Status = HandleGetDescriptor(Irp, Urb);
2050 break;
2051 case URB_FUNCTION_CLASS_DEVICE:
2052 Status = HandleClassDevice(Irp, Urb);
2053 break;
2054 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
2055 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
2056 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
2057 Status = HandleGetStatusFromDevice(Irp, Urb);
2058 break;
2059 case URB_FUNCTION_SELECT_CONFIGURATION:
2060 Status = HandleSelectConfiguration(Irp, Urb);
2061 break;
2062 case URB_FUNCTION_SELECT_INTERFACE:
2063 Status = HandleSelectInterface(Irp, Urb);
2064 break;
2065 case URB_FUNCTION_CLASS_OTHER:
2066 Status = HandleClassOther(Irp, Urb);
2067 break;
2068 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
2069 Status = HandleBulkOrInterruptTransfer(Irp, Urb);
2070 break;
2071 case URB_FUNCTION_ISOCH_TRANSFER:
2072 Status = HandleIsochronousTransfer(Irp, Urb);
2073 break;
2074 case URB_FUNCTION_CLASS_INTERFACE:
2075 Status = HandleClassInterface(Irp, Urb);
2076 break;
2077 case URB_FUNCTION_CLASS_ENDPOINT:
2078 Status = HandleClassEndpoint(Irp, Urb);
2079 break;
2080 default:
2081 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
2082 break;
2083 }
2084 //
2085 // request completed
2086 //
2087 break;
2088 }
2089 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
2090 {
2091 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
2092
2093 if (IoStack->Parameters.Others.Argument1)
2094 {
2095 //
2096 // store object as device handle
2097 //
2098 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
2099 Status = STATUS_SUCCESS;
2100 }
2101 else
2102 {
2103 //
2104 // mis-behaving hub driver
2105 //
2106 Status = STATUS_INVALID_DEVICE_REQUEST;
2107 }
2108
2109 //
2110 // request completed
2111 //
2112 break;
2113 }
2114 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
2115 {
2116 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
2117
2118 //
2119 // this is the first request send, it delivers the PDO to the caller
2120 //
2121 if (IoStack->Parameters.Others.Argument1)
2122 {
2123 //
2124 // store root hub pdo object
2125 //
2126 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
2127 }
2128
2129 if (IoStack->Parameters.Others.Argument2)
2130 {
2131 //
2132 // documentation claims to deliver the hcd controller object, although it is wrong
2133 //
2134 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
2135 }
2136
2137 //
2138 // request completed
2139 //
2140 Status = STATUS_SUCCESS;
2141 break;
2142 }
2143 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
2144 {
2145 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
2146
2147 //
2148 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2149 // requests this ioctl to deliver the number of presents.
2150
2151 if (IoStack->Parameters.Others.Argument1)
2152 {
2153 //
2154 // FIXME / verify: there is only one hub
2155 //
2156 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
2157 }
2158
2159 //
2160 // request completed
2161 //
2162 Status = STATUS_SUCCESS;
2163 Irp->IoStatus.Information = sizeof(ULONG);
2164 break;
2165 }
2166 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
2167 {
2168 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
2169 Status = STATUS_SUCCESS;
2170 break;
2171 }
2172 default:
2173 {
2174 DPRINT1("[USBLIB] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
2175 IoStack->Parameters.DeviceIoControl.IoControlCode,
2176 IoStack->Parameters.DeviceIoControl.InputBufferLength,
2177 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
2178 break;
2179 }
2180 }
2181 if (Status != STATUS_PENDING)
2182 {
2183 Irp->IoStatus.Status = Status;
2184 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2185 }
2186
2187 return Status;
2188 }
2189
2190 //-----------------------------------------------------------------------------------------
2191 PUSBHARDWAREDEVICE
2192 CHubController::GetUsbHardware()
2193 {
2194 return m_Hardware;
2195 }
2196
2197 //-----------------------------------------------------------------------------------------
2198 ULONG
2199 CHubController::AcquireDeviceAddress()
2200 {
2201 KIRQL OldLevel;
2202 ULONG DeviceAddress;
2203
2204 //
2205 // acquire device lock
2206 //
2207 KeAcquireSpinLock(&m_Lock, &OldLevel);
2208
2209 //
2210 // find address
2211 //
2212 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
2213 if (DeviceAddress != MAXULONG)
2214 {
2215 //
2216 // reserve address
2217 //
2218 RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2219
2220 //
2221 // device addresses start from 0x1 - 0xFF
2222 //
2223 DeviceAddress++;
2224 }
2225
2226 //
2227 // release spin lock
2228 //
2229 KeReleaseSpinLock(&m_Lock, OldLevel);
2230
2231 //
2232 // return device address
2233 //
2234 return DeviceAddress;
2235 }
2236 //-----------------------------------------------------------------------------------------
2237 VOID
2238 CHubController::ReleaseDeviceAddress(
2239 ULONG DeviceAddress)
2240 {
2241 KIRQL OldLevel;
2242
2243 //
2244 // acquire device lock
2245 //
2246 KeAcquireSpinLock(&m_Lock, &OldLevel);
2247
2248 //
2249 // sanity check
2250 //
2251 PC_ASSERT(DeviceAddress != 0);
2252
2253 //
2254 // convert back to bit number
2255 //
2256 DeviceAddress--;
2257
2258 //
2259 // clear bit
2260 //
2261 RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2262
2263 //
2264 // release lock
2265 //
2266 KeReleaseSpinLock(&m_Lock, OldLevel);
2267 }
2268 //-----------------------------------------------------------------------------------------
2269 NTSTATUS
2270 CHubController::RemoveUsbDevice(
2271 PUSBDEVICE UsbDevice)
2272 {
2273 PUSBDEVICE_ENTRY DeviceEntry;
2274 PLIST_ENTRY Entry;
2275 NTSTATUS Status = STATUS_UNSUCCESSFUL;
2276 KIRQL OldLevel;
2277
2278 //
2279 // acquire lock
2280 //
2281 KeAcquireSpinLock(&m_Lock, &OldLevel);
2282
2283 //
2284 // point to first entry
2285 //
2286 Entry = m_UsbDeviceList.Flink;
2287
2288 //
2289 // find matching entry
2290 //
2291 while(Entry != &m_UsbDeviceList)
2292 {
2293 //
2294 // get entry
2295 //
2296 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2297
2298 //
2299 // is it current entry
2300 //
2301 if (DeviceEntry->Device == UsbDevice)
2302 {
2303 //
2304 // remove entry
2305 //
2306 RemoveEntryList(Entry);
2307
2308 //
2309 // free entry
2310 //
2311 ExFreePoolWithTag(DeviceEntry, TAG_USBLIB);
2312
2313 //
2314 // done
2315 //
2316 Status = STATUS_SUCCESS;
2317 break;
2318 }
2319
2320 //
2321 // goto next device
2322 //
2323 Entry = Entry->Flink;
2324 }
2325
2326 //
2327 // release lock
2328 //
2329 KeReleaseSpinLock(&m_Lock, OldLevel);
2330
2331 //
2332 // return result
2333 //
2334 return Status;
2335 }
2336 //-----------------------------------------------------------------------------------------
2337 BOOLEAN
2338 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
2339 {
2340 PUSBDEVICE_ENTRY DeviceEntry;
2341 PLIST_ENTRY Entry;
2342 KIRQL OldLevel;
2343 BOOLEAN Result = FALSE;
2344
2345 //
2346 // acquire lock
2347 //
2348 KeAcquireSpinLock(&m_Lock, &OldLevel);
2349
2350 //
2351 // point to first entry
2352 //
2353 Entry = m_UsbDeviceList.Flink;
2354
2355 //
2356 // find matching entry
2357 //
2358 while(Entry != &m_UsbDeviceList)
2359 {
2360 //
2361 // get entry
2362 //
2363 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2364
2365 //
2366 // is it current entry
2367 //
2368 if (DeviceEntry->Device == UsbDevice)
2369 {
2370 //
2371 // device is valid
2372 //
2373 Result = TRUE;
2374 break;
2375 }
2376
2377 //
2378 // goto next device
2379 //
2380 Entry = Entry->Flink;
2381 }
2382
2383 //
2384 // release lock
2385 //
2386 KeReleaseSpinLock(&m_Lock, OldLevel);
2387
2388 //
2389 // return result
2390 //
2391 return Result;
2392
2393 }
2394
2395 //-----------------------------------------------------------------------------------------
2396 NTSTATUS
2397 CHubController::AddUsbDevice(
2398 PUSBDEVICE UsbDevice)
2399 {
2400 PUSBDEVICE_ENTRY DeviceEntry;
2401 KIRQL OldLevel;
2402
2403 //
2404 // allocate device entry
2405 //
2406 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBLIB);
2407 if (!DeviceEntry)
2408 {
2409 //
2410 // no memory
2411 //
2412 return STATUS_INSUFFICIENT_RESOURCES;
2413 }
2414
2415 //
2416 // initialize entry
2417 //
2418 DeviceEntry->Device = UsbDevice;
2419
2420 //
2421 // acquire lock
2422 //
2423 KeAcquireSpinLock(&m_Lock, &OldLevel);
2424
2425 //
2426 // insert entry
2427 //
2428 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
2429
2430 //
2431 // release spin lock
2432 //
2433 KeReleaseSpinLock(&m_Lock, OldLevel);
2434
2435 //
2436 // done
2437 //
2438 return STATUS_SUCCESS;
2439 }
2440
2441 //-----------------------------------------------------------------------------------------
2442 VOID
2443 CHubController::SetNotification(
2444 PVOID CallbackContext,
2445 PRH_INIT_CALLBACK CallbackRoutine)
2446 {
2447 KIRQL OldLevel;
2448
2449 //
2450 // acquire hub controller lock
2451 //
2452 KeAcquireSpinLock(&m_Lock, &OldLevel);
2453
2454 //
2455 // now set the callback routine and context of the hub
2456 //
2457 m_HubCallbackContext = CallbackContext;
2458 m_HubCallbackRoutine = CallbackRoutine;
2459
2460 //
2461 // release hub controller lock
2462 //
2463 KeReleaseSpinLock(&m_Lock, OldLevel);
2464 }
2465
2466 //=================================================================================================
2467 //
2468 // Generic Interface functions
2469 //
2470 VOID
2471 USB_BUSIFFN
2472 USBI_InterfaceReference(
2473 PVOID BusContext)
2474 {
2475 CHubController * Controller = (CHubController*)BusContext;
2476
2477 DPRINT1("USBH_InterfaceReference\n");
2478
2479 //
2480 // add reference
2481 //
2482 Controller->AddRef();
2483 }
2484
2485 VOID
2486 USB_BUSIFFN
2487 USBI_InterfaceDereference(
2488 PVOID BusContext)
2489 {
2490 CHubController * Controller = (CHubController*)BusContext;
2491
2492 DPRINT1("USBH_InterfaceDereference\n");
2493
2494 //
2495 // release
2496 //
2497 Controller->Release();
2498 }
2499 //=================================================================================================
2500 //
2501 // USB Hub Interface functions
2502 //
2503 NTSTATUS
2504 USB_BUSIFFN
2505 USBHI_CreateUsbDevice(
2506 PVOID BusContext,
2507 PUSB_DEVICE_HANDLE *NewDevice,
2508 PUSB_DEVICE_HANDLE HubDeviceHandle,
2509 USHORT PortStatus,
2510 USHORT PortNumber)
2511 {
2512 PUSBDEVICE NewUsbDevice;
2513 CHubController * Controller;
2514 NTSTATUS Status;
2515
2516 DPRINT1("USBHI_CreateUsbDevice\n");
2517
2518 //
2519 // first get hub controller
2520 //
2521 Controller = (CHubController *)BusContext;
2522
2523 //
2524 // sanity check
2525 //
2526 PC_ASSERT(Controller);
2527 PC_ASSERT(BusContext == HubDeviceHandle);
2528
2529 //
2530 // now allocate usb device
2531 //
2532 Status = CreateUSBDevice(&NewUsbDevice);
2533
2534 //
2535 // check for success
2536 //
2537 if (!NT_SUCCESS(Status))
2538 {
2539 //
2540 // release controller
2541 //
2542 Controller->Release();
2543 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
2544 return Status;
2545 }
2546
2547 //
2548 // now initialize device
2549 //
2550 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(), HubDeviceHandle, PortNumber, PortStatus);
2551
2552 //
2553 // check for success
2554 //
2555 if (!NT_SUCCESS(Status))
2556 {
2557 //
2558 // release usb device
2559 //
2560 NewUsbDevice->Release();
2561 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
2562 return Status;
2563 }
2564
2565 //
2566 // insert into list
2567 //
2568 Status = Controller->AddUsbDevice(NewUsbDevice);
2569 //
2570 // check for success
2571 //
2572 if (!NT_SUCCESS(Status))
2573 {
2574 //
2575 // release usb device
2576 //
2577 NewUsbDevice->Release();
2578
2579 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
2580 return Status;
2581 }
2582
2583 //
2584 // store the handle
2585 //
2586 *NewDevice = NewUsbDevice;
2587
2588 //
2589 // done
2590 //
2591 return STATUS_SUCCESS;
2592 }
2593
2594 NTSTATUS
2595 USB_BUSIFFN
2596 USBHI_InitializeUsbDevice(
2597 PVOID BusContext,
2598 PUSB_DEVICE_HANDLE DeviceHandle)
2599 {
2600 PUSBDEVICE UsbDevice;
2601 CHubController * Controller;
2602 ULONG DeviceAddress;
2603 NTSTATUS Status;
2604 ULONG Index = 0;
2605
2606 DPRINT1("USBHI_InitializeUsbDevice\n");
2607
2608 //
2609 // first get controller
2610 //
2611 Controller = (CHubController *)BusContext;
2612 PC_ASSERT(Controller);
2613
2614 //
2615 // get device object
2616 //
2617 UsbDevice = (PUSBDEVICE)DeviceHandle;
2618 PC_ASSERT(UsbDevice);
2619
2620 //
2621 // validate device handle
2622 //
2623 if (!Controller->ValidateUsbDevice(UsbDevice))
2624 {
2625 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
2626
2627 //
2628 // invalid device handle
2629 //
2630 return STATUS_DEVICE_NOT_CONNECTED;
2631 }
2632
2633 //
2634 // now reserve an address
2635 //
2636 DeviceAddress = Controller->AcquireDeviceAddress();
2637
2638 //
2639 // is the device address valid
2640 //
2641 if (DeviceAddress == MAXULONG)
2642 {
2643 //
2644 // failed to get an device address from the device address pool
2645 //
2646 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2647 return STATUS_DEVICE_DATA_ERROR;
2648 }
2649
2650 do
2651 {
2652 //
2653 // now set the device address
2654 //
2655 Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
2656
2657 if (NT_SUCCESS(Status))
2658 break;
2659
2660 }while(Index++ < 3 );
2661
2662 //
2663 // check for failure
2664 //
2665 if (!NT_SUCCESS(Status))
2666 {
2667 //
2668 // failed to set device address
2669 //
2670 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
2671
2672 //
2673 // release address
2674 //
2675 Controller->ReleaseDeviceAddress(DeviceAddress);
2676
2677 //
2678 // return error
2679 //
2680 return STATUS_DEVICE_DATA_ERROR;
2681 }
2682
2683 //
2684 // done
2685 //
2686 return STATUS_SUCCESS;
2687 }
2688
2689 NTSTATUS
2690 USB_BUSIFFN
2691 USBHI_GetUsbDescriptors(
2692 PVOID BusContext,
2693 PUSB_DEVICE_HANDLE DeviceHandle,
2694 PUCHAR DeviceDescriptorBuffer,
2695 PULONG DeviceDescriptorBufferLength,
2696 PUCHAR ConfigDescriptorBuffer,
2697 PULONG ConfigDescriptorBufferLength)
2698 {
2699 PUSBDEVICE UsbDevice;
2700 CHubController * Controller;
2701
2702 DPRINT1("USBHI_GetUsbDescriptors\n");
2703
2704 //
2705 // sanity check
2706 //
2707 PC_ASSERT(DeviceDescriptorBuffer);
2708 PC_ASSERT(DeviceDescriptorBufferLength);
2709 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
2710 PC_ASSERT(ConfigDescriptorBufferLength);
2711 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
2712
2713 //
2714 // first get controller
2715 //
2716 Controller = (CHubController *)BusContext;
2717 PC_ASSERT(Controller);
2718
2719
2720 //
2721 // get device object
2722 //
2723 UsbDevice = (PUSBDEVICE)DeviceHandle;
2724 PC_ASSERT(UsbDevice);
2725
2726 //
2727 // validate device handle
2728 //
2729 if (!Controller->ValidateUsbDevice(UsbDevice))
2730 {
2731 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
2732
2733 //
2734 // invalid device handle
2735 //
2736 return STATUS_DEVICE_NOT_CONNECTED;
2737 }
2738
2739 //
2740 // get device descriptor
2741 //
2742 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
2743
2744 //
2745 // store result length
2746 //
2747 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
2748
2749 //
2750 // get configuration descriptor
2751 //
2752 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
2753
2754 //
2755 // complete the request
2756 //
2757 return STATUS_SUCCESS;
2758 }
2759
2760 NTSTATUS
2761 USB_BUSIFFN
2762 USBHI_RemoveUsbDevice(
2763 PVOID BusContext,
2764 PUSB_DEVICE_HANDLE DeviceHandle,
2765 ULONG Flags)
2766 {
2767 PUSBDEVICE UsbDevice;
2768 CHubController * Controller;
2769 NTSTATUS Status;
2770
2771 DPRINT1("USBHI_RemoveUsbDevice\n");
2772
2773 //
2774 // first get controller
2775 //
2776 Controller = (CHubController *)BusContext;
2777 PC_ASSERT(Controller);
2778
2779 //
2780 // get device object
2781 //
2782 UsbDevice = (PUSBDEVICE)DeviceHandle;
2783 PC_ASSERT(UsbDevice);
2784
2785 //
2786 // validate device handle
2787 //
2788 if (!Controller->ValidateUsbDevice(UsbDevice))
2789 {
2790 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
2791
2792 //
2793 // invalid device handle
2794 //
2795 return STATUS_DEVICE_NOT_CONNECTED;
2796 }
2797
2798 //
2799 // check if there were flags passed
2800 //
2801 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
2802 {
2803 //
2804 // ignore flags for now
2805 //
2806 return STATUS_SUCCESS;
2807 }
2808
2809 //
2810 // remove device
2811 //
2812 Status = Controller->RemoveUsbDevice(UsbDevice);
2813 if (!NT_SUCCESS(Status))
2814 {
2815 //
2816 // invalid device handle
2817 //
2818 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
2819 PC_ASSERT(0);
2820 return STATUS_DEVICE_NOT_CONNECTED;
2821 }
2822
2823 //
2824 // release usb device
2825 //
2826 UsbDevice->Release();
2827
2828 //
2829 // done
2830 //
2831 return STATUS_SUCCESS;
2832 }
2833
2834 NTSTATUS
2835 USB_BUSIFFN
2836 USBHI_RestoreUsbDevice(
2837 PVOID BusContext,
2838 PUSB_DEVICE_HANDLE OldDeviceHandle,
2839 PUSB_DEVICE_HANDLE NewDeviceHandle)
2840 {
2841 PUSBDEVICE OldUsbDevice, NewUsbDevice;
2842 CHubController * Controller;
2843
2844 DPRINT1("USBHI_RestoreUsbDevice\n");
2845
2846 //
2847 // first get controller
2848 //
2849 Controller = (CHubController *)BusContext;
2850 PC_ASSERT(Controller);
2851
2852 //
2853 // get device object
2854 //
2855 OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
2856 NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
2857 PC_ASSERT(OldUsbDevice);
2858 PC_ASSERT(NewDeviceHandle);
2859
2860 //
2861 // validate device handle
2862 //
2863 PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
2864 PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
2865
2866 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
2867 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
2868
2869 //
2870 // remove old device handle
2871 //
2872 USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
2873
2874 return STATUS_SUCCESS;
2875 }
2876
2877 NTSTATUS
2878 USB_BUSIFFN
2879 USBHI_QueryDeviceInformation(
2880 PVOID BusContext,
2881 PUSB_DEVICE_HANDLE DeviceHandle,
2882 PVOID DeviceInformationBuffer,
2883 ULONG DeviceInformationBufferLength,
2884 PULONG LengthReturned)
2885 {
2886 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
2887 PUSBDEVICE UsbDevice;
2888 CHubController * Controller;
2889
2890 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
2891
2892 //
2893 // sanity check
2894 //
2895 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
2896 PC_ASSERT(DeviceInformationBuffer);
2897 PC_ASSERT(LengthReturned);
2898
2899 //
2900 // get controller object
2901 //
2902 Controller = (CHubController*)BusContext;
2903 PC_ASSERT(Controller);
2904
2905 //
2906 // get device object
2907 //
2908 UsbDevice = (PUSBDEVICE)DeviceHandle;
2909 PC_ASSERT(UsbDevice);
2910
2911 if (BusContext != DeviceHandle)
2912 {
2913 //
2914 // validate device handle
2915 //
2916 if (!Controller->ValidateUsbDevice(UsbDevice))
2917 {
2918 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
2919
2920 //
2921 // invalid device handle
2922 //
2923 return STATUS_DEVICE_NOT_CONNECTED;
2924 }
2925
2926 //
2927 // access information buffer
2928 //
2929 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2930
2931 //
2932 // initialize with default values
2933 //
2934 DeviceInfo->InformationLevel = 0;
2935 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2936 DeviceInfo->PortNumber = UsbDevice->GetPort();
2937 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
2938 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
2939 DeviceInfo->HubAddress = 0; //FIXME
2940 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
2941 DeviceInfo->DeviceType = UsbDevice->GetType();
2942 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2943
2944 //
2945 // get device descriptor
2946 //
2947 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
2948
2949 //
2950 // FIXME return pipe information
2951 //
2952
2953 //
2954 // store result length
2955 //
2956 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
2957
2958 return STATUS_SUCCESS;
2959 }
2960
2961 //
2962 // access information buffer
2963 //
2964 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2965
2966 //
2967 // initialize with default values
2968 //
2969 DeviceInfo->InformationLevel = 0;
2970 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2971 DeviceInfo->PortNumber = 0;
2972 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
2973 DeviceInfo->DeviceAddress = 0;
2974 DeviceInfo->HubAddress = 0; //FIXME
2975 DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
2976 DeviceInfo->DeviceType = Usb20Device; //FIXME
2977 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2978
2979 //
2980 // get device descriptor
2981 //
2982 RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
2983
2984 //
2985 // FIXME return pipe information
2986 //
2987
2988 //
2989 // store result length
2990 //
2991 #ifdef _MSC_VER
2992 *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
2993 #else
2994 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
2995 #endif
2996 //
2997 // done
2998 //
2999 return STATUS_SUCCESS;
3000 }
3001
3002 NTSTATUS
3003 USB_BUSIFFN
3004 USBHI_GetControllerInformation(
3005 PVOID BusContext,
3006 PVOID ControllerInformationBuffer,
3007 ULONG ControllerInformationBufferLength,
3008 PULONG LengthReturned)
3009 {
3010 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
3011
3012 DPRINT1("USBHI_GetControllerInformation\n");
3013
3014 //
3015 // sanity checks
3016 //
3017 PC_ASSERT(ControllerInformationBuffer);
3018 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
3019
3020 //
3021 // get controller info buffer
3022 //
3023 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
3024
3025 //
3026 // FIXME only version 0 is supported for now
3027 //
3028 PC_ASSERT(ControllerInfo->InformationLevel == 0);
3029
3030 //
3031 // fill in information
3032 //
3033 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
3034 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
3035 ControllerInfo->IsHighSpeedController = TRUE;
3036
3037 //
3038 // set length returned
3039 //
3040 *LengthReturned = ControllerInfo->ActualLength;
3041
3042 //
3043 // done
3044 //
3045 return STATUS_SUCCESS;
3046 }
3047
3048 NTSTATUS
3049 USB_BUSIFFN
3050 USBHI_ControllerSelectiveSuspend(
3051 PVOID BusContext,
3052 BOOLEAN Enable)
3053 {
3054 UNIMPLEMENTED
3055 return STATUS_NOT_IMPLEMENTED;
3056 }
3057
3058 NTSTATUS
3059 USB_BUSIFFN
3060 USBHI_GetExtendedHubInformation(
3061 PVOID BusContext,
3062 PDEVICE_OBJECT HubPhysicalDeviceObject,
3063 PVOID HubInformationBuffer,
3064 ULONG HubInformationBufferLength,
3065 PULONG LengthReturned)
3066 {
3067 PUSB_EXTHUB_INFORMATION_0 HubInfo;
3068 CHubController * Controller;
3069 PUSBHARDWAREDEVICE Hardware;
3070 ULONG Index;
3071 ULONG NumPort, Dummy2;
3072 USHORT Dummy1;
3073 NTSTATUS Status;
3074
3075 DPRINT1("USBHI_GetExtendedHubInformation\n");
3076
3077 //
3078 // sanity checks
3079 //
3080 PC_ASSERT(HubInformationBuffer);
3081 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
3082 PC_ASSERT(LengthReturned);
3083
3084 //
3085 // get hub controller
3086 //
3087 Controller = (CHubController *)BusContext;
3088 PC_ASSERT(Controller);
3089
3090 //
3091 // get usb hardware device
3092 //
3093 Hardware = Controller->GetUsbHardware();
3094
3095 //
3096 // retrieve number of ports
3097 //
3098 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
3099 if (!NT_SUCCESS(Status))
3100 {
3101 //
3102 // failed to get hardware details, ouch ;)
3103 //
3104 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
3105 return Status;
3106 }
3107
3108 //
3109 // get hub information buffer
3110 //
3111 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
3112
3113 //
3114 // initialize hub information
3115 //
3116 HubInfo->InformationLevel = 0;
3117
3118 //
3119 // store port count
3120 //
3121 HubInfo->NumberOfPorts = NumPort;
3122
3123 //
3124 // initialize port information
3125 //
3126 for(Index = 0; Index < NumPort; Index++)
3127 {
3128 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
3129 HubInfo->Port[Index].PortLabelNumber = Index + 1;
3130 HubInfo->Port[Index].VidOverride = 0;
3131 HubInfo->Port[Index].PidOverride = 0;
3132 HubInfo->Port[Index].PortAttributes = USB_PORTATTR_SHARED_USB2; //FIXME
3133 }
3134
3135 //
3136 // store result length
3137 //
3138 #ifdef _MSC_VER
3139 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
3140 #else
3141 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
3142 #endif
3143
3144 //
3145 // done
3146 //
3147 return STATUS_SUCCESS;
3148 }
3149
3150 NTSTATUS
3151 USB_BUSIFFN
3152 USBHI_GetRootHubSymbolicName(
3153 PVOID BusContext,
3154 PVOID HubSymNameBuffer,
3155 ULONG HubSymNameBufferLength,
3156 PULONG HubSymNameActualLength)
3157 {
3158 UNIMPLEMENTED
3159 return STATUS_NOT_IMPLEMENTED;
3160 }
3161
3162 PVOID
3163 USB_BUSIFFN
3164 USBHI_GetDeviceBusContext(
3165 PVOID HubBusContext,
3166 PVOID DeviceHandle)
3167 {
3168 UNIMPLEMENTED
3169 return NULL;
3170 }
3171
3172 NTSTATUS
3173 USB_BUSIFFN
3174 USBHI_Initialize20Hub(
3175 PVOID BusContext,
3176 PUSB_DEVICE_HANDLE HubDeviceHandle,
3177 ULONG TtCount)
3178 {
3179 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle, TtCount);
3180 return STATUS_SUCCESS;
3181 }
3182
3183 NTSTATUS
3184 USB_BUSIFFN
3185 USBHI_RootHubInitNotification(
3186 PVOID BusContext,
3187 PVOID CallbackContext,
3188 PRH_INIT_CALLBACK CallbackRoutine)
3189 {
3190 CHubController * Controller;
3191
3192 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
3193
3194 //
3195 // get controller object
3196 //
3197 Controller = (CHubController*)BusContext;
3198 PC_ASSERT(Controller);
3199
3200 //
3201 // set notification routine
3202 //
3203 Controller->SetNotification(CallbackContext, CallbackRoutine);
3204
3205 //
3206 // FIXME: determine when to perform callback
3207 //
3208 CallbackRoutine(CallbackContext);
3209
3210 //
3211 // done
3212 //
3213 return STATUS_SUCCESS;
3214 }
3215
3216 VOID
3217 USB_BUSIFFN
3218 USBHI_FlushTransfers(
3219 PVOID BusContext,
3220 PVOID DeviceHandle)
3221 {
3222 UNIMPLEMENTED
3223 }
3224
3225 VOID
3226 USB_BUSIFFN
3227 USBHI_SetDeviceHandleData(
3228 PVOID BusContext,
3229 PVOID DeviceHandle,
3230 PDEVICE_OBJECT UsbDevicePdo)
3231 {
3232 PUSBDEVICE UsbDevice;
3233 CHubController * Controller;
3234
3235 //
3236 // get controller
3237 //
3238 Controller = (CHubController *)BusContext;
3239 PC_ASSERT(Controller);
3240
3241 //
3242 // get device handle
3243 //
3244 UsbDevice = (PUSBDEVICE)DeviceHandle;
3245
3246 //
3247 // validate device handle
3248 //
3249 if (!Controller->ValidateUsbDevice(UsbDevice))
3250 {
3251 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
3252
3253 //
3254 // invalid handle
3255 //
3256 return;
3257 }
3258 else
3259 {
3260 //
3261 // usbhub sends this request as a part of the Pnp startup sequence
3262 // looks like we need apply a dragon voodoo to fixup the device stack
3263 // otherwise usbhub will cause a bugcheck
3264 //
3265 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo);
3266
3267 //
3268 // sanity check
3269 //
3270 PC_ASSERT(UsbDevicePdo->AttachedDevice);
3271
3272 //
3273 // should be usbstor
3274 // fixup device stack voodoo part #2
3275 //
3276 UsbDevicePdo->AttachedDevice->StackSize++;
3277
3278 //
3279 // set device handle data
3280 //
3281 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
3282 }
3283 }
3284
3285 //=================================================================================================
3286 //
3287 // USB Device Interface functions
3288 //
3289
3290 VOID
3291 USB_BUSIFFN
3292 USBDI_GetUSBDIVersion(
3293 PVOID BusContext,
3294 PUSBD_VERSION_INFORMATION VersionInformation,
3295 PULONG HcdCapabilites)
3296 {
3297 CHubController * Controller;
3298 PUSBHARDWAREDEVICE Device;
3299 ULONG Speed, Dummy2;
3300 USHORT Dummy1;
3301
3302 DPRINT1("USBDI_GetUSBDIVersion\n");
3303
3304 //
3305 // get controller
3306 //
3307 Controller = (CHubController*)BusContext;
3308
3309 //
3310 // get usb hardware
3311 //
3312 Device = Controller->GetUsbHardware();
3313 PC_ASSERT(Device);
3314
3315 if (VersionInformation)
3316 {
3317 //
3318 // windows xp supported
3319 //
3320 VersionInformation->USBDI_Version = 0x00000500;
3321
3322 //
3323 // get device speed
3324 //
3325 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3326
3327 //
3328 // store speed details
3329 //
3330 VersionInformation->Supported_USB_Version = Speed;
3331 }
3332
3333 //
3334 // no flags supported
3335 //
3336 *HcdCapabilites = 0;
3337 }
3338
3339 NTSTATUS
3340 USB_BUSIFFN
3341 USBDI_QueryBusTime(
3342 PVOID BusContext,
3343 PULONG CurrentFrame)
3344 {
3345 UNIMPLEMENTED
3346 return STATUS_NOT_IMPLEMENTED;
3347 }
3348
3349 NTSTATUS
3350 USB_BUSIFFN
3351 USBDI_SubmitIsoOutUrb(
3352 PVOID BusContext,
3353 PURB Urb)
3354 {
3355 UNIMPLEMENTED
3356 return STATUS_NOT_IMPLEMENTED;
3357 }
3358
3359 NTSTATUS
3360 USB_BUSIFFN
3361 USBDI_QueryBusInformation(
3362 PVOID BusContext,
3363 ULONG Level,
3364 PVOID BusInformationBuffer,
3365 PULONG BusInformationBufferLength,
3366 PULONG BusInformationActualLength)
3367 {
3368 UNIMPLEMENTED
3369 return STATUS_NOT_IMPLEMENTED;
3370 }
3371
3372 BOOLEAN
3373 USB_BUSIFFN
3374 USBDI_IsDeviceHighSpeed(
3375 PVOID BusContext)
3376 {
3377 CHubController * Controller;
3378 PUSBHARDWAREDEVICE Device;
3379 ULONG Speed, Dummy2;
3380 USHORT Dummy1;
3381
3382 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3383
3384 //
3385 // get controller
3386 //
3387 Controller = (CHubController*)BusContext;
3388
3389 //
3390 // get usb hardware
3391 //
3392 Device = Controller->GetUsbHardware();
3393 PC_ASSERT(Device);
3394
3395 //
3396 // get device speed
3397 //
3398 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3399
3400 //
3401 // USB 2.0 equals 0x200
3402 //
3403 return (Speed == 0x200);
3404 }
3405
3406 NTSTATUS
3407 USB_BUSIFFN
3408 USBDI_EnumLogEntry(
3409 PVOID BusContext,
3410 ULONG DriverTag,
3411 ULONG EnumTag,
3412 ULONG P1,
3413 ULONG P2)
3414 {
3415 UNIMPLEMENTED
3416 return STATUS_NOT_IMPLEMENTED;
3417 }
3418
3419 NTSTATUS
3420 CHubController::HandleQueryInterface(
3421 PIO_STACK_LOCATION IoStack)
3422 {
3423 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
3424 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
3425 UNICODE_STRING GuidBuffer;
3426 NTSTATUS Status;
3427
3428 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
3429 {
3430 //
3431 // get request parameters
3432 //
3433 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
3434 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
3435
3436 //
3437 // check version
3438 //
3439 if (IoStack->Parameters.QueryInterface.Version >= 6)
3440 {
3441 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3442
3443 //
3444 // version not supported
3445 //
3446 return STATUS_NOT_SUPPORTED;
3447 }
3448
3449 //
3450 // Interface version 0
3451 //
3452 if (IoStack->Parameters.QueryInterface.Version >= 0)
3453 {
3454 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
3455 InterfaceHub->BusContext = PVOID(this);
3456 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
3457 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
3458 }
3459
3460 //
3461 // Interface version 1
3462 //
3463 if (IoStack->Parameters.QueryInterface.Version >= 1)
3464 {
3465 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
3466 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
3467 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
3468 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
3469 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
3470 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
3471 }
3472
3473 //
3474 // Interface version 2
3475 //
3476 if (IoStack->Parameters.QueryInterface.Version >= 2)
3477 {
3478 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
3479 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
3480 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
3481 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
3482 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
3483 InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
3484
3485 }
3486
3487 //
3488 // Interface version 3
3489 //
3490 if (IoStack->Parameters.QueryInterface.Version >= 3)
3491 {
3492 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
3493 }
3494
3495 //
3496 // Interface version 4
3497 //
3498 if (IoStack->Parameters.QueryInterface.Version >= 4)
3499 {
3500 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
3501 }
3502
3503 //
3504 // Interface version 5
3505 //
3506 if (IoStack->Parameters.QueryInterface.Version >= 5)
3507 {
3508 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
3509 }
3510
3511 //
3512 // request completed
3513 //
3514 return STATUS_SUCCESS;
3515 }
3516 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
3517 {
3518 //
3519 // get request parameters
3520 //
3521 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
3522 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
3523
3524 //
3525 // check version
3526 //
3527 if (IoStack->Parameters.QueryInterface.Version >= 3)
3528 {
3529 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3530
3531 //
3532 // version not supported
3533 //
3534 return STATUS_NOT_SUPPORTED;
3535 }
3536
3537 //
3538 // interface version 0
3539 //
3540 if (IoStack->Parameters.QueryInterface.Version >= 0)
3541 {
3542 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
3543 InterfaceDI->BusContext = PVOID(this);
3544 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
3545 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
3546 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
3547 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
3548 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
3549 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
3550 }
3551
3552 //
3553 // interface version 1
3554 //
3555 if (IoStack->Parameters.QueryInterface.Version >= 1)
3556 {
3557 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
3558 }
3559
3560 //
3561 // interface version 2
3562 //
3563 if (IoStack->Parameters.QueryInterface.Version >= 2)
3564 {
3565 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
3566 }
3567
3568 //
3569 // request completed
3570 //
3571 return STATUS_SUCCESS;
3572 }
3573 else
3574 {
3575 //
3576 // convert guid to string
3577 //
3578 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
3579 if (NT_SUCCESS(Status))
3580 {
3581 //
3582 // print interface
3583 //
3584 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
3585
3586 //
3587 // free guid buffer
3588 //
3589 RtlFreeUnicodeString(&GuidBuffer);
3590 }
3591 }
3592 return STATUS_NOT_SUPPORTED;
3593 }
3594
3595 NTSTATUS
3596 CHubController::SetDeviceInterface(
3597 BOOLEAN Enable)
3598 {
3599 NTSTATUS Status = STATUS_SUCCESS;
3600
3601 if (Enable)
3602 {
3603 //
3604 // register device interface
3605 //
3606 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
3607
3608 if (NT_SUCCESS(Status))
3609 {
3610 //
3611 // now enable the device interface
3612 //
3613 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
3614
3615 //
3616 // enable interface
3617 //
3618 m_InterfaceEnabled = TRUE;
3619 }
3620 }
3621 else if (m_InterfaceEnabled)
3622 {
3623 //
3624 // disable device interface
3625 //
3626 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
3627
3628 if (NT_SUCCESS(Status))
3629 {
3630 //
3631 // now delete interface string
3632 //
3633 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
3634 }
3635
3636 //
3637 // disable interface
3638 //
3639 m_InterfaceEnabled = FALSE;
3640 }
3641
3642 //
3643 // done
3644 //
3645 return STATUS_SUCCESS;
3646 }
3647
3648 NTSTATUS
3649 CHubController::CreatePDO(
3650 PDRIVER_OBJECT DriverObject,
3651 PDEVICE_OBJECT * OutDeviceObject)
3652 {
3653 WCHAR CharDeviceName[64];
3654 NTSTATUS Status;
3655 ULONG UsbDeviceNumber = 0;
3656 UNICODE_STRING DeviceName;
3657
3658 while (TRUE)
3659 {
3660 //
3661 // construct device name
3662 //
3663 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
3664
3665 //
3666 // initialize device name
3667 //
3668 RtlInitUnicodeString(&DeviceName, CharDeviceName);
3669
3670 //
3671 // create device
3672 //
3673 Status = IoCreateDevice(DriverObject,
3674 sizeof(COMMON_DEVICE_EXTENSION),
3675 &DeviceName,
3676 FILE_DEVICE_CONTROLLER,
3677 0,
3678 FALSE,
3679 OutDeviceObject);
3680
3681 /* check for success */
3682 if (NT_SUCCESS(Status))
3683 break;
3684
3685 //
3686 // is there a device object with that same name
3687 //
3688 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
3689 {
3690 //
3691 // Try the next name
3692 //
3693 UsbDeviceNumber++;
3694 continue;
3695 }
3696
3697 //
3698 // bail out on other errors
3699 //
3700 if (!NT_SUCCESS(Status))
3701 {
3702 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
3703 return Status;
3704 }
3705 }
3706
3707 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
3708
3709 //
3710 // fixup device stack voodoo part #1
3711 //
3712 (*OutDeviceObject)->StackSize++;
3713
3714 /* done */
3715 return Status;
3716 }
3717
3718
3719
3720 NTSTATUS
3721 CreateHubController(
3722 PHUBCONTROLLER *OutHcdController)
3723 {
3724 PHUBCONTROLLER This;
3725
3726 //
3727 // allocate controller
3728 //
3729 This = new(NonPagedPool, TAG_USBLIB) CHubController(0);
3730 if (!This)
3731 {
3732 //
3733 // failed to allocate
3734 //
3735 return STATUS_INSUFFICIENT_RESOURCES;
3736 }
3737
3738 //
3739 // add reference count
3740 //
3741 This->AddRef();
3742
3743 //
3744 // return result
3745 //
3746 *OutHcdController = (PHUBCONTROLLER)This;
3747
3748 //
3749 // done
3750 //
3751 return STATUS_SUCCESS;
3752 }
3753
3754 VOID StatusChangeEndpointCallBack(PVOID Context)
3755 {
3756 CHubController* This;
3757 PIRP Irp;
3758 This = (CHubController*)Context;
3759
3760 ASSERT(This);
3761
3762 Irp = This->m_PendingSCEIrp;
3763 if (!Irp)
3764 {
3765 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3766 return;
3767 }
3768
3769 This->m_PendingSCEIrp = NULL;
3770 This->QueryStatusChageEndpoint(Irp);
3771
3772 Irp->IoStatus.Status = STATUS_SUCCESS;
3773 Irp->IoStatus.Information = 0;
3774
3775 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3776 }