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