[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 PVOID TransferBuffer = NULL;
1846
1847 DPRINT("CHubController::HandleVendorDevice Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1848
1849 //
1850 // sanity check
1851 //
1852 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1853
1854 //
1855 // check if this is a valid usb device handle
1856 //
1857 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1858 {
1859 DPRINT1("[USBLIB] HandleVendorDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1860
1861 //
1862 // invalid device handle
1863 //
1864 return STATUS_DEVICE_NOT_CONNECTED;
1865 }
1866
1867 //
1868 // get device
1869 //
1870 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1871
1872 //
1873 // initialize setup packet
1874 //
1875 CtrlSetup.bmRequestType.B = 0;
1876 CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
1877 CtrlSetup.bmRequestType._BM.Type = BMREQUEST_VENDOR;
1878 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1879 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1880 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1881 CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength;
1882
1883 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1884 {
1885 //
1886 // data direction is device to host
1887 //
1888 CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
1889 }
1890
1891 //
1892 // issue request
1893 //
1894 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1895
1896 return Status;
1897 }
1898
1899 //-----------------------------------------------------------------------------------------
1900 NTSTATUS
1901 CHubController::HandleSyncResetAndClearStall(
1902 IN OUT PIRP Irp,
1903 IN OUT PURB Urb)
1904 {
1905 NTSTATUS Status = STATUS_SUCCESS;
1906 PUSB_ENDPOINT EndpointDescriptor;
1907 ULONG Type;
1908
1909 //
1910 // sanity check
1911 //
1912 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1913 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1914 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1915
1916 //
1917 // check if this is a valid usb device handle
1918 //
1919 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1920 {
1921 DPRINT1("[USBLIB] HandleSyncResetAndClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1922
1923 //
1924 // invalid device handle
1925 //
1926 return STATUS_DEVICE_NOT_CONNECTED;
1927 }
1928
1929 //
1930 // abort pipe
1931 //
1932 Status = HandleAbortPipe(Irp, Urb);
1933 if (!NT_SUCCESS(Status))
1934 {
1935 //
1936 // failed
1937 //
1938 DPRINT1("[USBLIB] failed to reset pipe %x\n", Status);
1939 }
1940
1941
1942 //
1943 // get endpoint descriptor
1944 //
1945 EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbPipeRequest.PipeHandle;
1946
1947 //
1948 // get type
1949 //
1950 Type = (EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK);
1951 if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
1952 {
1953 //
1954 // clear stall
1955 //
1956 Status = HandleClearStall(Irp, Urb);
1957 }
1958 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
1959
1960 //
1961 // reset data toggle
1962 //
1963 if (NT_SUCCESS(Status))
1964 EndpointDescriptor->DataToggle = 0x0;
1965
1966 //
1967 // done
1968 //
1969 return Status;
1970 }
1971
1972 //-----------------------------------------------------------------------------------------
1973 NTSTATUS
1974 CHubController::HandleAbortPipe(
1975 IN OUT PIRP Irp,
1976 IN OUT PURB Urb)
1977 {
1978 NTSTATUS Status;
1979 PUSBDEVICE UsbDevice;
1980 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1981
1982 //
1983 // sanity check
1984 //
1985 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1986 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1987 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1988
1989 //
1990 // check if this is a valid usb device handle
1991 //
1992 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1993 {
1994 DPRINT1("[USBLIB] HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1995
1996 //
1997 // invalid device handle
1998 //
1999 return STATUS_DEVICE_NOT_CONNECTED;
2000 }
2001
2002 //
2003 // get endpoint descriptor
2004 //
2005 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
2006
2007 //
2008 // get device
2009 //
2010 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
2011
2012
2013 //
2014 // issue request
2015 //
2016 Status = UsbDevice->AbortPipe(EndpointDescriptor);
2017 DPRINT1("[USBLIB] URB_FUNCTION_ABORT_PIPE Status %x\n", Status);
2018
2019 //
2020 // done
2021 //
2022 return Status;
2023 }
2024
2025
2026 //-----------------------------------------------------------------------------------------
2027 NTSTATUS
2028 CHubController::HandleClearStall(
2029 IN OUT PIRP Irp,
2030 IN OUT PURB Urb)
2031 {
2032 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
2033 NTSTATUS Status;
2034 PUSBDEVICE UsbDevice;
2035 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
2036
2037
2038 //
2039 // sanity check
2040 //
2041 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
2042 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
2043 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
2044
2045 //
2046 // check if this is a valid usb device handle
2047 //
2048 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
2049 {
2050 DPRINT1("[USBLIB] HandleClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
2051
2052 //
2053 // invalid device handle
2054 //
2055 return STATUS_DEVICE_NOT_CONNECTED;
2056 }
2057
2058 //
2059 // get endpoint descriptor
2060 //
2061 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
2062
2063 //
2064 // get device
2065 //
2066 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
2067 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_CLEAR_STALL\n");
2068
2069 //
2070 // initialize setup packet
2071 //
2072 CtrlSetup.bmRequestType.B = 0x02;
2073 CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE;
2074 CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL;
2075 CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress;
2076 CtrlSetup.wLength = 0;
2077 CtrlSetup.wValue.W = 0;
2078
2079 //
2080 // issue request
2081 //
2082 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0);
2083
2084 DPRINT1("[USBLIB] URB_FUNCTION_CLEAR_STALL Status %x\n", Status);
2085
2086 //
2087 // done
2088 //
2089 return Status;
2090 }
2091
2092
2093 //-----------------------------------------------------------------------------------------
2094 NTSTATUS
2095 CHubController::HandleClassInterface(
2096 IN OUT PIRP Irp,
2097 IN OUT PURB Urb)
2098 {
2099 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
2100 NTSTATUS Status;
2101 PUSBDEVICE UsbDevice;
2102
2103 //
2104 // sanity check
2105 //
2106 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
2107 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
2108 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
2109
2110 //
2111 // check if this is a valid usb device handle
2112 //
2113 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
2114 {
2115 DPRINT1("[USBLIB] HandleClassInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
2116
2117 //
2118 // invalid device handle
2119 //
2120 return STATUS_DEVICE_NOT_CONNECTED;
2121 }
2122
2123 //
2124 // get device
2125 //
2126 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
2127
2128
2129 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
2130 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
2131 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
2132 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
2133 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
2134 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
2135 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
2136 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
2137 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
2138
2139 //
2140 // initialize setup packet
2141 //
2142 CtrlSetup.bmRequestType.B = 0x21;
2143 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
2144 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
2145 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
2146 CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength;
2147
2148 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
2149 {
2150 //
2151 // data direction is device to host
2152 //
2153 CtrlSetup.bmRequestType.B |= 0x80;
2154 }
2155
2156 //
2157 // issue request
2158 //
2159 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
2160
2161 //
2162 // assert on failure
2163 //
2164 if (!NT_SUCCESS(Status))
2165 {
2166 //
2167 // display error
2168 //
2169 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status);
2170 }
2171
2172 //
2173 // done
2174 //
2175 return Status;
2176 }
2177
2178 //-----------------------------------------------------------------------------------------
2179 NTSTATUS
2180 CHubController::HandleDeviceControl(
2181 IN PDEVICE_OBJECT DeviceObject,
2182 IN OUT PIRP Irp)
2183 {
2184 PIO_STACK_LOCATION IoStack;
2185 PCOMMON_DEVICE_EXTENSION DeviceExtension;
2186 PURB Urb;
2187 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
2188
2189 //
2190 // get current stack location
2191 //
2192 IoStack = IoGetCurrentIrpStackLocation(Irp);
2193
2194 //
2195 // get device extension
2196 //
2197 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
2198
2199 //
2200 // determine which request should be performed
2201 //
2202 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
2203 {
2204 case IOCTL_INTERNAL_USB_SUBMIT_URB:
2205 {
2206 //
2207 // get urb
2208 //
2209 Urb = (PURB)IoStack->Parameters.Others.Argument1;
2210 PC_ASSERT(Urb);
2211
2212 switch (Urb->UrbHeader.Function)
2213 {
2214 case URB_FUNCTION_SYNC_RESET_PIPE:
2215 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
2216 Status = HandleSyncResetAndClearStall(Irp, Urb);
2217 break;
2218 case URB_FUNCTION_ABORT_PIPE:
2219 Status = HandleAbortPipe(Irp, Urb);
2220 break;
2221 case URB_FUNCTION_SYNC_CLEAR_STALL:
2222 Status = HandleClearStall(Irp, Urb);
2223 break;
2224 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
2225 Status = HandleGetDescriptorFromInterface(Irp, Urb);
2226 break;
2227 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
2228 Status = HandleGetDescriptor(Irp, Urb);
2229 break;
2230 case URB_FUNCTION_CLASS_DEVICE:
2231 Status = HandleClassDevice(Irp, Urb);
2232 break;
2233 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
2234 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
2235 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
2236 Status = HandleGetStatusFromDevice(Irp, Urb);
2237 break;
2238 case URB_FUNCTION_SELECT_CONFIGURATION:
2239 Status = HandleSelectConfiguration(Irp, Urb);
2240 break;
2241 case URB_FUNCTION_SELECT_INTERFACE:
2242 Status = HandleSelectInterface(Irp, Urb);
2243 break;
2244 case URB_FUNCTION_CLASS_OTHER:
2245 Status = HandleClassOther(Irp, Urb);
2246 break;
2247 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
2248 Status = HandleBulkOrInterruptTransfer(Irp, Urb);
2249 break;
2250 case URB_FUNCTION_ISOCH_TRANSFER:
2251 Status = HandleIsochronousTransfer(Irp, Urb);
2252 break;
2253 case URB_FUNCTION_CLASS_INTERFACE:
2254 Status = HandleClassInterface(Irp, Urb);
2255 break;
2256 case URB_FUNCTION_CLASS_ENDPOINT:
2257 Status = HandleClassEndpoint(Irp, Urb);
2258 break;
2259 case URB_FUNCTION_VENDOR_DEVICE:
2260 Status = HandleVendorDevice(Irp, Urb);
2261 break;
2262 default:
2263 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
2264 break;
2265 }
2266 //
2267 // request completed
2268 //
2269 break;
2270 }
2271 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
2272 {
2273 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
2274
2275 if (IoStack->Parameters.Others.Argument1)
2276 {
2277 //
2278 // store object as device handle
2279 //
2280 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
2281 Status = STATUS_SUCCESS;
2282 }
2283 else
2284 {
2285 //
2286 // mis-behaving hub driver
2287 //
2288 Status = STATUS_INVALID_DEVICE_REQUEST;
2289 }
2290
2291 //
2292 // request completed
2293 //
2294 break;
2295 }
2296 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
2297 {
2298 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
2299
2300 //
2301 // this is the first request send, it delivers the PDO to the caller
2302 //
2303 if (IoStack->Parameters.Others.Argument1)
2304 {
2305 //
2306 // store root hub pdo object
2307 //
2308 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
2309 }
2310
2311 if (IoStack->Parameters.Others.Argument2)
2312 {
2313 //
2314 // documentation claims to deliver the hcd controller object, although it is wrong
2315 //
2316 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
2317 }
2318
2319 //
2320 // request completed
2321 //
2322 Status = STATUS_SUCCESS;
2323 break;
2324 }
2325 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
2326 {
2327 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
2328
2329 //
2330 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2331 // requests this ioctl to deliver the number of presents.
2332
2333 if (IoStack->Parameters.Others.Argument1)
2334 {
2335 //
2336 // FIXME / verify: there is only one hub
2337 //
2338 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
2339 }
2340
2341 //
2342 // request completed
2343 //
2344 Status = STATUS_SUCCESS;
2345 Irp->IoStatus.Information = sizeof(ULONG);
2346 break;
2347 }
2348 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
2349 {
2350 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
2351 Status = STATUS_SUCCESS;
2352 break;
2353 }
2354 default:
2355 {
2356 DPRINT1("[USBLIB] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
2357 IoStack->Parameters.DeviceIoControl.IoControlCode,
2358 IoStack->Parameters.DeviceIoControl.InputBufferLength,
2359 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
2360 break;
2361 }
2362 }
2363 if (Status != STATUS_PENDING)
2364 {
2365 Irp->IoStatus.Status = Status;
2366 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2367 }
2368
2369 return Status;
2370 }
2371
2372 //-----------------------------------------------------------------------------------------
2373 PUSBHARDWAREDEVICE
2374 CHubController::GetUsbHardware()
2375 {
2376 return m_Hardware;
2377 }
2378
2379 //-----------------------------------------------------------------------------------------
2380 ULONG
2381 CHubController::AcquireDeviceAddress()
2382 {
2383 KIRQL OldLevel;
2384 ULONG DeviceAddress;
2385
2386 //
2387 // acquire device lock
2388 //
2389 KeAcquireSpinLock(&m_Lock, &OldLevel);
2390
2391 //
2392 // find address
2393 //
2394 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
2395 if (DeviceAddress != MAXULONG)
2396 {
2397 //
2398 // reserve address
2399 //
2400 RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2401
2402 //
2403 // device addresses start from 0x1 - 0xFF
2404 //
2405 DeviceAddress++;
2406 }
2407
2408 //
2409 // release spin lock
2410 //
2411 KeReleaseSpinLock(&m_Lock, OldLevel);
2412
2413 //
2414 // return device address
2415 //
2416 return DeviceAddress;
2417 }
2418 //-----------------------------------------------------------------------------------------
2419 VOID
2420 CHubController::ReleaseDeviceAddress(
2421 ULONG DeviceAddress)
2422 {
2423 KIRQL OldLevel;
2424
2425 //
2426 // acquire device lock
2427 //
2428 KeAcquireSpinLock(&m_Lock, &OldLevel);
2429
2430 //
2431 // sanity check
2432 //
2433 PC_ASSERT(DeviceAddress != 0);
2434
2435 //
2436 // convert back to bit number
2437 //
2438 DeviceAddress--;
2439
2440 //
2441 // clear bit
2442 //
2443 RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2444
2445 //
2446 // release lock
2447 //
2448 KeReleaseSpinLock(&m_Lock, OldLevel);
2449 }
2450 //-----------------------------------------------------------------------------------------
2451 NTSTATUS
2452 CHubController::RemoveUsbDevice(
2453 PUSBDEVICE UsbDevice)
2454 {
2455 PUSBDEVICE_ENTRY DeviceEntry;
2456 PLIST_ENTRY Entry;
2457 NTSTATUS Status = STATUS_UNSUCCESSFUL;
2458 KIRQL OldLevel;
2459
2460 //
2461 // acquire lock
2462 //
2463 KeAcquireSpinLock(&m_Lock, &OldLevel);
2464
2465 //
2466 // point to first entry
2467 //
2468 Entry = m_UsbDeviceList.Flink;
2469
2470 //
2471 // find matching entry
2472 //
2473 while(Entry != &m_UsbDeviceList)
2474 {
2475 //
2476 // get entry
2477 //
2478 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2479
2480 //
2481 // is it current entry
2482 //
2483 if (DeviceEntry->Device == UsbDevice)
2484 {
2485 //
2486 // remove entry
2487 //
2488 RemoveEntryList(Entry);
2489
2490 //
2491 // free entry
2492 //
2493 ExFreePoolWithTag(DeviceEntry, TAG_USBLIB);
2494
2495 //
2496 // done
2497 //
2498 Status = STATUS_SUCCESS;
2499 break;
2500 }
2501
2502 //
2503 // goto next device
2504 //
2505 Entry = Entry->Flink;
2506 }
2507
2508 //
2509 // release lock
2510 //
2511 KeReleaseSpinLock(&m_Lock, OldLevel);
2512
2513 //
2514 // return result
2515 //
2516 return Status;
2517 }
2518 //-----------------------------------------------------------------------------------------
2519 BOOLEAN
2520 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
2521 {
2522 PUSBDEVICE_ENTRY DeviceEntry;
2523 PLIST_ENTRY Entry;
2524 KIRQL OldLevel;
2525 BOOLEAN Result = FALSE;
2526
2527 //
2528 // acquire lock
2529 //
2530 KeAcquireSpinLock(&m_Lock, &OldLevel);
2531
2532 //
2533 // point to first entry
2534 //
2535 Entry = m_UsbDeviceList.Flink;
2536
2537 //
2538 // find matching entry
2539 //
2540 while(Entry != &m_UsbDeviceList)
2541 {
2542 //
2543 // get entry
2544 //
2545 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2546
2547 //
2548 // is it current entry
2549 //
2550 if (DeviceEntry->Device == UsbDevice)
2551 {
2552 //
2553 // device is valid
2554 //
2555 Result = TRUE;
2556 break;
2557 }
2558
2559 //
2560 // goto next device
2561 //
2562 Entry = Entry->Flink;
2563 }
2564
2565 //
2566 // release lock
2567 //
2568 KeReleaseSpinLock(&m_Lock, OldLevel);
2569
2570 //
2571 // return result
2572 //
2573 return Result;
2574
2575 }
2576
2577 //-----------------------------------------------------------------------------------------
2578 NTSTATUS
2579 CHubController::AddUsbDevice(
2580 PUSBDEVICE UsbDevice)
2581 {
2582 PUSBDEVICE_ENTRY DeviceEntry;
2583 KIRQL OldLevel;
2584
2585 //
2586 // allocate device entry
2587 //
2588 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBLIB);
2589 if (!DeviceEntry)
2590 {
2591 //
2592 // no memory
2593 //
2594 return STATUS_INSUFFICIENT_RESOURCES;
2595 }
2596
2597 //
2598 // initialize entry
2599 //
2600 DeviceEntry->Device = UsbDevice;
2601
2602 //
2603 // acquire lock
2604 //
2605 KeAcquireSpinLock(&m_Lock, &OldLevel);
2606
2607 //
2608 // insert entry
2609 //
2610 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
2611
2612 //
2613 // release spin lock
2614 //
2615 KeReleaseSpinLock(&m_Lock, OldLevel);
2616
2617 //
2618 // done
2619 //
2620 return STATUS_SUCCESS;
2621 }
2622
2623 //-----------------------------------------------------------------------------------------
2624 VOID
2625 CHubController::SetNotification(
2626 PVOID CallbackContext,
2627 PRH_INIT_CALLBACK CallbackRoutine)
2628 {
2629 KIRQL OldLevel;
2630
2631 //
2632 // acquire hub controller lock
2633 //
2634 KeAcquireSpinLock(&m_Lock, &OldLevel);
2635
2636 //
2637 // now set the callback routine and context of the hub
2638 //
2639 m_HubCallbackContext = CallbackContext;
2640 m_HubCallbackRoutine = CallbackRoutine;
2641
2642 //
2643 // release hub controller lock
2644 //
2645 KeReleaseSpinLock(&m_Lock, OldLevel);
2646 }
2647
2648 //=================================================================================================
2649 //
2650 // Generic Interface functions
2651 //
2652 VOID
2653 USB_BUSIFFN
2654 USBI_InterfaceReference(
2655 PVOID BusContext)
2656 {
2657 CHubController * Controller = (CHubController*)BusContext;
2658
2659 DPRINT1("USBH_InterfaceReference\n");
2660
2661 //
2662 // add reference
2663 //
2664 Controller->AddRef();
2665 }
2666
2667 VOID
2668 USB_BUSIFFN
2669 USBI_InterfaceDereference(
2670 PVOID BusContext)
2671 {
2672 CHubController * Controller = (CHubController*)BusContext;
2673
2674 DPRINT1("USBH_InterfaceDereference\n");
2675
2676 //
2677 // release
2678 //
2679 Controller->Release();
2680 }
2681 //=================================================================================================
2682 //
2683 // USB Hub Interface functions
2684 //
2685 NTSTATUS
2686 USB_BUSIFFN
2687 USBHI_CreateUsbDevice(
2688 PVOID BusContext,
2689 PUSB_DEVICE_HANDLE *NewDevice,
2690 PUSB_DEVICE_HANDLE HubDeviceHandle,
2691 USHORT PortStatus,
2692 USHORT PortNumber)
2693 {
2694 PUSBDEVICE NewUsbDevice;
2695 CHubController * Controller;
2696 NTSTATUS Status;
2697
2698 DPRINT1("USBHI_CreateUsbDevice\n");
2699
2700 //
2701 // first get hub controller
2702 //
2703 Controller = (CHubController *)BusContext;
2704
2705 //
2706 // sanity check
2707 //
2708 PC_ASSERT(Controller);
2709 PC_ASSERT(BusContext == HubDeviceHandle);
2710
2711 //
2712 // now allocate usb device
2713 //
2714 Status = CreateUSBDevice(&NewUsbDevice);
2715
2716 //
2717 // check for success
2718 //
2719 if (!NT_SUCCESS(Status))
2720 {
2721 //
2722 // release controller
2723 //
2724 Controller->Release();
2725 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
2726 return Status;
2727 }
2728
2729 //
2730 // now initialize device
2731 //
2732 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(), HubDeviceHandle, PortNumber, PortStatus);
2733
2734 //
2735 // check for success
2736 //
2737 if (!NT_SUCCESS(Status))
2738 {
2739 //
2740 // release usb device
2741 //
2742 NewUsbDevice->Release();
2743 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
2744 return Status;
2745 }
2746
2747 //
2748 // insert into list
2749 //
2750 Status = Controller->AddUsbDevice(NewUsbDevice);
2751 //
2752 // check for success
2753 //
2754 if (!NT_SUCCESS(Status))
2755 {
2756 //
2757 // release usb device
2758 //
2759 NewUsbDevice->Release();
2760
2761 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
2762 return Status;
2763 }
2764
2765 //
2766 // store the handle
2767 //
2768 *NewDevice = NewUsbDevice;
2769
2770 //
2771 // done
2772 //
2773 return STATUS_SUCCESS;
2774 }
2775
2776 NTSTATUS
2777 USB_BUSIFFN
2778 USBHI_InitializeUsbDevice(
2779 PVOID BusContext,
2780 PUSB_DEVICE_HANDLE DeviceHandle)
2781 {
2782 PUSBDEVICE UsbDevice;
2783 CHubController * Controller;
2784 ULONG DeviceAddress;
2785 NTSTATUS Status;
2786 ULONG Index = 0;
2787
2788 DPRINT1("USBHI_InitializeUsbDevice\n");
2789
2790 //
2791 // first get controller
2792 //
2793 Controller = (CHubController *)BusContext;
2794 PC_ASSERT(Controller);
2795
2796 //
2797 // get device object
2798 //
2799 UsbDevice = (PUSBDEVICE)DeviceHandle;
2800 PC_ASSERT(UsbDevice);
2801
2802 //
2803 // validate device handle
2804 //
2805 if (!Controller->ValidateUsbDevice(UsbDevice))
2806 {
2807 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
2808
2809 //
2810 // invalid device handle
2811 //
2812 return STATUS_DEVICE_NOT_CONNECTED;
2813 }
2814
2815 //
2816 // now reserve an address
2817 //
2818 DeviceAddress = Controller->AcquireDeviceAddress();
2819
2820 //
2821 // is the device address valid
2822 //
2823 if (DeviceAddress == MAXULONG)
2824 {
2825 //
2826 // failed to get an device address from the device address pool
2827 //
2828 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2829 return STATUS_DEVICE_DATA_ERROR;
2830 }
2831
2832 do
2833 {
2834 //
2835 // now set the device address
2836 //
2837 Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
2838
2839 if (NT_SUCCESS(Status))
2840 break;
2841
2842 }while(Index++ < 3 );
2843
2844 //
2845 // check for failure
2846 //
2847 if (!NT_SUCCESS(Status))
2848 {
2849 //
2850 // failed to set device address
2851 //
2852 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
2853
2854 //
2855 // release address
2856 //
2857 Controller->ReleaseDeviceAddress(DeviceAddress);
2858
2859 //
2860 // return error
2861 //
2862 return STATUS_DEVICE_DATA_ERROR;
2863 }
2864
2865 //
2866 // done
2867 //
2868 return STATUS_SUCCESS;
2869 }
2870
2871 NTSTATUS
2872 USB_BUSIFFN
2873 USBHI_GetUsbDescriptors(
2874 PVOID BusContext,
2875 PUSB_DEVICE_HANDLE DeviceHandle,
2876 PUCHAR DeviceDescriptorBuffer,
2877 PULONG DeviceDescriptorBufferLength,
2878 PUCHAR ConfigDescriptorBuffer,
2879 PULONG ConfigDescriptorBufferLength)
2880 {
2881 PUSBDEVICE UsbDevice;
2882 CHubController * Controller;
2883
2884 DPRINT1("USBHI_GetUsbDescriptors\n");
2885
2886 //
2887 // sanity check
2888 //
2889 PC_ASSERT(DeviceDescriptorBuffer);
2890 PC_ASSERT(DeviceDescriptorBufferLength);
2891 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
2892 PC_ASSERT(ConfigDescriptorBufferLength);
2893 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
2894
2895 //
2896 // first get controller
2897 //
2898 Controller = (CHubController *)BusContext;
2899 PC_ASSERT(Controller);
2900
2901
2902 //
2903 // get device object
2904 //
2905 UsbDevice = (PUSBDEVICE)DeviceHandle;
2906 PC_ASSERT(UsbDevice);
2907
2908 //
2909 // validate device handle
2910 //
2911 if (!Controller->ValidateUsbDevice(UsbDevice))
2912 {
2913 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
2914
2915 //
2916 // invalid device handle
2917 //
2918 return STATUS_DEVICE_NOT_CONNECTED;
2919 }
2920
2921 //
2922 // get device descriptor
2923 //
2924 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
2925
2926 //
2927 // store result length
2928 //
2929 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
2930
2931 //
2932 // get configuration descriptor
2933 //
2934 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
2935
2936 //
2937 // complete the request
2938 //
2939 return STATUS_SUCCESS;
2940 }
2941
2942 NTSTATUS
2943 USB_BUSIFFN
2944 USBHI_RemoveUsbDevice(
2945 PVOID BusContext,
2946 PUSB_DEVICE_HANDLE DeviceHandle,
2947 ULONG Flags)
2948 {
2949 PUSBDEVICE UsbDevice;
2950 CHubController * Controller;
2951 NTSTATUS Status;
2952
2953 DPRINT1("USBHI_RemoveUsbDevice\n");
2954
2955 //
2956 // first get controller
2957 //
2958 Controller = (CHubController *)BusContext;
2959 PC_ASSERT(Controller);
2960
2961 //
2962 // get device object
2963 //
2964 UsbDevice = (PUSBDEVICE)DeviceHandle;
2965 PC_ASSERT(UsbDevice);
2966
2967 //
2968 // validate device handle
2969 //
2970 if (!Controller->ValidateUsbDevice(UsbDevice))
2971 {
2972 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
2973
2974 //
2975 // invalid device handle
2976 //
2977 return STATUS_DEVICE_NOT_CONNECTED;
2978 }
2979
2980 //
2981 // check if there were flags passed
2982 //
2983 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
2984 {
2985 //
2986 // ignore flags for now
2987 //
2988 return STATUS_SUCCESS;
2989 }
2990
2991 //
2992 // remove device
2993 //
2994 Status = Controller->RemoveUsbDevice(UsbDevice);
2995 if (!NT_SUCCESS(Status))
2996 {
2997 //
2998 // invalid device handle
2999 //
3000 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
3001 PC_ASSERT(0);
3002 return STATUS_DEVICE_NOT_CONNECTED;
3003 }
3004
3005 //
3006 // release usb device
3007 //
3008 UsbDevice->Release();
3009
3010 //
3011 // done
3012 //
3013 return STATUS_SUCCESS;
3014 }
3015
3016 NTSTATUS
3017 USB_BUSIFFN
3018 USBHI_RestoreUsbDevice(
3019 PVOID BusContext,
3020 PUSB_DEVICE_HANDLE OldDeviceHandle,
3021 PUSB_DEVICE_HANDLE NewDeviceHandle)
3022 {
3023 PUSBDEVICE OldUsbDevice, NewUsbDevice;
3024 CHubController * Controller;
3025
3026 DPRINT1("USBHI_RestoreUsbDevice\n");
3027
3028 //
3029 // first get controller
3030 //
3031 Controller = (CHubController *)BusContext;
3032 PC_ASSERT(Controller);
3033
3034 //
3035 // get device object
3036 //
3037 OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
3038 NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
3039 PC_ASSERT(OldUsbDevice);
3040 PC_ASSERT(NewDeviceHandle);
3041
3042 //
3043 // validate device handle
3044 //
3045 PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
3046 PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
3047
3048 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
3049 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
3050
3051 //
3052 // remove old device handle
3053 //
3054 USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
3055
3056 return STATUS_SUCCESS;
3057 }
3058
3059 NTSTATUS
3060 USB_BUSIFFN
3061 USBHI_QueryDeviceInformation(
3062 PVOID BusContext,
3063 PUSB_DEVICE_HANDLE DeviceHandle,
3064 PVOID DeviceInformationBuffer,
3065 ULONG DeviceInformationBufferLength,
3066 PULONG LengthReturned)
3067 {
3068 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
3069 PUSBDEVICE UsbDevice;
3070 CHubController * Controller;
3071
3072 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
3073
3074 //
3075 // sanity check
3076 //
3077 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
3078 PC_ASSERT(DeviceInformationBuffer);
3079 PC_ASSERT(LengthReturned);
3080
3081 //
3082 // get controller object
3083 //
3084 Controller = (CHubController*)BusContext;
3085 PC_ASSERT(Controller);
3086
3087 //
3088 // get device object
3089 //
3090 UsbDevice = (PUSBDEVICE)DeviceHandle;
3091 PC_ASSERT(UsbDevice);
3092
3093 if (BusContext != DeviceHandle)
3094 {
3095 //
3096 // validate device handle
3097 //
3098 if (!Controller->ValidateUsbDevice(UsbDevice))
3099 {
3100 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
3101
3102 //
3103 // invalid device handle
3104 //
3105 return STATUS_DEVICE_NOT_CONNECTED;
3106 }
3107
3108 //
3109 // access information buffer
3110 //
3111 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
3112
3113 //
3114 // initialize with default values
3115 //
3116 DeviceInfo->InformationLevel = 0;
3117 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
3118 DeviceInfo->PortNumber = UsbDevice->GetPort();
3119 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
3120 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
3121 DeviceInfo->HubAddress = 0; //FIXME
3122 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
3123 DeviceInfo->DeviceType = UsbDevice->GetType();
3124 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
3125
3126 //
3127 // get device descriptor
3128 //
3129 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
3130
3131 //
3132 // FIXME return pipe information
3133 //
3134
3135 //
3136 // store result length
3137 //
3138 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
3139
3140 return STATUS_SUCCESS;
3141 }
3142
3143 //
3144 // access information buffer
3145 //
3146 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
3147
3148 //
3149 // initialize with default values
3150 //
3151 DeviceInfo->InformationLevel = 0;
3152 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
3153 DeviceInfo->PortNumber = 0;
3154 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
3155 DeviceInfo->DeviceAddress = 0;
3156 DeviceInfo->HubAddress = 0; //FIXME
3157 DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
3158 DeviceInfo->DeviceType = Usb20Device; //FIXME
3159 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
3160
3161 //
3162 // get device descriptor
3163 //
3164 RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
3165
3166 //
3167 // FIXME return pipe information
3168 //
3169
3170 //
3171 // store result length
3172 //
3173 #ifdef _MSC_VER
3174 *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
3175 #else
3176 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
3177 #endif
3178 //
3179 // done
3180 //
3181 return STATUS_SUCCESS;
3182 }
3183
3184 NTSTATUS
3185 USB_BUSIFFN
3186 USBHI_GetControllerInformation(
3187 PVOID BusContext,
3188 PVOID ControllerInformationBuffer,
3189 ULONG ControllerInformationBufferLength,
3190 PULONG LengthReturned)
3191 {
3192 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
3193
3194 DPRINT1("USBHI_GetControllerInformation\n");
3195
3196 //
3197 // sanity checks
3198 //
3199 PC_ASSERT(ControllerInformationBuffer);
3200 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
3201
3202 //
3203 // get controller info buffer
3204 //
3205 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
3206
3207 //
3208 // FIXME only version 0 is supported for now
3209 //
3210 PC_ASSERT(ControllerInfo->InformationLevel == 0);
3211
3212 //
3213 // fill in information
3214 //
3215 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
3216 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
3217 ControllerInfo->IsHighSpeedController = TRUE;
3218
3219 //
3220 // set length returned
3221 //
3222 *LengthReturned = ControllerInfo->ActualLength;
3223
3224 //
3225 // done
3226 //
3227 return STATUS_SUCCESS;
3228 }
3229
3230 NTSTATUS
3231 USB_BUSIFFN
3232 USBHI_ControllerSelectiveSuspend(
3233 PVOID BusContext,
3234 BOOLEAN Enable)
3235 {
3236 UNIMPLEMENTED
3237 return STATUS_NOT_IMPLEMENTED;
3238 }
3239
3240 NTSTATUS
3241 USB_BUSIFFN
3242 USBHI_GetExtendedHubInformation(
3243 PVOID BusContext,
3244 PDEVICE_OBJECT HubPhysicalDeviceObject,
3245 PVOID HubInformationBuffer,
3246 ULONG HubInformationBufferLength,
3247 PULONG LengthReturned)
3248 {
3249 PUSB_EXTHUB_INFORMATION_0 HubInfo;
3250 CHubController * Controller;
3251 PUSBHARDWAREDEVICE Hardware;
3252 ULONG Index;
3253 ULONG NumPort, Dummy2;
3254 USHORT Dummy1;
3255 NTSTATUS Status;
3256
3257 DPRINT1("USBHI_GetExtendedHubInformation\n");
3258
3259 //
3260 // sanity checks
3261 //
3262 PC_ASSERT(HubInformationBuffer);
3263 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
3264 PC_ASSERT(LengthReturned);
3265
3266 //
3267 // get hub controller
3268 //
3269 Controller = (CHubController *)BusContext;
3270 PC_ASSERT(Controller);
3271
3272 //
3273 // get usb hardware device
3274 //
3275 Hardware = Controller->GetUsbHardware();
3276
3277 //
3278 // retrieve number of ports
3279 //
3280 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
3281 if (!NT_SUCCESS(Status))
3282 {
3283 //
3284 // failed to get hardware details, ouch ;)
3285 //
3286 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
3287 return Status;
3288 }
3289
3290 //
3291 // get hub information buffer
3292 //
3293 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
3294
3295 //
3296 // initialize hub information
3297 //
3298 HubInfo->InformationLevel = 0;
3299
3300 //
3301 // store port count
3302 //
3303 HubInfo->NumberOfPorts = NumPort;
3304
3305 //
3306 // initialize port information
3307 //
3308 for(Index = 0; Index < NumPort; Index++)
3309 {
3310 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
3311 HubInfo->Port[Index].PortLabelNumber = Index + 1;
3312 HubInfo->Port[Index].VidOverride = 0;
3313 HubInfo->Port[Index].PidOverride = 0;
3314 HubInfo->Port[Index].PortAttributes = USB_PORTATTR_SHARED_USB2; //FIXME
3315 }
3316
3317 //
3318 // store result length
3319 //
3320 #ifdef _MSC_VER
3321 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
3322 #else
3323 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
3324 #endif
3325
3326 //
3327 // done
3328 //
3329 return STATUS_SUCCESS;
3330 }
3331
3332 NTSTATUS
3333 USB_BUSIFFN
3334 USBHI_GetRootHubSymbolicName(
3335 PVOID BusContext,
3336 PVOID HubSymNameBuffer,
3337 ULONG HubSymNameBufferLength,
3338 PULONG HubSymNameActualLength)
3339 {
3340 UNIMPLEMENTED
3341 return STATUS_NOT_IMPLEMENTED;
3342 }
3343
3344 PVOID
3345 USB_BUSIFFN
3346 USBHI_GetDeviceBusContext(
3347 PVOID HubBusContext,
3348 PVOID DeviceHandle)
3349 {
3350 UNIMPLEMENTED
3351 return NULL;
3352 }
3353
3354 NTSTATUS
3355 USB_BUSIFFN
3356 USBHI_Initialize20Hub(
3357 PVOID BusContext,
3358 PUSB_DEVICE_HANDLE HubDeviceHandle,
3359 ULONG TtCount)
3360 {
3361 DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle, TtCount);
3362 return STATUS_SUCCESS;
3363 }
3364
3365 NTSTATUS
3366 USB_BUSIFFN
3367 USBHI_RootHubInitNotification(
3368 PVOID BusContext,
3369 PVOID CallbackContext,
3370 PRH_INIT_CALLBACK CallbackRoutine)
3371 {
3372 CHubController * Controller;
3373
3374 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
3375
3376 //
3377 // get controller object
3378 //
3379 Controller = (CHubController*)BusContext;
3380 PC_ASSERT(Controller);
3381
3382 //
3383 // set notification routine
3384 //
3385 Controller->SetNotification(CallbackContext, CallbackRoutine);
3386
3387 //
3388 // FIXME: determine when to perform callback
3389 //
3390 CallbackRoutine(CallbackContext);
3391
3392 //
3393 // done
3394 //
3395 return STATUS_SUCCESS;
3396 }
3397
3398 VOID
3399 USB_BUSIFFN
3400 USBHI_FlushTransfers(
3401 PVOID BusContext,
3402 PVOID DeviceHandle)
3403 {
3404 UNIMPLEMENTED
3405 }
3406
3407 VOID
3408 USB_BUSIFFN
3409 USBHI_SetDeviceHandleData(
3410 PVOID BusContext,
3411 PVOID DeviceHandle,
3412 PDEVICE_OBJECT UsbDevicePdo)
3413 {
3414 PUSBDEVICE UsbDevice;
3415 CHubController * Controller;
3416
3417 //
3418 // get controller
3419 //
3420 Controller = (CHubController *)BusContext;
3421 PC_ASSERT(Controller);
3422
3423 //
3424 // get device handle
3425 //
3426 UsbDevice = (PUSBDEVICE)DeviceHandle;
3427
3428 //
3429 // validate device handle
3430 //
3431 if (!Controller->ValidateUsbDevice(UsbDevice))
3432 {
3433 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
3434
3435 //
3436 // invalid handle
3437 //
3438 return;
3439 }
3440 else
3441 {
3442 //
3443 // usbhub sends this request as a part of the Pnp startup sequence
3444 // looks like we need apply a dragon voodoo to fixup the device stack
3445 // otherwise usbhub will cause a bugcheck
3446 //
3447 DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo);
3448
3449 //
3450 // sanity check
3451 //
3452 PC_ASSERT(UsbDevicePdo->AttachedDevice);
3453
3454 //
3455 // should be usbstor
3456 // fixup device stack voodoo part #2
3457 //
3458 UsbDevicePdo->AttachedDevice->StackSize++;
3459
3460 //
3461 // set device handle data
3462 //
3463 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
3464 }
3465 }
3466
3467 //=================================================================================================
3468 //
3469 // USB Device Interface functions
3470 //
3471
3472 VOID
3473 USB_BUSIFFN
3474 USBDI_GetUSBDIVersion(
3475 PVOID BusContext,
3476 PUSBD_VERSION_INFORMATION VersionInformation,
3477 PULONG HcdCapabilites)
3478 {
3479 CHubController * Controller;
3480 PUSBHARDWAREDEVICE Device;
3481 ULONG Speed, Dummy2;
3482 USHORT Dummy1;
3483
3484 DPRINT1("USBDI_GetUSBDIVersion\n");
3485
3486 //
3487 // get controller
3488 //
3489 Controller = (CHubController*)BusContext;
3490
3491 //
3492 // get usb hardware
3493 //
3494 Device = Controller->GetUsbHardware();
3495 PC_ASSERT(Device);
3496
3497 if (VersionInformation)
3498 {
3499 //
3500 // windows xp supported
3501 //
3502 VersionInformation->USBDI_Version = 0x00000500;
3503
3504 //
3505 // get device speed
3506 //
3507 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3508
3509 //
3510 // store speed details
3511 //
3512 VersionInformation->Supported_USB_Version = Speed;
3513 }
3514
3515 //
3516 // no flags supported
3517 //
3518 *HcdCapabilites = 0;
3519 }
3520
3521 NTSTATUS
3522 USB_BUSIFFN
3523 USBDI_QueryBusTime(
3524 PVOID BusContext,
3525 PULONG CurrentFrame)
3526 {
3527 UNIMPLEMENTED
3528 return STATUS_NOT_IMPLEMENTED;
3529 }
3530
3531 NTSTATUS
3532 USB_BUSIFFN
3533 USBDI_SubmitIsoOutUrb(
3534 PVOID BusContext,
3535 PURB Urb)
3536 {
3537 UNIMPLEMENTED
3538 return STATUS_NOT_IMPLEMENTED;
3539 }
3540
3541 NTSTATUS
3542 USB_BUSIFFN
3543 USBDI_QueryBusInformation(
3544 PVOID BusContext,
3545 ULONG Level,
3546 PVOID BusInformationBuffer,
3547 PULONG BusInformationBufferLength,
3548 PULONG BusInformationActualLength)
3549 {
3550 UNIMPLEMENTED
3551 return STATUS_NOT_IMPLEMENTED;
3552 }
3553
3554 BOOLEAN
3555 USB_BUSIFFN
3556 USBDI_IsDeviceHighSpeed(
3557 PVOID BusContext)
3558 {
3559 CHubController * Controller;
3560 PUSBHARDWAREDEVICE Device;
3561 ULONG Speed, Dummy2;
3562 USHORT Dummy1;
3563
3564 DPRINT1("USBDI_IsDeviceHighSpeed\n");
3565
3566 //
3567 // get controller
3568 //
3569 Controller = (CHubController*)BusContext;
3570
3571 //
3572 // get usb hardware
3573 //
3574 Device = Controller->GetUsbHardware();
3575 PC_ASSERT(Device);
3576
3577 //
3578 // get device speed
3579 //
3580 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3581
3582 //
3583 // USB 2.0 equals 0x200
3584 //
3585 return (Speed == 0x200);
3586 }
3587
3588 NTSTATUS
3589 USB_BUSIFFN
3590 USBDI_EnumLogEntry(
3591 PVOID BusContext,
3592 ULONG DriverTag,
3593 ULONG EnumTag,
3594 ULONG P1,
3595 ULONG P2)
3596 {
3597 UNIMPLEMENTED
3598 return STATUS_NOT_IMPLEMENTED;
3599 }
3600
3601 NTSTATUS
3602 CHubController::HandleQueryInterface(
3603 PIO_STACK_LOCATION IoStack)
3604 {
3605 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
3606 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
3607 UNICODE_STRING GuidBuffer;
3608 NTSTATUS Status;
3609
3610 if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
3611 {
3612 //
3613 // get request parameters
3614 //
3615 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
3616 InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
3617
3618 //
3619 // check version
3620 //
3621 if (IoStack->Parameters.QueryInterface.Version >= 6)
3622 {
3623 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3624
3625 //
3626 // version not supported
3627 //
3628 return STATUS_NOT_SUPPORTED;
3629 }
3630
3631 //
3632 // Interface version 0
3633 //
3634 if (IoStack->Parameters.QueryInterface.Version >= 0)
3635 {
3636 InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
3637 InterfaceHub->BusContext = PVOID(this);
3638 InterfaceHub->InterfaceReference = USBI_InterfaceReference;
3639 InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
3640 }
3641
3642 //
3643 // Interface version 1
3644 //
3645 if (IoStack->Parameters.QueryInterface.Version >= 1)
3646 {
3647 InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
3648 InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
3649 InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
3650 InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
3651 InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
3652 InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
3653 }
3654
3655 //
3656 // Interface version 2
3657 //
3658 if (IoStack->Parameters.QueryInterface.Version >= 2)
3659 {
3660 InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
3661 InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
3662 InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
3663 InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
3664 InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
3665 InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
3666
3667 }
3668
3669 //
3670 // Interface version 3
3671 //
3672 if (IoStack->Parameters.QueryInterface.Version >= 3)
3673 {
3674 InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
3675 }
3676
3677 //
3678 // Interface version 4
3679 //
3680 if (IoStack->Parameters.QueryInterface.Version >= 4)
3681 {
3682 InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
3683 }
3684
3685 //
3686 // Interface version 5
3687 //
3688 if (IoStack->Parameters.QueryInterface.Version >= 5)
3689 {
3690 InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
3691 }
3692
3693 //
3694 // request completed
3695 //
3696 return STATUS_SUCCESS;
3697 }
3698 else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
3699 {
3700 //
3701 // get request parameters
3702 //
3703 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
3704 InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
3705
3706 //
3707 // check version
3708 //
3709 if (IoStack->Parameters.QueryInterface.Version >= 3)
3710 {
3711 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
3712
3713 //
3714 // version not supported
3715 //
3716 return STATUS_NOT_SUPPORTED;
3717 }
3718
3719 //
3720 // interface version 0
3721 //
3722 if (IoStack->Parameters.QueryInterface.Version >= 0)
3723 {
3724 InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
3725 InterfaceDI->BusContext = PVOID(this);
3726 InterfaceDI->InterfaceReference = USBI_InterfaceReference;
3727 InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
3728 InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
3729 InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
3730 InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
3731 InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
3732 }
3733
3734 //
3735 // interface version 1
3736 //
3737 if (IoStack->Parameters.QueryInterface.Version >= 1)
3738 {
3739 InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
3740 }
3741
3742 //
3743 // interface version 2
3744 //
3745 if (IoStack->Parameters.QueryInterface.Version >= 2)
3746 {
3747 InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
3748 }
3749
3750 //
3751 // request completed
3752 //
3753 return STATUS_SUCCESS;
3754 }
3755 else
3756 {
3757 //
3758 // convert guid to string
3759 //
3760 Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
3761 if (NT_SUCCESS(Status))
3762 {
3763 //
3764 // print interface
3765 //
3766 DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
3767
3768 //
3769 // free guid buffer
3770 //
3771 RtlFreeUnicodeString(&GuidBuffer);
3772 }
3773 }
3774 return STATUS_NOT_SUPPORTED;
3775 }
3776
3777 NTSTATUS
3778 CHubController::SetDeviceInterface(
3779 BOOLEAN Enable)
3780 {
3781 NTSTATUS Status = STATUS_SUCCESS;
3782
3783 if (Enable)
3784 {
3785 //
3786 // register device interface
3787 //
3788 Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
3789
3790 if (NT_SUCCESS(Status))
3791 {
3792 //
3793 // now enable the device interface
3794 //
3795 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
3796
3797 //
3798 // enable interface
3799 //
3800 m_InterfaceEnabled = TRUE;
3801 }
3802 }
3803 else if (m_InterfaceEnabled)
3804 {
3805 //
3806 // disable device interface
3807 //
3808 Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
3809
3810 if (NT_SUCCESS(Status))
3811 {
3812 //
3813 // now delete interface string
3814 //
3815 RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
3816 }
3817
3818 //
3819 // disable interface
3820 //
3821 m_InterfaceEnabled = FALSE;
3822 }
3823
3824 //
3825 // done
3826 //
3827 return STATUS_SUCCESS;
3828 }
3829
3830 NTSTATUS
3831 CHubController::CreatePDO(
3832 PDRIVER_OBJECT DriverObject,
3833 PDEVICE_OBJECT * OutDeviceObject)
3834 {
3835 WCHAR CharDeviceName[64];
3836 NTSTATUS Status;
3837 ULONG UsbDeviceNumber = 0;
3838 UNICODE_STRING DeviceName;
3839
3840 while (TRUE)
3841 {
3842 //
3843 // construct device name
3844 //
3845 swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
3846
3847 //
3848 // initialize device name
3849 //
3850 RtlInitUnicodeString(&DeviceName, CharDeviceName);
3851
3852 //
3853 // create device
3854 //
3855 Status = IoCreateDevice(DriverObject,
3856 sizeof(COMMON_DEVICE_EXTENSION),
3857 &DeviceName,
3858 FILE_DEVICE_CONTROLLER,
3859 0,
3860 FALSE,
3861 OutDeviceObject);
3862
3863 /* check for success */
3864 if (NT_SUCCESS(Status))
3865 break;
3866
3867 //
3868 // is there a device object with that same name
3869 //
3870 if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
3871 {
3872 //
3873 // Try the next name
3874 //
3875 UsbDeviceNumber++;
3876 continue;
3877 }
3878
3879 //
3880 // bail out on other errors
3881 //
3882 if (!NT_SUCCESS(Status))
3883 {
3884 DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
3885 return Status;
3886 }
3887 }
3888
3889 DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
3890
3891 //
3892 // fixup device stack voodoo part #1
3893 //
3894 (*OutDeviceObject)->StackSize++;
3895
3896 /* done */
3897 return Status;
3898 }
3899
3900
3901
3902 NTSTATUS
3903 NTAPI
3904 CreateHubController(
3905 PHUBCONTROLLER *OutHcdController)
3906 {
3907 PHUBCONTROLLER This;
3908
3909 //
3910 // allocate controller
3911 //
3912 This = new(NonPagedPool, TAG_USBLIB) CHubController(0);
3913 if (!This)
3914 {
3915 //
3916 // failed to allocate
3917 //
3918 return STATUS_INSUFFICIENT_RESOURCES;
3919 }
3920
3921 //
3922 // add reference count
3923 //
3924 This->AddRef();
3925
3926 //
3927 // return result
3928 //
3929 *OutHcdController = (PHUBCONTROLLER)This;
3930
3931 //
3932 // done
3933 //
3934 return STATUS_SUCCESS;
3935 }
3936
3937 VOID StatusChangeEndpointCallBack(PVOID Context)
3938 {
3939 CHubController* This;
3940 PIRP Irp;
3941 This = (CHubController*)Context;
3942
3943 ASSERT(This);
3944
3945 Irp = This->m_PendingSCEIrp;
3946 if (!Irp)
3947 {
3948 DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
3949 return;
3950 }
3951
3952 This->m_PendingSCEIrp = NULL;
3953 This->QueryStatusChageEndpoint(Irp);
3954
3955 Irp->IoStatus.Status = STATUS_SUCCESS;
3956 Irp->IoStatus.Information = 0;
3957
3958 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3959 }