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/usb_device.cpp
5 * PURPOSE: USB OHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 class CUSBDevice
: public IUSBDevice
17 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
19 STDMETHODIMP_(ULONG
) AddRef()
21 InterlockedIncrement(&m_Ref
);
24 STDMETHODIMP_(ULONG
) Release()
26 InterlockedDecrement(&m_Ref
);
36 // IUSBDevice interface functions
37 virtual NTSTATUS
Initialize(IN PHUBCONTROLLER HubController
, IN PUSBHARDWAREDEVICE Device
, IN PVOID Parent
, IN ULONG Port
, IN ULONG PortStatus
);
38 virtual BOOLEAN
IsHub();
39 virtual NTSTATUS
GetParent(PVOID
* Parent
);
40 virtual UCHAR
GetDeviceAddress();
41 virtual ULONG
GetPort();
42 virtual USB_DEVICE_SPEED
GetSpeed();
43 virtual USB_DEVICE_TYPE
GetType();
44 virtual ULONG
GetState();
45 virtual void SetDeviceHandleData(PVOID Data
);
46 virtual NTSTATUS
SetDeviceAddress(UCHAR DeviceAddress
);
47 virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
);
48 virtual UCHAR
GetConfigurationValue();
49 virtual NTSTATUS
SubmitIrp(PIRP Irp
);
50 virtual VOID
GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
, IN ULONG BufferLength
, OUT PULONG OutBufferLength
);
51 virtual ULONG
GetConfigurationDescriptorsLength();
52 virtual NTSTATUS
SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
, OUT ULONG BufferLength
, OUT PVOID Buffer
);
53 virtual NTSTATUS
SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
, IN PUSBD_INTERFACE_INFORMATION Interface
, OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
);
54 virtual NTSTATUS
SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
, IN OUT PUSBD_INTERFACE_INFORMATION Interface
);
55 virtual NTSTATUS
AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
);
58 virtual NTSTATUS
CommitIrp(PIRP Irp
);
59 virtual NTSTATUS
CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
, IN ULONG BufferLength
, IN OUT PMDL Mdl
);
60 virtual NTSTATUS
CreateConfigurationDescriptor(ULONG ConfigurationIndex
);
61 virtual NTSTATUS
CreateDeviceDescriptor();
62 virtual VOID
DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
);
63 virtual VOID
DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
);
65 // constructor / destructor
66 CUSBDevice(IUnknown
*OuterUnknown
){}
67 virtual ~CUSBDevice(){}
71 PHUBCONTROLLER m_HubController
;
72 PUSBHARDWAREDEVICE m_Device
;
75 UCHAR m_DeviceAddress
;
77 UCHAR m_ConfigurationIndex
;
79 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
82 PDMAMEMORYMANAGER m_DmaManager
;
83 PUSB_CONFIGURATION_DESCRIPTOR
*m_ConfigurationDescriptors
;
84 LIST_ENTRY m_IrpListHead
;
88 //----------------------------------------------------------------------------------------
91 CUSBDevice::QueryInterface(
95 return STATUS_UNSUCCESSFUL
;
98 //----------------------------------------------------------------------------------------
100 CUSBDevice::Initialize(
101 IN PHUBCONTROLLER HubController
,
102 IN PUSBHARDWAREDEVICE Device
,
110 // initialize members
112 m_HubController
= HubController
;
116 m_PortStatus
= PortStatus
;
119 // initialize device lock
121 KeInitializeSpinLock(&m_Lock
);
124 // initialize irp list
126 InitializeListHead(&m_IrpListHead
);
129 // no device address has been set yet
134 // get usb request queue
136 Status
= m_Device
->GetUSBQueue(&m_Queue
);
137 if (!NT_SUCCESS(Status
))
140 // failed to get usb queue
142 DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n", Status
);
149 Status
= m_Device
->GetDMA(&m_DmaManager
);
150 if (!NT_SUCCESS(Status
))
153 // failed to get dma manager
155 DPRINT1("CUSBDevice::Initialize GetDMA failed with %x\n", Status
);
162 PC_ASSERT(m_DmaManager
);
165 // get device descriptor
167 Status
= CreateDeviceDescriptor();
168 if (!NT_SUCCESS(Status
))
171 // failed to get device descriptor
173 DPRINT1("CUSBDevice::Initialize Failed to get device descriptor with %x\n", Status
);
183 //----------------------------------------------------------------------------------------
188 // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h
191 return (m_DeviceDescriptor
.bDeviceClass
== 0x09 && m_DeviceDescriptor
.bDeviceSubClass
== 0x00);
194 //----------------------------------------------------------------------------------------
196 CUSBDevice::GetParent(
207 return STATUS_SUCCESS
;
210 //----------------------------------------------------------------------------------------
212 CUSBDevice::GetDeviceAddress()
215 // get device address
217 return m_DeviceAddress
;
220 //----------------------------------------------------------------------------------------
222 CUSBDevice::GetPort()
225 // get port to which this device is connected to
230 //----------------------------------------------------------------------------------------
232 CUSBDevice::GetSpeed()
234 if (m_PortStatus
& USB_PORT_STATUS_LOW_SPEED
)
241 else if (m_PortStatus
& USB_PORT_STATUS_HIGH_SPEED
)
250 // default to full speed
255 //----------------------------------------------------------------------------------------
257 CUSBDevice::GetType()
260 // device is encoded into bcdUSB
262 if (m_DeviceDescriptor
.bcdUSB
== 0x110)
269 else if (m_DeviceDescriptor
.bcdUSB
== 0x200)
277 DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor
.bcdUSB
);
282 //----------------------------------------------------------------------------------------
284 CUSBDevice::GetState()
290 //----------------------------------------------------------------------------------------
292 CUSBDevice::SetDeviceHandleData(
296 // set device data, for debugging issues
301 //----------------------------------------------------------------------------------------
303 CUSBDevice::SetDeviceAddress(
306 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
311 DPRINT1("CUSBDevice::SetDeviceAddress Address %d\n", DeviceAddress
);
313 CtrlSetup
= (PUSB_DEFAULT_PIPE_SETUP_PACKET
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), TAG_USBOHCI
);
315 return STATUS_INSUFFICIENT_RESOURCES
;
320 RtlZeroMemory(CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
323 // initialize request
325 CtrlSetup
->bRequest
= USB_REQUEST_SET_ADDRESS
;
326 CtrlSetup
->wValue
.W
= (USHORT
)DeviceAddress
;
329 // set device address
331 Status
= CommitSetupPacket(CtrlSetup
, 0, 0, 0);
336 ExFreePoolWithTag(CtrlSetup
, TAG_USBOHCI
);
341 if (!NT_SUCCESS(Status
))
344 // failed to set device address
346 DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status
, DeviceAddress
);
351 // lets have a short nap
353 KeStallExecutionProcessor(300);
356 // back up old address
358 OldAddress
= m_DeviceAddress
;
361 // store new device address
363 m_DeviceAddress
= DeviceAddress
;
366 // check that setting device address succeeded by retrieving the device descriptor
368 Status
= CreateDeviceDescriptor();
369 if (!NT_SUCCESS(Status
))
372 // failed to retrieve device descriptor
374 DPRINT1("CUSBbDevice::SetDeviceAddress> failed to retrieve device descriptor with device address set Error %x\n", Status
);
375 m_DeviceAddress
= OldAddress
;
378 // return error status
386 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
);
389 // allocate configuration descriptor
391 m_ConfigurationDescriptors
= (PUSB_CONFIGURATION_DESCRIPTOR
*) ExAllocatePoolWithTag(NonPagedPool
, sizeof(PUSB_CONFIGURATION_DESCRIPTOR
) * m_DeviceDescriptor
.bNumConfigurations
, TAG_USBOHCI
);
394 // zero configuration descriptor
396 RtlZeroMemory(m_ConfigurationDescriptors
, sizeof(PUSB_CONFIGURATION_DESCRIPTOR
) * m_DeviceDescriptor
.bNumConfigurations
);
399 // retrieve the configuration descriptors
401 for(Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
404 // retrieve configuration descriptors from device
406 Status
= CreateConfigurationDescriptor(Index
);
407 if (!NT_SUCCESS(Status
))
409 DPRINT1("CUSBDevice::SetDeviceAddress> failed to retrieve configuration %lu\n", Index
);
421 //----------------------------------------------------------------------------------------
423 CUSBDevice::GetDeviceDescriptor(
424 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
426 RtlMoveMemory(DeviceDescriptor
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
429 //----------------------------------------------------------------------------------------
431 CUSBDevice::GetConfigurationValue()
434 // return configuration index
436 return m_ConfigurationIndex
;
439 //----------------------------------------------------------------------------------------
441 CUSBDevice::CommitIrp(
447 if (!m_Queue
|| !m_DmaManager
)
452 DPRINT1("CUSBDevice::CommitUrb> no queue / dma !!!\n");
453 return STATUS_UNSUCCESSFUL
;
459 Status
= m_Queue
->CreateUSBRequest(&Request
);
460 if (!NT_SUCCESS(Status
))
463 // failed to build request
465 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status
);
470 // initialize request
472 Status
= Request
->InitializeWithIrp(m_DmaManager
, Irp
, GetSpeed());
475 // mark irp as pending
477 IoMarkIrpPending(Irp
);
480 // now add the request
482 Status
= m_Queue
->AddUSBRequest(Request
);
483 if (!NT_SUCCESS(Status
))
486 // failed to add request
488 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status
);
496 return STATUS_PENDING
;
499 //----------------------------------------------------------------------------------------
501 CUSBDevice::SubmitIrp(
508 // acquire device lock
510 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
515 Status
= CommitIrp(Irp
);
520 KeReleaseSpinLock(&m_Lock
, OldLevel
);
524 //----------------------------------------------------------------------------------------
526 CUSBDevice::CommitSetupPacket(
527 IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
,
528 IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
529 IN ULONG BufferLength
,
540 DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
541 return STATUS_UNSUCCESSFUL
;
547 Status
= m_Queue
->CreateUSBRequest(&Request
);
548 if (!NT_SUCCESS(Status
))
551 // failed to build request
553 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status
);
558 // initialize request
560 Status
= Request
->InitializeWithSetupPacket(m_DmaManager
, Packet
, m_DeviceAddress
, EndpointDescriptor
, GetSpeed(), BufferLength
, Mdl
);
561 if (!NT_SUCCESS(Status
))
564 // failed to initialize request
566 DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status
);
572 // now add the request
574 Status
= m_Queue
->AddUSBRequest(Request
);
575 if (!NT_SUCCESS(Status
))
578 // failed to add request
580 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status
);
586 // get the result code when the operation has been finished
588 Request
->GetResultStatus(&Status
, NULL
);
601 //----------------------------------------------------------------------------------------
603 CUSBDevice::CreateDeviceDescriptor()
605 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
608 PVOID DeviceDescriptor
;
611 // allocate descriptor page aligned
613 DeviceDescriptor
= ExAllocatePool(NonPagedPool
, PAGE_SIZE
);
614 if (!DeviceDescriptor
)
619 return STATUS_INSUFFICIENT_RESOURCES
;
625 RtlZeroMemory(DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
626 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
631 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
632 CtrlSetup
.wValue
.HiByte
= USB_DEVICE_DESCRIPTOR_TYPE
;
633 CtrlSetup
.wLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
634 CtrlSetup
.bmRequestType
.B
= 0x80;
637 // allocate mdl describing the device descriptor
639 Mdl
= IoAllocateMdl(DeviceDescriptor
, PAGE_SIZE
, FALSE
, FALSE
, 0);
643 // failed to allocate mdl
645 return STATUS_INSUFFICIENT_RESOURCES
;
649 // build mdl for non paged pool
651 MmBuildMdlForNonPagedPool(Mdl
);
654 // commit setup packet
656 Status
= CommitSetupPacket(&CtrlSetup
, 0, sizeof(USB_DEVICE_DESCRIPTOR
), Mdl
);
663 if (NT_SUCCESS(Status
))
666 // copy back device descriptor
668 RtlCopyMemory(&m_DeviceDescriptor
, DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
671 // informal dbg print
673 DumpDeviceDescriptor(&m_DeviceDescriptor
);
679 ExFreePool(DeviceDescriptor
);
688 //----------------------------------------------------------------------------------------
690 CUSBDevice::CreateConfigurationDescriptor(
694 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
697 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
703 PC_ASSERT(m_ConfigurationDescriptors
);
706 // first allocate a buffer which should be enough to store all different interfaces and endpoints
708 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_USBOHCI
);
712 // failed to allocate buffer
714 return STATUS_INSUFFICIENT_RESOURCES
;
720 RtlZeroMemory(Buffer
, PAGE_SIZE
);
723 // build setup packet
725 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
726 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_STANDARD
;
727 CtrlSetup
.bmRequestType
._BM
.Reserved
= 0;
728 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
729 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
730 CtrlSetup
.wValue
.LowByte
= 0;
731 CtrlSetup
.wValue
.HiByte
= USB_CONFIGURATION_DESCRIPTOR_TYPE
;
732 CtrlSetup
.wIndex
.W
= 0;
733 CtrlSetup
.wLength
= PAGE_SIZE
;
736 // FIXME: where put configuration index?
740 // now build MDL describing the buffer
742 Mdl
= IoAllocateMdl(Buffer
, PAGE_SIZE
, FALSE
, FALSE
, 0);
746 // failed to allocate mdl
748 ExFreePoolWithTag(Buffer
, TAG_USBOHCI
);
749 return STATUS_INSUFFICIENT_RESOURCES
;
753 // build mdl for non paged pool
755 MmBuildMdlForNonPagedPool(Mdl
);
760 Status
= CommitSetupPacket(&CtrlSetup
, 0, PAGE_SIZE
, Mdl
);
761 if (!NT_SUCCESS(Status
))
764 // failed to issue request, cleanup
777 // get configuration descriptor
779 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Buffer
;
782 // informal debug print
784 DumpConfigurationDescriptor(ConfigurationDescriptor
);
789 PC_ASSERT(ConfigurationDescriptor
->bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
790 PC_ASSERT(ConfigurationDescriptor
->wTotalLength
<= PAGE_SIZE
);
791 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
);
794 // store configuration descriptor
796 m_ConfigurationDescriptors
[Index
] = ConfigurationDescriptor
;
803 //----------------------------------------------------------------------------------------
805 CUSBDevice::GetConfigurationDescriptors(
806 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
,
807 IN ULONG BufferLength
,
808 OUT PULONG OutBufferLength
)
813 PC_ASSERT(BufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
814 PC_ASSERT(ConfigDescriptorBuffer
);
815 PC_ASSERT(OutBufferLength
);
818 // reset copied length
820 *OutBufferLength
= 0;
823 // FIXME: support multiple configurations
825 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
828 // copy configuration descriptor
830 RtlCopyMemory(ConfigDescriptorBuffer
, m_ConfigurationDescriptors
[0], min(m_ConfigurationDescriptors
[0]->wTotalLength
, BufferLength
));
831 *OutBufferLength
= m_ConfigurationDescriptors
[0]->wTotalLength
;
834 //----------------------------------------------------------------------------------------
836 CUSBDevice::GetConfigurationDescriptorsLength()
839 // FIXME: support multiple configurations
841 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
843 ASSERT(m_ConfigurationDescriptors
[0]);
844 ASSERT(m_ConfigurationDescriptors
[0]->wTotalLength
);
846 return m_ConfigurationDescriptors
[0]->wTotalLength
;
848 //----------------------------------------------------------------------------------------
850 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
852 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor
);
853 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
854 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
855 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
856 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
857 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
858 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
859 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
860 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
861 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
862 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
863 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
864 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
865 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
866 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
869 //----------------------------------------------------------------------------------------
871 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
873 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor
);
874 DPRINT1("bLength %x\n", ConfigurationDescriptor
->bLength
);
875 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor
->bDescriptorType
);
876 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor
->wTotalLength
);
877 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
878 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor
->bConfigurationValue
);
879 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor
->iConfiguration
);
880 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor
->bmAttributes
);
881 DPRINT1("MaxPower %x\n", ConfigurationDescriptor
->MaxPower
);
883 //----------------------------------------------------------------------------------------
885 CUSBDevice::SubmitSetupPacket(
886 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
887 IN OUT ULONG BufferLength
,
898 Mdl
= IoAllocateMdl(Buffer
, BufferLength
, FALSE
, FALSE
, 0);
900 return STATUS_INSUFFICIENT_RESOURCES
;
903 // HACK HACK HACK: assume the buffer is build from non paged pool
905 MmBuildMdlForNonPagedPool(Mdl
);
909 // commit setup packet
911 Status
= CommitSetupPacket(SetupPacket
, 0, BufferLength
, Mdl
);
927 //----------------------------------------------------------------------------------------
929 CUSBDevice::SelectConfiguration(
930 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
931 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo
,
932 OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
)
934 ULONG InterfaceIndex
, PipeIndex
;
935 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
937 PUSB_CONFIGURATION_DESCRIPTOR CurrentConfigurationDescriptor
;
938 PUSB_INTERFACE_DESCRIPTOR CurrentInterfaceDescriptor
;
939 PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
;
943 // FIXME: support multiple configurations
945 ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
946 ASSERT(m_ConfigurationDescriptors
[0]);
947 CurrentConfigurationDescriptor
= m_ConfigurationDescriptors
[0];
952 PC_ASSERT(ConfigurationDescriptor
->iConfiguration
== CurrentConfigurationDescriptor
->iConfiguration
);
953 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
<= CurrentConfigurationDescriptor
->bNumInterfaces
);
954 DPRINT1("CUSBDevice::SelectConfiguration NumInterfaces %lu\n", ConfigurationDescriptor
->bNumInterfaces
);
958 // copy interface info and pipe info
960 for(InterfaceIndex
= 0; InterfaceIndex
< ConfigurationDescriptor
->bNumInterfaces
; InterfaceIndex
++)
963 // find interface descriptor
965 CurrentInterfaceDescriptor
= USBD_ParseConfigurationDescriptor(CurrentConfigurationDescriptor
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
970 ASSERT(CurrentInterfaceDescriptor
);
971 ASSERT(CurrentInterfaceDescriptor
->bLength
!= 0);
972 ASSERT(InterfaceInfo
->NumberOfPipes
== CurrentInterfaceDescriptor
->bNumEndpoints
);
973 ASSERT(InterfaceInfo
->Length
!= 0);
975 PC_ASSERT(InterfaceInfo
->Length
== FIELD_OFFSET(USBD_INTERFACE_INFORMATION
, Pipes
[InterfaceInfo
->NumberOfPipes
]));
978 DPRINT1("CUSBDevice::SelectConfiguration InterfaceNumber %lu AlternativeSetting %lu bNumEndpoints %lu\n", InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
, CurrentInterfaceDescriptor
->bNumEndpoints
);
981 // copy interface info
983 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)CurrentInterfaceDescriptor
;
984 InterfaceInfo
->Class
= CurrentInterfaceDescriptor
->bInterfaceClass
;
985 InterfaceInfo
->SubClass
= CurrentInterfaceDescriptor
->bInterfaceSubClass
;
986 InterfaceInfo
->Protocol
= CurrentInterfaceDescriptor
->bInterfaceProtocol
;
987 InterfaceInfo
->Reserved
= 0;
990 // copy endpoint info
992 StartPosition
= CurrentInterfaceDescriptor
;
993 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
996 // find corresponding endpoint descriptor
998 CurrentEndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)USBD_ParseDescriptors(CurrentConfigurationDescriptor
, CurrentConfigurationDescriptor
->wTotalLength
, StartPosition
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
1003 ASSERT(CurrentEndpointDescriptor
);
1004 ASSERT(CurrentEndpointDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1009 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= CurrentEndpointDescriptor
->wMaxPacketSize
;
1010 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= CurrentEndpointDescriptor
->bEndpointAddress
;
1011 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= CurrentEndpointDescriptor
->bInterval
;
1012 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)CurrentEndpointDescriptor
->bmAttributes
;
1013 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)CurrentEndpointDescriptor
;
1016 // move start position beyond the current endpoint descriptor
1018 StartPosition
= (PVOID
)(CurrentEndpointDescriptor
+ 1);
1024 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
)((ULONG_PTR
)PtrToUlong(InterfaceInfo
) + InterfaceInfo
->Length
);
1028 // now build setup packet
1030 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1031 CtrlSetup
.bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1032 CtrlSetup
.wValue
.W
= ConfigurationDescriptor
->bConfigurationValue
;
1035 // select configuration
1037 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1040 // informal debug print
1042 DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationDescriptor
->iConfiguration
, m_ConfigurationIndex
, Status
);
1044 if (NT_SUCCESS(Status
))
1047 // store configuration device index
1049 m_ConfigurationIndex
= ConfigurationDescriptor
->iConfiguration
;
1052 // store configuration handle
1054 *ConfigurationHandle
= m_ConfigurationDescriptors
[0];
1063 //----------------------------------------------------------------------------------------
1065 CUSBDevice::SelectInterface(
1066 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
,
1067 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo
)
1069 PUSB_CONFIGURATION_DESCRIPTOR Configuration
;
1071 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1073 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
1074 PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
;
1075 PVOID StartPosition
;
1078 // FIXME support multiple configurations
1080 PC_ASSERT(m_ConfigurationDescriptors
[0] == (PUSB_CONFIGURATION_DESCRIPTOR
)ConfigurationHandle
);
1083 // get configuration struct
1085 Configuration
= (PUSB_CONFIGURATION_DESCRIPTOR
)ConfigurationHandle
;
1090 PC_ASSERT(Configuration
->bNumInterfaces
> InterfaceInfo
->InterfaceNumber
);
1092 //PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1096 // FIXME: check bandwidth
1100 // find interface number
1102 InterfaceDescriptor
= USBD_ParseConfigurationDescriptor(Configuration
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
1103 ASSERT(InterfaceDescriptor
);
1106 // initialize setup packet
1108 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1109 CtrlSetup
.bRequest
= USB_REQUEST_SET_INTERFACE
;
1110 CtrlSetup
.wValue
.W
= InterfaceDescriptor
->bAlternateSetting
;
1111 CtrlSetup
.wIndex
.W
= InterfaceDescriptor
->bInterfaceNumber
;
1112 CtrlSetup
.bmRequestType
.B
= 0x01;
1117 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1120 // informal debug print
1122 DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo
->AlternateSetting
, InterfaceInfo
->InterfaceNumber
, Status
);
1123 DPRINT1("CUSBDevice::SelectInterface bInterfaceNumber %u bAlternateSetting %u NumberOfPipes %u Length %lu\n",
1124 InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, InterfaceInfo
->NumberOfPipes
, InterfaceInfo
->Length
);
1125 InterfaceInfo
->InterfaceHandle
= InterfaceDescriptor
;
1126 InterfaceInfo
->NumberOfPipes
= InterfaceDescriptor
->bNumEndpoints
;
1129 // are there end points
1131 if (InterfaceDescriptor
->bNumEndpoints
)
1136 ASSERT(InterfaceInfo
->Length
== sizeof(USBD_INTERFACE_INFORMATION
) + (InterfaceDescriptor
->bNumEndpoints
> 1 ? sizeof(USBD_PIPE_INFORMATION
) * (InterfaceDescriptor
->bNumEndpoints
- 1) : 0));
1139 // store number of pipes
1141 InterfaceInfo
->NumberOfPipes
= InterfaceDescriptor
->bNumEndpoints
;
1143 StartPosition
= InterfaceDescriptor
;
1144 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
1147 // find corresponding endpoint descriptor
1149 CurrentEndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)USBD_ParseDescriptors(Configuration
, Configuration
->wTotalLength
, StartPosition
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
1154 ASSERT(CurrentEndpointDescriptor
);
1155 ASSERT(CurrentEndpointDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1160 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= CurrentEndpointDescriptor
->wMaxPacketSize
;
1161 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= CurrentEndpointDescriptor
->bEndpointAddress
;
1162 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= CurrentEndpointDescriptor
->bInterval
;
1163 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)CurrentEndpointDescriptor
->bmAttributes
;
1164 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)CurrentEndpointDescriptor
;
1167 // move start position beyond the current endpoint descriptor
1169 StartPosition
= (PVOID
)(CurrentEndpointDescriptor
+ 1);
1179 CUSBDevice::AbortPipe(
1180 IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
1183 // let it handle usb queue
1186 ASSERT(m_DeviceAddress
);
1191 return m_Queue
->AbortDevicePipe(m_DeviceAddress
, EndpointDescriptor
);
1194 //----------------------------------------------------------------------------------------
1197 PUSBDEVICE
*OutDevice
)
1202 // allocate controller
1204 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBDevice(0);
1208 // failed to allocate
1210 return STATUS_INSUFFICIENT_RESOURCES
;
1214 // add reference count
1221 *OutDevice
= (PUSBDEVICE
)This
;
1226 return STATUS_SUCCESS
;