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