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