[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 NTSTATUS Status;
1048
1049 //
1050 // is the request for the Root Hub
1051 //
1052 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1053 {
1054 //
1055 // FIXME: support setting device to unconfigured state
1056 //
1057 PC_ASSERT(Urb->UrbSelectConfiguration.ConfigurationDescriptor);
1058
1059 //
1060 // set device handle
1061 //
1062 Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&ROOTHUB2_CONFIGURATION_DESCRIPTOR;
1063
1064 //
1065 // copy interface info
1066 //
1067 InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
1068
1069 InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&ROOTHUB2_INTERFACE_DESCRIPTOR;
1070 InterfaceInfo->Class = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceClass;
1071 InterfaceInfo->SubClass = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceSubClass;
1072 InterfaceInfo->Protocol = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceProtocol;
1073 InterfaceInfo->Reserved = 0;
1074
1075 //
1076 // sanity check
1077 //
1078 PC_ASSERT(InterfaceInfo->NumberOfPipes == 1);
1079
1080 //
1081 // copy pipe info
1082 //
1083 InterfaceInfo->Pipes[0].MaximumPacketSize = ROOTHUB2_ENDPOINT_DESCRIPTOR.wMaxPacketSize;
1084 InterfaceInfo->Pipes[0].EndpointAddress = ROOTHUB2_ENDPOINT_DESCRIPTOR.bEndpointAddress;
1085 InterfaceInfo->Pipes[0].Interval = ROOTHUB2_ENDPOINT_DESCRIPTOR.bInterval;
1086 InterfaceInfo->Pipes[0].PipeType = (USBD_PIPE_TYPE)(ROOTHUB2_ENDPOINT_DESCRIPTOR.bmAttributes & USB_ENDPOINT_TYPE_MASK);
1087 InterfaceInfo->Pipes[0].PipeHandle = (PVOID)&ROOTHUB2_ENDPOINT_DESCRIPTOR;
1088
1089 return STATUS_SUCCESS;
1090 }
1091 else
1092 {
1093 //
1094 // check if this is a valid usb device handle
1095 //
1096 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1097 {
1098 DPRINT1("[USBLIB] HandleSelectConfiguration invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1099
1100 //
1101 // invalid device handle
1102 //
1103 return STATUS_DEVICE_NOT_CONNECTED;
1104 }
1105
1106 //
1107 // get device
1108 //
1109 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1110
1111 //
1112 // select configuration
1113 //
1114 Status = UsbDevice->SelectConfiguration(Urb->UrbSelectConfiguration.ConfigurationDescriptor, &Urb->UrbSelectConfiguration.Interface, &Urb->UrbSelectConfiguration.ConfigurationHandle);
1115 if (NT_SUCCESS(Status))
1116 {
1117 // successfully configured device
1118 Urb->UrbSelectConfiguration.Hdr.Status = USBD_STATUS_SUCCESS;
1119 }
1120 return Status;
1121 }
1122 }
1123
1124 //-----------------------------------------------------------------------------------------
1125 NTSTATUS
1126 CHubController::HandleSelectInterface(
1127 IN OUT PIRP Irp,
1128 PURB Urb)
1129 {
1130 PUSBDEVICE UsbDevice;
1131
1132 //
1133 // sanity check
1134 //
1135 PC_ASSERT(Urb->UrbSelectInterface.ConfigurationHandle);
1136
1137 //
1138 // is the request for the Root Hub
1139 //
1140 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1141 {
1142 //
1143 // no op for root hub
1144 //
1145 return STATUS_SUCCESS;
1146 }
1147 else
1148 {
1149 //
1150 // check if this is a valid usb device handle
1151 //
1152 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1153 {
1154 DPRINT1("[USBLIB] HandleSelectInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1155
1156 //
1157 // invalid device handle
1158 //
1159 return STATUS_DEVICE_NOT_CONNECTED;
1160 }
1161
1162 //
1163 // get device
1164 //
1165 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1166
1167 //
1168 // select interface
1169 //
1170 return UsbDevice->SelectInterface(Urb->UrbSelectInterface.ConfigurationHandle, &Urb->UrbSelectInterface.Interface);
1171 }
1172 }
1173
1174 //-----------------------------------------------------------------------------------------
1175 NTSTATUS
1176 CHubController::HandleGetStatusFromDevice(
1177 IN OUT PIRP Irp,
1178 PURB Urb)
1179 {
1180 PUSHORT DeviceStatus;
1181 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1182 NTSTATUS Status;
1183 PUSBDEVICE UsbDevice;
1184
1185 //
1186 // sanity checks
1187 //
1188 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
1189 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
1190
1191 //
1192 // get status buffer
1193 //
1194 DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
1195
1196
1197 if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this))
1198 {
1199 //
1200 // FIXME need more flags ?
1201 //
1202 *DeviceStatus = USB_PORT_STATUS_CONNECT;
1203 return STATUS_SUCCESS;
1204 }
1205
1206 //
1207 // check if this is a valid usb device handle
1208 //
1209 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1210 {
1211 DPRINT1("[USBLIB] HandleGetStatusFromDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1212
1213 //
1214 // invalid device handle
1215 //
1216 return STATUS_DEVICE_NOT_CONNECTED;
1217 }
1218
1219 //
1220 // get device
1221 //
1222 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1223
1224
1225 //
1226 // generate setup packet
1227 //
1228 CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
1229 CtrlSetup.wValue.LowByte = 0;
1230 CtrlSetup.wValue.HiByte = 0;
1231 CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1232 CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
1233 CtrlSetup.bmRequestType.B = 0x80;
1234
1235 if (Urb->UrbHeader.Function == URB_FUNCTION_GET_STATUS_FROM_INTERFACE)
1236 {
1237 //
1238 // add interface type
1239 //
1240 CtrlSetup.bmRequestType.B |= 0x01;
1241 }
1242 else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_STATUS_FROM_ENDPOINT)
1243 {
1244 //
1245 // add interface type
1246 //
1247 CtrlSetup.bmRequestType.B |= 0x02;
1248 }
1249
1250 //
1251 // submit setup packet
1252 //
1253 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1254 ASSERT(Status == STATUS_SUCCESS);
1255 DPRINT1("[USBLIB] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
1256
1257 //
1258 // done
1259 //
1260 return Status;
1261 }
1262
1263 //-----------------------------------------------------------------------------------------
1264 NTSTATUS
1265 CHubController::HandleClassDevice(
1266 IN OUT PIRP Irp,
1267 IN OUT PURB Urb)
1268 {
1269 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1270 PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
1271 ULONG PortCount, Dummy2;
1272 USHORT Dummy1;
1273 PUSBDEVICE UsbDevice;
1274 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1275
1276 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
1277
1278 //
1279 // check class request type
1280 //
1281 switch(Urb->UrbControlVendorClassRequest.Request)
1282 {
1283 case USB_REQUEST_GET_STATUS:
1284 {
1285 //
1286 // check if this is a valid usb device handle
1287 //
1288 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1289 {
1290 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1291
1292 //
1293 // invalid device handle
1294 //
1295 return STATUS_DEVICE_NOT_CONNECTED;
1296 }
1297
1298 //
1299 // get device
1300 //
1301 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1302
1303
1304 //
1305 // generate setup packet
1306 //
1307 CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
1308 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1309 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1310 CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
1311 CtrlSetup.bmRequestType.B = 0xA0;
1312
1313 //
1314 // submit setup packet
1315 //
1316 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1317 ASSERT(Status == STATUS_SUCCESS);
1318 break;
1319 }
1320 case USB_REQUEST_GET_DESCRIPTOR:
1321 {
1322 switch (Urb->UrbControlVendorClassRequest.Value >> 8)
1323 {
1324 case USB_DEVICE_CLASS_RESERVED: // FALL THROUGH
1325 case USB_DEVICE_CLASS_HUB:
1326 {
1327 if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this))
1328 {
1329 //
1330 // sanity checks
1331 //
1332 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1333 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR));
1334
1335 //
1336 // get hub descriptor
1337 //
1338 UsbHubDescriptor = (PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer;
1339
1340 //
1341 // one hub is handled
1342 //
1343 UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
1344 Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR);
1345
1346 //
1347 // type should 0x29 according to msdn
1348 //
1349 UsbHubDescriptor->bDescriptorType = 0x29;
1350
1351 //
1352 // get port count
1353 //
1354 Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &PortCount, &Dummy2);
1355 PC_ASSERT(Status == STATUS_SUCCESS);
1356
1357 //
1358 // FIXME: retrieve values
1359 //
1360 UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount;
1361 UsbHubDescriptor->wHubCharacteristics = 0x00;
1362 UsbHubDescriptor->bPowerOnToPowerGood = 0x01;
1363 UsbHubDescriptor->bHubControlCurrent = 0x00;
1364
1365 //
1366 // done
1367 //
1368 Status = STATUS_SUCCESS;
1369 }
1370 else
1371 {
1372 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1373 {
1374 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1375 //
1376 // invalid device handle
1377 //
1378 return STATUS_DEVICE_NOT_CONNECTED;
1379 }
1380
1381 //
1382 // FIXME: implement support for real hubs
1383 //
1384 UNIMPLEMENTED
1385 Status = STATUS_NOT_IMPLEMENTED;
1386 }
1387 break;
1388 }
1389 default:
1390 DPRINT1("[USBLIB] HandleClassDevice Class %x not implemented\n", Urb->UrbControlVendorClassRequest.Value >> 8);
1391 break;
1392 }
1393 break;
1394 }
1395 default:
1396 {
1397 //
1398 // check if this is a valid usb device handle
1399 //
1400 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1401 {
1402 DPRINT1("HandleClassDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1403
1404 //
1405 // invalid device handle
1406 //
1407 return STATUS_DEVICE_NOT_CONNECTED;
1408 }
1409
1410 //
1411 // get device
1412 //
1413 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1414
1415 //
1416 // generate setup packet
1417 //
1418 CtrlSetup.bmRequestType.B = 0;
1419 CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
1420 CtrlSetup.bmRequestType._BM.Type = BMREQUEST_CLASS;
1421 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1422 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1423 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1424 CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength;
1425
1426 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1427 {
1428 //
1429 // data direction is device to host
1430 //
1431 CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
1432 }
1433
1434 //
1435 // submit setup packet
1436 //
1437 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1438 ASSERT(Status == STATUS_SUCCESS);
1439
1440 break;
1441 }
1442 }
1443
1444 return Status;
1445 }
1446
1447 //-----------------------------------------------------------------------------------------
1448 NTSTATUS
1449 CHubController::HandleGetDescriptorFromInterface(
1450 IN OUT PIRP Irp,
1451 IN OUT PURB Urb)
1452 {
1453 PUSBDEVICE UsbDevice;
1454 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1455 NTSTATUS Status;
1456
1457 //
1458 // sanity check
1459 //
1460 ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
1461 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1462
1463 //
1464 // check if this is a valid usb device handle
1465 //
1466 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1467 {
1468 DPRINT1("[USBLIB] HandleGetDescriptorFromInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1469
1470 //
1471 // invalid device handle
1472 //
1473 return STATUS_DEVICE_NOT_CONNECTED;
1474 }
1475
1476 //
1477 // get device
1478 //
1479 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1480
1481 //
1482 // generate setup packet
1483 //
1484 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1485 CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1486 CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1487 CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1488 CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1489 CtrlSetup.bmRequestType.B = 0x81;
1490
1491 //
1492 // submit setup packet
1493 //
1494 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1495 if (!NT_SUCCESS(Status))
1496 {
1497 DPRINT1("[USBLIB] HandleGetDescriptorFromInterface failed with %x\n", Status);
1498 }
1499
1500 //
1501 // done
1502 //
1503 return Status;
1504 }
1505
1506 //-----------------------------------------------------------------------------------------
1507 NTSTATUS
1508 CHubController::HandleGetDescriptor(
1509 IN OUT PIRP Irp,
1510 IN OUT PURB Urb)
1511 {
1512 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1513 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1514 PUCHAR Buffer;
1515 PUSBDEVICE UsbDevice;
1516 ULONG Length, BufferLength;
1517
1518 DPRINT("[USBLIB] HandleGetDescriptor Type %x\n", Urb->UrbControlDescriptorRequest.DescriptorType);
1519
1520 //
1521 // check descriptor type
1522 //
1523 switch(Urb->UrbControlDescriptorRequest.DescriptorType)
1524 {
1525 case USB_DEVICE_DESCRIPTOR_TYPE:
1526 {
1527 //
1528 // sanity check
1529 //
1530 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1531 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1532
1533 if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this))
1534 {
1535 //
1536 // copy root hub device descriptor
1537 //
1538 RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
1539 Irp->IoStatus.Information = sizeof(USB_DEVICE_DESCRIPTOR);
1540 Urb->UrbControlDescriptorRequest.Hdr.Status = USBD_STATUS_SUCCESS;
1541 Status = STATUS_SUCCESS;
1542 }
1543 else
1544 {
1545 //
1546 // check if this is a valid usb device handle
1547 //
1548 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1549 {
1550 DPRINT1("[USBLIB] HandleGetDescriptor invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1551
1552 //
1553 // invalid device handle
1554 //
1555 return STATUS_DEVICE_NOT_CONNECTED;
1556 }
1557
1558 //
1559 // get device
1560 //
1561 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1562
1563 //
1564 // retrieve device descriptor from device
1565 //
1566 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
1567 Irp->IoStatus.Information = sizeof(USB_DEVICE_DESCRIPTOR);
1568 Urb->UrbControlDescriptorRequest.Hdr.Status = USBD_STATUS_SUCCESS;
1569 Status = STATUS_SUCCESS;
1570 }
1571 break;
1572 }
1573 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
1574 {
1575 //
1576 // sanity checks
1577 //
1578 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1579 //
1580 // From MSDN
1581 // The caller must allocate a buffer large enough to hold all of this information or the data is truncated without error.
1582 //
1583 BufferLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
1584 Buffer = (PUCHAR) Urb->UrbControlDescriptorRequest.TransferBuffer;
1585
1586 if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this))
1587 {
1588 //
1589 // request is for the root bus controller
1590 //
1591 Length = BufferLength > sizeof(USB_CONFIGURATION_DESCRIPTOR) ?
1592 sizeof(USB_CONFIGURATION_DESCRIPTOR) : BufferLength;
1593 RtlCopyMemory(Buffer, &ROOTHUB2_CONFIGURATION_DESCRIPTOR, Length);
1594
1595 //
1596 // Check if we still have some space left
1597 //
1598 if(Length == BufferLength)
1599 {
1600 //
1601 // We copied all we could
1602 //
1603 Status = STATUS_SUCCESS;
1604 break;
1605 }
1606 //
1607 // Go further
1608 //
1609 Buffer += Length;
1610 BufferLength -= Length;
1611
1612 //
1613 // copy interface descriptor template
1614 //
1615 Length = BufferLength > sizeof(USB_INTERFACE_DESCRIPTOR) ?
1616 sizeof(USB_INTERFACE_DESCRIPTOR) : BufferLength;
1617 RtlCopyMemory(Buffer, &ROOTHUB2_INTERFACE_DESCRIPTOR, Length);
1618
1619 //
1620 // Check if we still have some space left
1621 //
1622 if(Length == BufferLength)
1623 {
1624 //
1625 // We copied all we could
1626 //
1627 Status = STATUS_SUCCESS;
1628 break;
1629 }
1630 //
1631 // Go further
1632 //
1633 Buffer += Length;
1634 BufferLength -= Length;
1635
1636
1637 //
1638 // copy end point descriptor template
1639 //
1640 Length = BufferLength > sizeof(USB_ENDPOINT_DESCRIPTOR) ?
1641 sizeof(USB_ENDPOINT_DESCRIPTOR) : BufferLength;
1642 RtlCopyMemory(Buffer, &ROOTHUB2_ENDPOINT_DESCRIPTOR, Length);
1643
1644 //
1645 // done
1646 //
1647 Status = STATUS_SUCCESS;
1648
1649 }
1650 else
1651 {
1652 //
1653 // check if this is a valid usb device handle
1654 //
1655 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1656 {
1657 DPRINT1("[USBLIB] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1658
1659 //
1660 // invalid device handle
1661 //
1662 return STATUS_DEVICE_NOT_CONNECTED;
1663 }
1664
1665 //
1666 // get device
1667 //
1668 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1669
1670 //
1671 // Allocate temporary buffer
1672 //
1673 BufferLength = UsbDevice->GetConfigurationDescriptorsLength();
1674 Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, BufferLength, TAG_USBLIB);
1675 if(!Buffer)
1676 {
1677 Status = STATUS_NO_MEMORY;
1678 break;
1679 }
1680
1681 //
1682 // perform work in IUSBDevice
1683 //
1684 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)Buffer, BufferLength, &Length);
1685
1686 //
1687 // Copy what we can
1688 //
1689 Length = Urb->UrbControlDescriptorRequest.TransferBufferLength > Length ?
1690 Length : Urb->UrbControlDescriptorRequest.TransferBufferLength;
1691 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, Length);
1692
1693 //
1694 // Free temporary buffer
1695 //
1696 ExFreePoolWithTag(Buffer, TAG_USBLIB);
1697
1698 //
1699 // store result size
1700 //
1701 Irp->IoStatus.Information = Length;
1702 Urb->UrbControlDescriptorRequest.TransferBufferLength = Length;
1703 Urb->UrbControlDescriptorRequest.Hdr.Status = USBD_STATUS_SUCCESS;
1704 Status = STATUS_SUCCESS;
1705 }
1706 break;
1707 }
1708 case USB_STRING_DESCRIPTOR_TYPE:
1709 {
1710 //
1711 // sanity check
1712 //
1713 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1714 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
1715
1716
1717 //
1718 // check if this is a valid usb device handle
1719 //
1720 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1721 {
1722 DPRINT1("[USBLIB] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1723
1724 //
1725 // invalid device handle
1726 //
1727 return STATUS_DEVICE_NOT_CONNECTED;
1728 }
1729
1730 //
1731 // get device
1732 //
1733 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1734
1735 //
1736 // generate setup packet
1737 //
1738 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1739 CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1740 CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1741 CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1742 CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1743 CtrlSetup.bmRequestType.B = 0x80;
1744
1745 //
1746 // submit setup packet
1747 //
1748 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1749 break;
1750 }
1751 default:
1752 DPRINT1("[USBLIB] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb->UrbControlDescriptorRequest.DescriptorType);
1753 break;
1754 }
1755
1756 //
1757 // done
1758 //
1759 return Status;
1760 }
1761
1762 //-----------------------------------------------------------------------------------------
1763 NTSTATUS
1764 CHubController::HandleClassEndpoint(
1765 IN OUT PIRP Irp,
1766 IN OUT PURB Urb)
1767 {
1768 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1769 NTSTATUS Status;
1770 PUSBDEVICE UsbDevice;
1771
1772 //
1773 // sanity check
1774 //
1775 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1776 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1777 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1778
1779 //
1780 // check if this is a valid usb device handle
1781 //
1782 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1783 {
1784 DPRINT1("[USBLIB] HandleClassEndpoint invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1785
1786 //
1787 // invalid device handle
1788 //
1789 return STATUS_DEVICE_NOT_CONNECTED;
1790 }
1791
1792 //
1793 // get device
1794 //
1795 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1796
1797
1798 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1799 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
1800 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
1801 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
1802 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1803 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
1804 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1805 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
1806 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
1807
1808 //
1809 // initialize setup packet
1810 //
1811 CtrlSetup.bmRequestType.B = 0x22; //FIXME: Const.
1812 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1813 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1814 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1815 CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength;
1816
1817 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1818 {
1819 //
1820 // data direction is device to host
1821 //
1822 CtrlSetup.bmRequestType.B |= 0x80;
1823 }
1824
1825
1826 //
1827 // issue request
1828 //
1829 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1830
1831 //
1832 // assert on failure
1833 //
1834 PC_ASSERT(NT_SUCCESS(Status));
1835
1836
1837 //
1838 // done
1839 //
1840 return Status;
1841 }
1842
1843 //-----------------------------------------------------------------------------------------
1844 NTSTATUS
1845 CHubController::HandleVendorDevice(
1846 IN OUT PIRP Irp,
1847 IN OUT PURB Urb)
1848 {
1849 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1850 PUSBDEVICE UsbDevice;
1851 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1852
1853 //DPRINT("CHubController::HandleVendorDevice Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1854
1855 //
1856 // sanity check
1857 //
1858 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1859
1860 //
1861 // check if this is a valid usb device handle
1862 //
1863 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1864 {
1865 DPRINT1("[USBLIB] HandleVendorDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1866
1867 //
1868 // invalid device handle
1869 //
1870 return STATUS_DEVICE_NOT_CONNECTED;
1871 }
1872
1873 //
1874 // get device
1875 //
1876 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1877
1878 //
1879 // initialize setup packet
1880 //
1881 CtrlSetup.bmRequestType.B = 0;
1882 CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
1883 CtrlSetup.bmRequestType._BM.Type = BMREQUEST_VENDOR;
1884 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1885 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1886 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1887 CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength;
1888
1889 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1890 {
1891 //
1892 // data direction is device to host
1893 //
1894 CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
1895 }
1896
1897 //
1898 // issue request
1899 //
1900 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1901 if (NT_SUCCESS(Status))
1902 {
1903 // success
1904 Urb->UrbControlVendorClassRequest.Hdr.Status = USBD_STATUS_SUCCESS;
1905 Irp->IoStatus.Information = Urb->UrbControlVendorClassRequest.TransferBufferLength;
1906 }
1907
1908 return Status;
1909 }
1910
1911 //-----------------------------------------------------------------------------------------
1912 NTSTATUS
1913 CHubController::HandleSyncResetAndClearStall(
1914 IN OUT PIRP Irp,
1915 IN OUT PURB Urb)
1916 {
1917 NTSTATUS Status = STATUS_SUCCESS;
1918 PUSB_ENDPOINT EndpointDescriptor;
1919 ULONG Type;
1920
1921 //
1922 // sanity check
1923 //
1924 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1925 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1926 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1927
1928 //
1929 // check if this is a valid usb device handle
1930 //
1931 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1932 {
1933 DPRINT1("[USBLIB] HandleSyncResetAndClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1934
1935 //
1936 // invalid device handle
1937 //
1938 return STATUS_DEVICE_NOT_CONNECTED;
1939 }
1940
1941 //
1942 // abort pipe
1943 //
1944 Status = HandleAbortPipe(Irp, Urb);
1945 if (!NT_SUCCESS(Status))
1946 {
1947 //
1948 // failed
1949 //
1950 DPRINT1("[USBLIB] failed to reset pipe %x\n", Status);
1951 }
1952
1953
1954 //
1955 // get endpoint descriptor
1956 //
1957 EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbPipeRequest.PipeHandle;
1958
1959 //
1960 // get type
1961 //
1962 Type = (EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK);
1963 if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
1964 {
1965 //
1966 // clear stall
1967 //
1968 Status = HandleClearStall(Irp, Urb);
1969 }
1970 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
1971
1972 //
1973 // reset data toggle
1974 //
1975 if (NT_SUCCESS(Status))
1976 EndpointDescriptor->DataToggle = 0x0;
1977
1978 //
1979 // done
1980 //
1981 return Status;
1982 }
1983
1984 //-----------------------------------------------------------------------------------------
1985 NTSTATUS
1986 CHubController::HandleAbortPipe(
1987 IN OUT PIRP Irp,
1988 IN OUT PURB Urb)
1989 {
1990 NTSTATUS Status;
1991 PUSBDEVICE UsbDevice;
1992 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1993
1994 //
1995 // sanity check
1996 //
1997 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1998 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1999 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
2000
2001 //
2002 // check if this is a valid usb device handle
2003 //
2004 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
2005 {
2006 DPRINT1("[USBLIB] HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
2007
2008 //
2009 // invalid device handle
2010 //
2011 return STATUS_DEVICE_NOT_CONNECTED;
2012 }
2013
2014 //
2015 // get endpoint descriptor
2016 //
2017 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
2018
2019 //
2020 // get device
2021 //
2022 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
2023
2024
2025 //
2026 // issue request
2027 //
2028 Status = UsbDevice->AbortPipe(EndpointDescriptor);
2029 DPRINT1("[USBLIB] URB_FUNCTION_ABORT_PIPE Status %x\n", Status);
2030
2031 //
2032 // done
2033 //
2034 return Status;
2035 }
2036
2037
2038 //-----------------------------------------------------------------------------------------
2039 NTSTATUS
2040 CHubController::HandleClearStall(
2041 IN OUT PIRP Irp,
2042 IN OUT PURB Urb)
2043 {
2044 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
2045 NTSTATUS Status;
2046 PUSBDEVICE UsbDevice;
2047 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
2048
2049
2050 //
2051 // sanity check
2052 //
2053 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
2054 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
2055 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
2056
2057 //
2058 // check if this is a valid usb device handle
2059 //
2060 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
2061 {
2062 DPRINT1("[USBLIB] HandleClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
2063
2064 //
2065 // invalid device handle
2066 //
2067 return STATUS_DEVICE_NOT_CONNECTED;
2068 }
2069
2070 //
2071 // get endpoint descriptor
2072 //
2073 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
2074
2075 //
2076 // get device
2077 //
2078 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
2079 DPRINT1("[USBLIB] URB_FUNCTION_SYNC_CLEAR_STALL\n");
2080
2081 //
2082 // initialize setup packet
2083 //
2084 CtrlSetup.bmRequestType.B = 0x02;
2085 CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE;
2086 CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL;
2087 CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress;
2088 CtrlSetup.wLength = 0;
2089 CtrlSetup.wValue.W = 0;
2090
2091 //
2092 // issue request
2093 //
2094 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0);
2095
2096 DPRINT1("[USBLIB] URB_FUNCTION_CLEAR_STALL Status %x\n", Status);
2097
2098 //
2099 // done
2100 //
2101 return Status;
2102 }
2103
2104
2105 //-----------------------------------------------------------------------------------------
2106 NTSTATUS
2107 CHubController::HandleClassInterface(
2108 IN OUT PIRP Irp,
2109 IN OUT PURB Urb)
2110 {
2111 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
2112 NTSTATUS Status;
2113 PUSBDEVICE UsbDevice;
2114
2115 //
2116 // sanity check
2117 //
2118 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
2119 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
2120 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
2121
2122 //
2123 // check if this is a valid usb device handle
2124 //
2125 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
2126 {
2127 DPRINT1("[USBLIB] HandleClassInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
2128
2129 //
2130 // invalid device handle
2131 //
2132 return STATUS_DEVICE_NOT_CONNECTED;
2133 }
2134
2135 //
2136 // get device
2137 //
2138 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
2139
2140
2141 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
2142 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
2143 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
2144 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
2145 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
2146 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
2147 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
2148 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
2149 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
2150
2151 //
2152 // initialize setup packet
2153 //
2154 CtrlSetup.bmRequestType.B = 0x21;
2155 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
2156 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
2157 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
2158 CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength;
2159
2160 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
2161 {
2162 //
2163 // data direction is device to host
2164 //
2165 CtrlSetup.bmRequestType.B |= 0x80;
2166 }
2167
2168 //
2169 // issue request
2170 //
2171 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
2172
2173 //
2174 // assert on failure
2175 //
2176 if (!NT_SUCCESS(Status))
2177 {
2178 //
2179 // display error
2180 //
2181 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status);
2182 }
2183
2184 //
2185 // done
2186 //
2187 return Status;
2188 }
2189
2190 //-----------------------------------------------------------------------------------------
2191 NTSTATUS
2192 CHubController::HandleDeviceControl(
2193 IN PDEVICE_OBJECT DeviceObject,
2194 IN OUT PIRP Irp)
2195 {
2196 PIO_STACK_LOCATION IoStack;
2197 PCOMMON_DEVICE_EXTENSION DeviceExtension;
2198 PURB Urb;
2199 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
2200
2201 //
2202 // get current stack location
2203 //
2204 IoStack = IoGetCurrentIrpStackLocation(Irp);
2205
2206 //
2207 // get device extension
2208 //
2209 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
2210
2211 //
2212 // determine which request should be performed
2213 //
2214 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
2215 {
2216 case IOCTL_INTERNAL_USB_SUBMIT_URB:
2217 {
2218 //
2219 // get urb
2220 //
2221 Urb = (PURB)IoStack->Parameters.Others.Argument1;
2222 PC_ASSERT(Urb);
2223
2224 switch (Urb->UrbHeader.Function)
2225 {
2226 case URB_FUNCTION_SYNC_RESET_PIPE:
2227 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
2228 Status = HandleSyncResetAndClearStall(Irp, Urb);
2229 break;
2230 case URB_FUNCTION_ABORT_PIPE:
2231 Status = HandleAbortPipe(Irp, Urb);
2232 break;
2233 case URB_FUNCTION_SYNC_CLEAR_STALL:
2234 Status = HandleClearStall(Irp, Urb);
2235 break;
2236 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
2237 Status = HandleGetDescriptorFromInterface(Irp, Urb);
2238 break;
2239 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
2240 Status = HandleGetDescriptor(Irp, Urb);
2241 break;
2242 case URB_FUNCTION_CLASS_DEVICE:
2243 Status = HandleClassDevice(Irp, Urb);
2244 break;
2245 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
2246 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
2247 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
2248 Status = HandleGetStatusFromDevice(Irp, Urb);
2249 break;
2250 case URB_FUNCTION_SELECT_CONFIGURATION:
2251 Status = HandleSelectConfiguration(Irp, Urb);
2252 break;
2253 case URB_FUNCTION_SELECT_INTERFACE:
2254 Status = HandleSelectInterface(Irp, Urb);
2255 break;
2256 case URB_FUNCTION_CLASS_OTHER:
2257 Status = HandleClassOther(Irp, Urb);
2258 break;
2259 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
2260 Status = HandleBulkOrInterruptTransfer(Irp, Urb);
2261 break;
2262 case URB_FUNCTION_ISOCH_TRANSFER:
2263 Status = HandleIsochronousTransfer(Irp, Urb);
2264 break;
2265 case URB_FUNCTION_CLASS_INTERFACE:
2266 Status = HandleClassInterface(Irp, Urb);
2267 break;
2268 case URB_FUNCTION_CLASS_ENDPOINT:
2269 Status = HandleClassEndpoint(Irp, Urb);
2270 break;
2271 case URB_FUNCTION_VENDOR_DEVICE:
2272 Status = HandleVendorDevice(Irp, Urb);
2273 break;
2274 default:
2275 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
2276 break;
2277 }
2278 //
2279 // request completed
2280 //
2281 break;
2282 }
2283 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
2284 {
2285 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
2286
2287 if (IoStack->Parameters.Others.Argument1)
2288 {
2289 //
2290 // store object as device handle
2291 //
2292 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
2293 Status = STATUS_SUCCESS;
2294 }
2295 else
2296 {
2297 //
2298 // mis-behaving hub driver
2299 //
2300 Status = STATUS_INVALID_DEVICE_REQUEST;
2301 }
2302
2303 //
2304 // request completed
2305 //
2306 break;
2307 }
2308 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
2309 {
2310 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
2311
2312 //
2313 // this is the first request send, it delivers the PDO to the caller
2314 //
2315 if (IoStack->Parameters.Others.Argument1)
2316 {
2317 //
2318 // store root hub pdo object
2319 //
2320 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
2321 }
2322
2323 if (IoStack->Parameters.Others.Argument2)
2324 {
2325 //
2326 // documentation claims to deliver the hcd controller object, although it is wrong
2327 //
2328 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
2329 }
2330
2331 //
2332 // request completed
2333 //
2334 Status = STATUS_SUCCESS;
2335 break;
2336 }
2337 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
2338 {
2339 DPRINT("[USBLIB] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
2340
2341 //
2342 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2343 // requests this ioctl to deliver the number of presents.
2344
2345 if (IoStack->Parameters.Others.Argument1)
2346 {
2347 //
2348 // FIXME / verify: there is only one hub
2349 //
2350 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
2351 }
2352
2353 //
2354 // request completed
2355 //
2356 Status = STATUS_SUCCESS;
2357 Irp->IoStatus.Information = sizeof(ULONG);
2358 break;
2359 }
2360 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
2361 {
2362 DPRINT1("[USBLIB] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
2363 Status = STATUS_SUCCESS;
2364 break;
2365 }
2366 default:
2367 {
2368 DPRINT1("[USBLIB] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
2369 IoStack->Parameters.DeviceIoControl.IoControlCode,
2370 IoStack->Parameters.DeviceIoControl.InputBufferLength,
2371 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
2372 break;
2373 }
2374 }
2375 if (Status != STATUS_PENDING)
2376 {
2377 Irp->IoStatus.Status = Status;
2378 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2379 }
2380
2381 return Status;
2382 }
2383
2384 //-----------------------------------------------------------------------------------------
2385 PUSBHARDWAREDEVICE
2386 CHubController::GetUsbHardware()
2387 {
2388 return m_Hardware;
2389 }
2390
2391 //-----------------------------------------------------------------------------------------
2392 ULONG
2393 CHubController::AcquireDeviceAddress()
2394 {
2395 KIRQL OldLevel;
2396 ULONG DeviceAddress;
2397
2398 //
2399 // acquire device lock
2400 //
2401 KeAcquireSpinLock(&m_Lock, &OldLevel);
2402
2403 //
2404 // find address
2405 //
2406 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
2407 if (DeviceAddress != MAXULONG)
2408 {
2409 //
2410 // reserve address
2411 //
2412 RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2413
2414 //
2415 // device addresses start from 0x1 - 0xFF
2416 //
2417 DeviceAddress++;
2418 }
2419
2420 //
2421 // release spin lock
2422 //
2423 KeReleaseSpinLock(&m_Lock, OldLevel);
2424
2425 //
2426 // return device address
2427 //
2428 return DeviceAddress;
2429 }
2430 //-----------------------------------------------------------------------------------------
2431 VOID
2432 CHubController::ReleaseDeviceAddress(
2433 ULONG DeviceAddress)
2434 {
2435 KIRQL OldLevel;
2436
2437 //
2438 // acquire device lock
2439 //
2440 KeAcquireSpinLock(&m_Lock, &OldLevel);
2441
2442 //
2443 // sanity check
2444 //
2445 PC_ASSERT(DeviceAddress != 0);
2446
2447 //
2448 // convert back to bit number
2449 //
2450 DeviceAddress--;
2451
2452 //
2453 // clear bit
2454 //
2455 RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2456
2457 //
2458 // release lock
2459 //
2460 KeReleaseSpinLock(&m_Lock, OldLevel);
2461 }
2462 //-----------------------------------------------------------------------------------------
2463 NTSTATUS
2464 CHubController::RemoveUsbDevice(
2465 PUSBDEVICE UsbDevice)
2466 {
2467 PUSBDEVICE_ENTRY DeviceEntry;
2468 PLIST_ENTRY Entry;
2469 NTSTATUS Status = STATUS_UNSUCCESSFUL;
2470 KIRQL OldLevel;
2471
2472 //
2473 // acquire lock
2474 //
2475 KeAcquireSpinLock(&m_Lock, &OldLevel);
2476
2477 //
2478 // point to first entry
2479 //
2480 Entry = m_UsbDeviceList.Flink;
2481
2482 //
2483 // find matching entry
2484 //
2485 while(Entry != &m_UsbDeviceList)
2486 {
2487 //
2488 // get entry
2489 //
2490 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2491
2492 //
2493 // is it current entry
2494 //
2495 if (DeviceEntry->Device == UsbDevice)
2496 {
2497 //
2498 // remove entry
2499 //
2500 RemoveEntryList(Entry);
2501
2502 //
2503 // free entry
2504 //
2505 ExFreePoolWithTag(DeviceEntry, TAG_USBLIB);
2506
2507 //
2508 // done
2509 //
2510 Status = STATUS_SUCCESS;
2511 break;
2512 }
2513
2514 //
2515 // goto next device
2516 //
2517 Entry = Entry->Flink;
2518 }
2519
2520 //
2521 // release lock
2522 //
2523 KeReleaseSpinLock(&m_Lock, OldLevel);
2524
2525 //
2526 // return result
2527 //
2528 return Status;
2529 }
2530 //-----------------------------------------------------------------------------------------
2531 BOOLEAN
2532 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
2533 {
2534 PUSBDEVICE_ENTRY DeviceEntry;
2535 PLIST_ENTRY Entry;
2536 KIRQL OldLevel;
2537 BOOLEAN Result = FALSE;
2538
2539 //
2540 // acquire lock
2541 //
2542 KeAcquireSpinLock(&m_Lock, &OldLevel);
2543
2544 //
2545 // point to first entry
2546 //
2547 Entry = m_UsbDeviceList.Flink;
2548
2549 //
2550 // find matching entry
2551 //
2552 while(Entry != &m_UsbDeviceList)
2553 {
2554 //
2555 // get entry
2556 //
2557 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2558
2559 //
2560 // is it current entry
2561 //
2562 if (DeviceEntry->Device == UsbDevice)
2563 {
2564 //
2565 // device is valid
2566 //
2567 Result = TRUE;
2568 break;
2569 }
2570
2571 //
2572 // goto next device
2573 //
2574 Entry = Entry->Flink;
2575 }
2576
2577 //
2578 // release lock
2579 //
2580 KeReleaseSpinLock(&m_Lock, OldLevel);
2581
2582 //
2583 // return result
2584 //
2585 return Result;
2586
2587 }
2588
2589 //-----------------------------------------------------------------------------------------
2590 NTSTATUS
2591 CHubController::AddUsbDevice(
2592 PUSBDEVICE UsbDevice)
2593 {
2594 PUSBDEVICE_ENTRY DeviceEntry;
2595 KIRQL OldLevel;
2596
2597 //
2598 // allocate device entry
2599 //
2600 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBLIB);
2601 if (!DeviceEntry)
2602 {
2603 //
2604 // no memory
2605 //
2606 return STATUS_INSUFFICIENT_RESOURCES;
2607 }
2608
2609 //
2610 // initialize entry
2611 //
2612 DeviceEntry->Device = UsbDevice;
2613
2614 //
2615 // acquire lock
2616 //
2617 KeAcquireSpinLock(&m_Lock, &OldLevel);
2618
2619 //
2620 // insert entry
2621 //
2622 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
2623
2624 //
2625 // release spin lock
2626 //
2627 KeReleaseSpinLock(&m_Lock, OldLevel);
2628
2629 //
2630 // done
2631 //
2632 return STATUS_SUCCESS;
2633 }
2634
2635 //-----------------------------------------------------------------------------------------
2636 VOID
2637 CHubController::SetNotification(
2638 PVOID CallbackContext,
2639 PRH_INIT_CALLBACK CallbackRoutine)
2640 {
2641 KIRQL OldLevel;
2642
2643 //
2644 // acquire hub controller lock
2645 //
2646 KeAcquireSpinLock(&m_Lock, &OldLevel);
2647
2648 //
2649 // now set the callback routine and context of the hub
2650 //
2651 m_HubCallbackContext = CallbackContext;
2652 m_HubCallbackRoutine = CallbackRoutine;
2653
2654 //
2655 // release hub controller lock
2656 //
2657 KeReleaseSpinLock(&m_Lock, OldLevel);
2658 }
2659
2660 //=================================================================================================
2661 //
2662 // Generic Interface functions
2663 //
2664 VOID
2665 USB_BUSIFFN
2666 USBI_InterfaceReference(
2667 PVOID BusContext)
2668 {
2669 CHubController * Controller = (CHubController*)BusContext;
2670
2671 DPRINT1("USBH_InterfaceReference\n");
2672
2673 //
2674 // add reference
2675 //
2676 Controller->AddRef();
2677 }
2678
2679 VOID
2680 USB_BUSIFFN
2681 USBI_InterfaceDereference(
2682 PVOID BusContext)
2683 {
2684 CHubController * Controller = (CHubController*)BusContext;
2685
2686 DPRINT1("USBH_InterfaceDereference\n");
2687
2688 //
2689 // release
2690 //
2691 Controller->Release();
2692 }
2693 //=================================================================================================
2694 //
2695 // USB Hub Interface functions
2696 //
2697 NTSTATUS
2698 USB_BUSIFFN
2699 USBHI_CreateUsbDevice(
2700 PVOID BusContext,
2701 PUSB_DEVICE_HANDLE *NewDevice,
2702 PUSB_DEVICE_HANDLE HubDeviceHandle,
2703 USHORT PortStatus,
2704 USHORT PortNumber)
2705 {
2706 PUSBDEVICE NewUsbDevice;
2707 CHubController * Controller;
2708 NTSTATUS Status;
2709
2710 DPRINT1("USBHI_CreateUsbDevice\n");
2711
2712 //
2713 // first get hub controller
2714 //
2715 Controller = (CHubController *)BusContext;
2716
2717 //
2718 // sanity check
2719 //
2720 PC_ASSERT(Controller);
2721 PC_ASSERT(BusContext == HubDeviceHandle);
2722
2723 //
2724 // now allocate usb device
2725 //
2726 Status = CreateUSBDevice(&NewUsbDevice);
2727
2728 //
2729 // check for success
2730 //
2731 if (!NT_SUCCESS(Status))
2732 {
2733 //
2734 // release controller
2735 //
2736 Controller->Release();
2737 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
2738 return Status;
2739 }
2740
2741 //
2742 // now initialize device
2743 //
2744 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(), HubDeviceHandle, PortNumber, PortStatus);
2745
2746 //
2747 // check for success
2748 //
2749 if (!NT_SUCCESS(Status))
2750 {
2751 //
2752 // release usb device
2753 //
2754 NewUsbDevice->Release();
2755 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
2756 return Status;
2757 }
2758
2759 //
2760 // insert into list
2761 //
2762 Status = Controller->AddUsbDevice(NewUsbDevice);
2763 //
2764 // check for success
2765 //
2766 if (!NT_SUCCESS(Status))
2767 {
2768 //
2769 // release usb device
2770 //
2771 NewUsbDevice->Release();
2772
2773 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
2774 return Status;
2775 }
2776
2777 //
2778 // store the handle
2779 //
2780 *NewDevice = NewUsbDevice;
2781
2782 //
2783 // done
2784 //
2785 return STATUS_SUCCESS;
2786 }
2787
2788 NTSTATUS
2789 USB_BUSIFFN
2790 USBHI_InitializeUsbDevice(
2791 PVOID BusContext,
2792 PUSB_DEVICE_HANDLE DeviceHandle)
2793 {
2794 PUSBDEVICE UsbDevice;
2795 CHubController * Controller;
2796 ULONG DeviceAddress;
2797 NTSTATUS Status;
2798 ULONG Index = 0;
2799
2800 DPRINT1("USBHI_InitializeUsbDevice\n");
2801
2802 //
2803 // first get controller
2804 //
2805 Controller = (CHubController *)BusContext;
2806 PC_ASSERT(Controller);
2807
2808 //
2809 // get device object
2810 //
2811 UsbDevice = (PUSBDEVICE)DeviceHandle;
2812 PC_ASSERT(UsbDevice);
2813
2814 //
2815 // validate device handle
2816 //
2817 if (!Controller->ValidateUsbDevice(UsbDevice))
2818 {
2819 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
2820
2821 //
2822 // invalid device handle
2823 //
2824 return STATUS_DEVICE_NOT_CONNECTED;
2825 }
2826
2827 //
2828 // now reserve an address
2829 //
2830 DeviceAddress = Controller->AcquireDeviceAddress();
2831
2832 //
2833 // is the device address valid
2834 //
2835 if (DeviceAddress == MAXULONG)
2836 {
2837 //
2838 // failed to get an device address from the device address pool
2839 //
2840 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2841 return STATUS_DEVICE_DATA_ERROR;
2842 }
2843
2844 do
2845 {
2846 //
2847 // now set the device address
2848 //
2849 Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
2850
2851 if (NT_SUCCESS(Status))
2852 break;
2853
2854 }while(Index++ < 3 );
2855
2856 //
2857 // check for failure
2858 //
2859 if (!NT_SUCCESS(Status))
2860 {
2861 //
2862 // failed to set device address
2863 //
2864 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
2865
2866 //
2867 // release address
2868 //
2869 Controller->ReleaseDeviceAddress(DeviceAddress);
2870
2871 //
2872 // return error
2873 //
2874 return STATUS_DEVICE_DATA_ERROR;
2875 }
2876
2877 //
2878 // done
2879 //
2880 return STATUS_SUCCESS;
2881 }
2882
2883 NTSTATUS
2884 USB_BUSIFFN
2885 USBHI_GetUsbDescriptors(
2886 PVOID BusContext,
2887 PUSB_DEVICE_HANDLE DeviceHandle,
2888 PUCHAR DeviceDescriptorBuffer,
2889 PULONG DeviceDescriptorBufferLength,
2890 PUCHAR ConfigDescriptorBuffer,
2891 PULONG ConfigDescriptorBufferLength)
2892 {
2893 PUSBDEVICE UsbDevice;
2894 CHubController * Controller;
2895
2896 DPRINT1("USBHI_GetUsbDescriptors\n");
2897
2898 //
2899 // sanity check
2900 //
2901 PC_ASSERT(DeviceDescriptorBuffer);
2902 PC_ASSERT(DeviceDescriptorBufferLength);
2903 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
2904 PC_ASSERT(ConfigDescriptorBufferLength);
2905 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
2906
2907 //
2908 // first get controller
2909 //
2910 Controller = (CHubController *)BusContext;
2911 PC_ASSERT(Controller);
2912
2913
2914 //
2915 // get device object
2916 //
2917 UsbDevice = (PUSBDEVICE)DeviceHandle;
2918 PC_ASSERT(UsbDevice);
2919
2920 //
2921 // validate device handle
2922 //
2923 if (!Controller->ValidateUsbDevice(UsbDevice))
2924 {
2925 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
2926
2927 //
2928 // invalid device handle
2929 //
2930 return STATUS_DEVICE_NOT_CONNECTED;
2931 }
2932
2933 //
2934 // get device descriptor
2935 //
2936 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
2937
2938 //
2939 // store result length
2940 //
2941 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
2942
2943 //
2944 // get configuration descriptor
2945 //
2946 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
2947
2948 //
2949 // complete the request
2950 //
2951 return STATUS_SUCCESS;
2952 }
2953
2954 NTSTATUS
2955 USB_BUSIFFN
2956 USBHI_RemoveUsbDevice(
2957 PVOID BusContext,
2958 PUSB_DEVICE_HANDLE DeviceHandle,
2959 ULONG Flags)
2960 {
2961 PUSBDEVICE UsbDevice;
2962 CHubController * Controller;
2963 NTSTATUS Status;
2964
2965 DPRINT1("USBHI_RemoveUsbDevice\n");
2966
2967 //
2968 // first get controller
2969 //
2970 Controller = (CHubController *)BusContext;
2971 PC_ASSERT(Controller);
2972
2973 //
2974 // get device object
2975 //
2976 UsbDevice = (PUSBDEVICE)DeviceHandle;
2977 PC_ASSERT(UsbDevice);
2978
2979 //
2980 // validate device handle
2981 //
2982 if (!Controller->ValidateUsbDevice(UsbDevice))
2983 {
2984 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
2985
2986 //
2987 // invalid device handle
2988 //
2989 return STATUS_DEVICE_NOT_CONNECTED;
2990 }
2991
2992 //
2993 // check if there were flags passed
2994 //
2995 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
2996 {
2997 //
2998 // ignore flags for now
2999 //
3000 return STATUS_SUCCESS;
3001 }
3002
3003 //
3004 // remove device
3005 //
3006 Status = Controller->RemoveUsbDevice(UsbDevice);
3007 if (!NT_SUCCESS(Status))
3008 {
3009 //
3010 // invalid device handle
3011 //
3012 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
3013 PC_ASSERT(0);
3014 return STATUS_DEVICE_NOT_CONNECTED;
3015 }
3016
3017 //
3018 // release usb device
3019 //
3020 UsbDevice->Release();
3021
3022 //
3023 // done
3024 //
3025 return STATUS_SUCCESS;
3026 }
3027
3028 NTSTATUS
3029 USB_BUSIFFN
3030 USBHI_RestoreUsbDevice(
3031 PVOID BusContext,
3032 PUSB_DEVICE_HANDLE OldDeviceHandle,
3033 PUSB_DEVICE_HANDLE NewDeviceHandle)
3034 {
3035 PUSBDEVICE OldUsbDevice, NewUsbDevice;
3036 CHubController * Controller;
3037
3038 DPRINT1("USBHI_RestoreUsbDevice\n");
3039
3040 //
3041 // first get controller
3042 //
3043 Controller = (CHubController *)BusContext;
3044 PC_ASSERT(Controller);
3045
3046 //
3047 // get device object
3048 //
3049 OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
3050 NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
3051 PC_ASSERT(OldUsbDevice);
3052 PC_ASSERT(NewDeviceHandle);
3053
3054 //
3055 // validate device handle
3056 //
3057 PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
3058 PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
3059
3060 DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
3061 DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
3062
3063 //
3064 // remove old device handle
3065 //
3066 USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
3067
3068 return STATUS_SUCCESS;
3069 }
3070
3071 NTSTATUS
3072 USB_BUSIFFN
3073 USBHI_QueryDeviceInformation(
3074 PVOID BusContext,
3075 PUSB_DEVICE_HANDLE DeviceHandle,
3076 PVOID DeviceInformationBuffer,
3077 ULONG DeviceInformationBufferLength,
3078 PULONG LengthReturned)
3079 {
3080 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
3081 PUSBDEVICE UsbDevice;
3082 CHubController * Controller;
3083
3084 DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
3085
3086 //
3087 // sanity check
3088 //
3089 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
3090 PC_ASSERT(DeviceInformationBuffer);
3091 PC_ASSERT(LengthReturned);
3092
3093 //
3094 // get controller object
3095 //
3096 Controller = (CHubController*)BusContext;
3097 PC_ASSERT(Controller);
3098
3099 //
3100 // get device object
3101 //
3102 UsbDevice = (PUSBDEVICE)DeviceHandle;
3103 PC_ASSERT(UsbDevice);
3104
3105 if (BusContext != DeviceHandle)
3106 {
3107 //
3108 // validate device handle
3109 //
3110 if (!Controller->ValidateUsbDevice(UsbDevice))
3111 {
3112 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
3113
3114 //
3115 // invalid device handle
3116 //
3117 return STATUS_DEVICE_NOT_CONNECTED;
3118 }
3119
3120 //
3121 // access information buffer
3122 //
3123 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
3124
3125 //
3126 // initialize with default values
3127 //
3128 DeviceInfo->InformationLevel = 0;
3129 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
3130 DeviceInfo->PortNumber = UsbDevice->GetPort();
3131 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
3132 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
3133 DeviceInfo->HubAddress = 0; //FIXME
3134 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
3135 DeviceInfo->DeviceType = UsbDevice->GetType();
3136 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
3137
3138 //
3139 // get device descriptor
3140 //
3141 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
3142
3143 //
3144 // FIXME return pipe information
3145 //
3146
3147 //
3148 // store result length
3149 //
3150 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
3151
3152 return STATUS_SUCCESS;
3153 }
3154
3155 //
3156 // access information buffer
3157 //
3158 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
3159
3160 //
3161 // initialize with default values
3162 //
3163 DeviceInfo->InformationLevel = 0;
3164 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
3165 DeviceInfo->PortNumber = 0;
3166 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
3167 DeviceInfo->DeviceAddress = 0;
3168 DeviceInfo->HubAddress = 0; //FIXME
3169 DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
3170 DeviceInfo->DeviceType = Usb20Device; //FIXME
3171 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
3172
3173 //
3174 // get device descriptor
3175 //
3176 RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
3177
3178 //
3179 // FIXME return pipe information
3180 //
3181
3182 //
3183 // store result length
3184 //
3185 #ifdef _MSC_VER
3186 *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
3187 #else
3188 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
3189 #endif
3190 //
3191 // done
3192 //
3193 return STATUS_SUCCESS;
3194 }
3195
3196 NTSTATUS
3197 USB_BUSIFFN
3198 USBHI_GetControllerInformation(
3199 PVOID BusContext,
3200 PVOID ControllerInformationBuffer,
3201 ULONG ControllerInformationBufferLength,
3202 PULONG LengthReturned)
3203 {
3204 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
3205
3206 DPRINT1("USBHI_GetControllerInformation\n");
3207
3208 //
3209 // sanity checks
3210 //
3211 PC_ASSERT(ControllerInformationBuffer);
3212 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
3213
3214 //
3215 // get controller info buffer
3216 //
3217 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
3218
3219 //
3220 // FIXME only version 0 is supported for now
3221 //
3222 PC_ASSERT(ControllerInfo->InformationLevel == 0);
3223
3224 //
3225 // fill in information
3226 //
3227 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
3228 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
3229 ControllerInfo->IsHighSpeedController = TRUE;
3230
3231 //
3232 // set length returned
3233 //
3234 *LengthReturned = ControllerInfo->ActualLength;
3235
3236 //
3237 // done
3238 //
3239 return STATUS_SUCCESS;
3240 }
3241
3242 NTSTATUS
3243 USB_BUSIFFN
3244 USBHI_ControllerSelectiveSuspend(
3245 PVOID BusContext,
3246 BOOLEAN Enable)
3247 {
3248 UNIMPLEMENTED
3249 return STATUS_NOT_IMPLEMENTED;
3250 }
3251
3252 NTSTATUS
3253 USB_BUSIFFN
3254 USBHI_GetExtendedHubInformation(
3255 PVOID BusContext,
3256 PDEVICE_OBJECT HubPhysicalDeviceObject,
3257 PVOID HubInformationBuffer,
3258 ULONG HubInformationBufferLength,
3259 PULONG LengthReturned)
3260 {
3261 PUSB_EXTHUB_INFORMATION_0 HubInfo;
3262 CHubController * Controller;
3263 PUSBHARDWAREDEVICE Hardware;
3264 ULONG Index;
3265 ULONG NumPort, Dummy2;
3266 USHORT Dummy1;
3267 NTSTATUS Status;
3268
3269 DPRINT1("USBHI_GetExtendedHubInformation\n");
3270
3271 //
3272 // sanity checks
3273 //
3274 PC_ASSERT(HubInformationBuffer);
3275 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
3276 PC_ASSERT(LengthReturned);
3277
3278 //
3279 // get hub controller
3280 //
3281 Controller = (CHubController *)BusContext;
3282 PC_ASSERT(Controller);
3283
3284 //
3285 // get usb hardware device
3286 //
3287 Hardware = Controller->GetUsbHardware();
3288
3289 //
3290 // retrieve number of ports
3291 //
3292 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
3293 if (!NT_SUCCESS(Status))
3294 {
3295 //
3296 // failed to get