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