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