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