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