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