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