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
);
57 virtual NTSTATUS
CommitIrp(PIRP Irp
);
58 virtual NTSTATUS
CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
, IN ULONG BufferLength
, IN OUT PMDL Mdl
);
59 virtual NTSTATUS
CreateConfigurationDescriptor(ULONG ConfigurationIndex
);
60 virtual NTSTATUS
CreateDeviceDescriptor();
61 virtual VOID
DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
);
62 virtual VOID
DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
);
64 // constructor / destructor
65 CUSBDevice(IUnknown
*OuterUnknown
){}
66 virtual ~CUSBDevice(){}
70 PHUBCONTROLLER m_HubController
;
71 PUSBHARDWAREDEVICE m_Device
;
74 UCHAR m_DeviceAddress
;
76 UCHAR m_ConfigurationIndex
;
78 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
81 PDMAMEMORYMANAGER m_DmaManager
;
82 PUSB_CONFIGURATION_DESCRIPTOR
*m_ConfigurationDescriptors
;
85 //----------------------------------------------------------------------------------------
88 CUSBDevice::QueryInterface(
92 return STATUS_UNSUCCESSFUL
;
95 //----------------------------------------------------------------------------------------
97 CUSBDevice::Initialize(
98 IN PHUBCONTROLLER HubController
,
99 IN PUSBHARDWAREDEVICE Device
,
107 // initialize members
109 m_HubController
= HubController
;
113 m_PortStatus
= PortStatus
;
116 // initialize device lock
118 KeInitializeSpinLock(&m_Lock
);
121 // no device address has been set yet
126 // get usb request queue
128 Status
= m_Device
->GetUSBQueue(&m_Queue
);
129 if (!NT_SUCCESS(Status
))
132 // failed to get usb queue
134 DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n", Status
);
141 Status
= m_Device
->GetDMA(&m_DmaManager
);
142 if (!NT_SUCCESS(Status
))
145 // failed to get dma manager
147 DPRINT1("CUSBDevice::Initialize GetDMA failed with %x\n", Status
);
154 PC_ASSERT(m_DmaManager
);
157 // get device descriptor
159 Status
= CreateDeviceDescriptor();
160 if (!NT_SUCCESS(Status
))
163 // failed to get device descriptor
165 DPRINT1("CUSBDevice::Initialize Failed to get device descriptor with %x\n", Status
);
175 //----------------------------------------------------------------------------------------
180 // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h
183 return (m_DeviceDescriptor
.bDeviceClass
== 0x09 && m_DeviceDescriptor
.bDeviceSubClass
== 0x00);
186 //----------------------------------------------------------------------------------------
188 CUSBDevice::GetParent(
199 return STATUS_SUCCESS
;
202 //----------------------------------------------------------------------------------------
204 CUSBDevice::GetDeviceAddress()
207 // get device address
209 return m_DeviceAddress
;
212 //----------------------------------------------------------------------------------------
214 CUSBDevice::GetPort()
217 // get port to which this device is connected to
222 //----------------------------------------------------------------------------------------
224 CUSBDevice::GetSpeed()
226 if (m_PortStatus
& USB_PORT_STATUS_LOW_SPEED
)
233 else if (m_PortStatus
& USB_PORT_STATUS_HIGH_SPEED
)
242 // default to full speed
247 //----------------------------------------------------------------------------------------
249 CUSBDevice::GetType()
252 // device is encoded into bcdUSB
254 if (m_DeviceDescriptor
.bcdUSB
== 0x110)
261 else if (m_DeviceDescriptor
.bcdUSB
== 0x200)
269 DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor
.bcdUSB
);
275 //----------------------------------------------------------------------------------------
277 CUSBDevice::GetState()
283 //----------------------------------------------------------------------------------------
285 CUSBDevice::SetDeviceHandleData(
289 // set device data, for debugging issues
294 //----------------------------------------------------------------------------------------
296 CUSBDevice::SetDeviceAddress(
299 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
304 DPRINT1("CUSBDevice::SetDeviceAddress Address %d\n", DeviceAddress
);
306 CtrlSetup
= (PUSB_DEFAULT_PIPE_SETUP_PACKET
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), TAG_USBOHCI
);
308 return STATUS_INSUFFICIENT_RESOURCES
;
313 RtlZeroMemory(CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
316 // initialize request
318 CtrlSetup
->bRequest
= USB_REQUEST_SET_ADDRESS
;
319 CtrlSetup
->wValue
.W
= (USHORT
)DeviceAddress
;
322 // set device address
324 Status
= CommitSetupPacket(CtrlSetup
, 0, 0, 0);
329 ExFreePoolWithTag(CtrlSetup
, TAG_USBOHCI
);
334 if (!NT_SUCCESS(Status
))
337 // failed to set device address
339 DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status
, DeviceAddress
);
344 // lets have a short nap
346 KeStallExecutionProcessor(300);
349 // back up old address
351 OldAddress
= m_DeviceAddress
;
354 // store new device address
356 m_DeviceAddress
= DeviceAddress
;
359 // check that setting device address succeeded by retrieving the device descriptor
361 Status
= CreateDeviceDescriptor();
362 if (!NT_SUCCESS(Status
))
365 // failed to retrieve device descriptor
367 DPRINT1("CUSBbDevice::SetDeviceAddress> failed to retrieve device descriptor with device address set Error %x\n", Status
);
368 m_DeviceAddress
= OldAddress
;
371 // return error status
379 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
);
382 // allocate configuration descriptor
384 m_ConfigurationDescriptors
= (PUSB_CONFIGURATION_DESCRIPTOR
*) ExAllocatePoolWithTag(NonPagedPool
, sizeof(PUSB_CONFIGURATION_DESCRIPTOR
) * m_DeviceDescriptor
.bNumConfigurations
, TAG_USBOHCI
);
387 // zero configuration descriptor
389 RtlZeroMemory(m_ConfigurationDescriptors
, sizeof(PUSB_CONFIGURATION_DESCRIPTOR
) * m_DeviceDescriptor
.bNumConfigurations
);
392 // retrieve the configuration descriptors
394 for(Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
397 // retrieve configuration descriptors from device
399 Status
= CreateConfigurationDescriptor(Index
);
400 if (!NT_SUCCESS(Status
))
402 DPRINT1("CUSBDevice::SetDeviceAddress> failed to retrieve configuration %lu\n", Index
);
414 //----------------------------------------------------------------------------------------
416 CUSBDevice::GetDeviceDescriptor(
417 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
419 RtlMoveMemory(DeviceDescriptor
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
422 //----------------------------------------------------------------------------------------
424 CUSBDevice::GetConfigurationValue()
427 // return configuration index
429 return m_ConfigurationIndex
;
432 //----------------------------------------------------------------------------------------
434 CUSBDevice::CommitIrp(
440 if (!m_Queue
|| !m_DmaManager
)
445 DPRINT1("CUSBDevice::CommitUrb> no queue / dma !!!\n");
446 return STATUS_UNSUCCESSFUL
;
452 Status
= m_Queue
->CreateUSBRequest(&Request
);
453 if (!NT_SUCCESS(Status
))
456 // failed to build request
458 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status
);
463 // initialize request
465 Status
= Request
->InitializeWithIrp(m_DmaManager
, Irp
);
468 // mark irp as pending
470 IoMarkIrpPending(Irp
);
473 // now add the request
475 Status
= m_Queue
->AddUSBRequest(Request
);
476 if (!NT_SUCCESS(Status
))
479 // failed to add request
481 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status
);
489 return STATUS_PENDING
;
492 //----------------------------------------------------------------------------------------
494 CUSBDevice::SubmitIrp(
501 // acquire device lock
503 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
508 Status
= CommitIrp(Irp
);
513 KeReleaseSpinLock(&m_Lock
, OldLevel
);
517 //----------------------------------------------------------------------------------------
519 CUSBDevice::CommitSetupPacket(
520 IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
,
521 IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
522 IN ULONG BufferLength
,
533 DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
534 return STATUS_UNSUCCESSFUL
;
540 Status
= m_Queue
->CreateUSBRequest(&Request
);
541 if (!NT_SUCCESS(Status
))
544 // failed to build request
546 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status
);
551 // initialize request
553 Status
= Request
->InitializeWithSetupPacket(m_DmaManager
, Packet
, m_DeviceAddress
, EndpointDescriptor
, BufferLength
, Mdl
);
554 if (!NT_SUCCESS(Status
))
557 // failed to initialize request
559 DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status
);
565 // now add the request
567 Status
= m_Queue
->AddUSBRequest(Request
);
568 if (!NT_SUCCESS(Status
))
571 // failed to add request
573 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status
);
579 // get the result code when the operation has been finished
581 Request
->GetResultStatus(&Status
, NULL
);
594 //----------------------------------------------------------------------------------------
596 CUSBDevice::CreateDeviceDescriptor()
598 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
605 RtlZeroMemory(&m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
606 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
611 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
612 CtrlSetup
.wValue
.HiByte
= USB_DEVICE_DESCRIPTOR_TYPE
;
613 CtrlSetup
.wLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
614 CtrlSetup
.bmRequestType
.B
= 0x80;
617 // allocate mdl describing the device descriptor
619 Mdl
= IoAllocateMdl(&m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
), FALSE
, FALSE
, 0);
623 // failed to allocate mdl
625 return STATUS_INSUFFICIENT_RESOURCES
;
629 // build mdl for non paged pool
631 MmBuildMdlForNonPagedPool(Mdl
);
634 // commit setup packet
636 Status
= CommitSetupPacket(&CtrlSetup
, 0, sizeof(USB_DEVICE_DESCRIPTOR
), Mdl
);
643 if (NT_SUCCESS(Status
))
646 // informal dbg print
648 DumpDeviceDescriptor(&m_DeviceDescriptor
);
658 //----------------------------------------------------------------------------------------
660 CUSBDevice::CreateConfigurationDescriptor(
664 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
667 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
673 PC_ASSERT(m_ConfigurationDescriptors
);
676 // first allocate a buffer which should be enough to store all different interfaces and endpoints
678 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_USBOHCI
);
682 // failed to allocate buffer
684 return STATUS_INSUFFICIENT_RESOURCES
;
690 RtlZeroMemory(Buffer
, PAGE_SIZE
);
693 // build setup packet
695 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
696 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_STANDARD
;
697 CtrlSetup
.bmRequestType
._BM
.Reserved
= 0;
698 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
699 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
700 CtrlSetup
.wValue
.LowByte
= 0;
701 CtrlSetup
.wValue
.HiByte
= USB_CONFIGURATION_DESCRIPTOR_TYPE
;
702 CtrlSetup
.wIndex
.W
= 0;
703 CtrlSetup
.wLength
= PAGE_SIZE
;
706 // FIXME: where put configuration index?
710 // now build MDL describing the buffer
712 Mdl
= IoAllocateMdl(Buffer
, PAGE_SIZE
, FALSE
, FALSE
, 0);
716 // failed to allocate mdl
718 ExFreePoolWithTag(Buffer
, TAG_USBOHCI
);
719 return STATUS_INSUFFICIENT_RESOURCES
;
723 // build mdl for non paged pool
725 MmBuildMdlForNonPagedPool(Mdl
);
730 Status
= CommitSetupPacket(&CtrlSetup
, 0, PAGE_SIZE
, Mdl
);
731 if (!NT_SUCCESS(Status
))
734 // failed to issue request, cleanup
747 // get configuration descriptor
749 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Buffer
;
752 // informal debug print
754 DumpConfigurationDescriptor(ConfigurationDescriptor
);
759 PC_ASSERT(ConfigurationDescriptor
->bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
760 PC_ASSERT(ConfigurationDescriptor
->wTotalLength
<= PAGE_SIZE
);
761 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
);
764 // store configuration descriptor
766 m_ConfigurationDescriptors
[Index
] = ConfigurationDescriptor
;
773 //----------------------------------------------------------------------------------------
775 CUSBDevice::GetConfigurationDescriptors(
776 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
,
777 IN ULONG BufferLength
,
778 OUT PULONG OutBufferLength
)
783 PC_ASSERT(BufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
784 PC_ASSERT(ConfigDescriptorBuffer
);
785 PC_ASSERT(OutBufferLength
);
788 // reset copied length
790 *OutBufferLength
= 0;
793 // FIXME: support multiple configurations
795 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
798 // copy configuration descriptor
800 RtlCopyMemory(ConfigDescriptorBuffer
, m_ConfigurationDescriptors
[0], min(m_ConfigurationDescriptors
[0]->wTotalLength
, BufferLength
));
801 *OutBufferLength
= m_ConfigurationDescriptors
[0]->wTotalLength
;
804 //----------------------------------------------------------------------------------------
806 CUSBDevice::GetConfigurationDescriptorsLength()
809 // FIXME: support multiple configurations
811 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
813 ASSERT(m_ConfigurationDescriptors
[0]);
814 ASSERT(m_ConfigurationDescriptors
[0]->wTotalLength
);
816 return m_ConfigurationDescriptors
[0]->wTotalLength
;
818 //----------------------------------------------------------------------------------------
820 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
822 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor
);
823 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
824 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
825 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
826 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
827 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
828 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
829 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
830 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
831 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
832 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
833 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
834 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
835 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
836 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
839 //----------------------------------------------------------------------------------------
841 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
843 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor
);
844 DPRINT1("bLength %x\n", ConfigurationDescriptor
->bLength
);
845 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor
->bDescriptorType
);
846 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor
->wTotalLength
);
847 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
848 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor
->bConfigurationValue
);
849 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor
->iConfiguration
);
850 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor
->bmAttributes
);
851 DPRINT1("MaxPower %x\n", ConfigurationDescriptor
->MaxPower
);
853 //----------------------------------------------------------------------------------------
855 CUSBDevice::SubmitSetupPacket(
856 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
857 IN OUT ULONG BufferLength
,
868 Mdl
= IoAllocateMdl(Buffer
, BufferLength
, FALSE
, FALSE
, 0);
870 return STATUS_INSUFFICIENT_RESOURCES
;
873 // HACK HACK HACK: assume the buffer is build from non paged pool
875 MmBuildMdlForNonPagedPool(Mdl
);
879 // commit setup packet
881 Status
= CommitSetupPacket(SetupPacket
, 0, BufferLength
, Mdl
);
897 //----------------------------------------------------------------------------------------
899 CUSBDevice::SelectConfiguration(
900 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
901 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo
,
902 OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
)
904 ULONG InterfaceIndex
, PipeIndex
;
905 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
907 PUSB_CONFIGURATION_DESCRIPTOR CurrentConfigurationDescriptor
;
908 PUSB_INTERFACE_DESCRIPTOR CurrentInterfaceDescriptor
;
909 PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
;
913 // FIXME: support multiple configurations
915 ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
916 ASSERT(m_ConfigurationDescriptors
[0]);
917 CurrentConfigurationDescriptor
= m_ConfigurationDescriptors
[0];
922 PC_ASSERT(ConfigurationDescriptor
->iConfiguration
== CurrentConfigurationDescriptor
->iConfiguration
);
923 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
<= CurrentConfigurationDescriptor
->bNumInterfaces
);
924 DPRINT1("CUSBDevice::SelectConfiguration NumInterfaces %lu\n", ConfigurationDescriptor
->bNumInterfaces
);
928 // copy interface info and pipe info
930 for(InterfaceIndex
= 0; InterfaceIndex
< ConfigurationDescriptor
->bNumInterfaces
; InterfaceIndex
++)
933 // find interface descriptor
935 CurrentInterfaceDescriptor
= USBD_ParseConfigurationDescriptor(CurrentConfigurationDescriptor
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
940 ASSERT(CurrentInterfaceDescriptor
);
941 ASSERT(CurrentInterfaceDescriptor
->bLength
!= 0);
942 ASSERT(InterfaceInfo
->NumberOfPipes
== CurrentInterfaceDescriptor
->bNumEndpoints
);
943 ASSERT(InterfaceInfo
->Length
!= 0);
945 PC_ASSERT(InterfaceInfo
->Length
== FIELD_OFFSET(USBD_INTERFACE_INFORMATION
, Pipes
[InterfaceInfo
->NumberOfPipes
]));
948 DPRINT1("CUSBDevice::SelectConfiguration InterfaceNumber %lu AlternativeSetting %lu bNumEndpoints %lu\n", InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
, CurrentInterfaceDescriptor
->bNumEndpoints
);
951 // copy interface info
953 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)CurrentInterfaceDescriptor
;
954 InterfaceInfo
->Class
= CurrentInterfaceDescriptor
->bInterfaceClass
;
955 InterfaceInfo
->SubClass
= CurrentInterfaceDescriptor
->bInterfaceSubClass
;
956 InterfaceInfo
->Protocol
= CurrentInterfaceDescriptor
->bInterfaceProtocol
;
957 InterfaceInfo
->Reserved
= 0;
960 // copy endpoint info
962 StartPosition
= CurrentInterfaceDescriptor
;
963 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
966 // find corresponding endpoint descriptor
968 CurrentEndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)USBD_ParseDescriptors(CurrentConfigurationDescriptor
, CurrentConfigurationDescriptor
->wTotalLength
, StartPosition
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
973 ASSERT(CurrentEndpointDescriptor
);
974 ASSERT(CurrentEndpointDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
979 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= CurrentEndpointDescriptor
->wMaxPacketSize
;
980 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= CurrentEndpointDescriptor
->bEndpointAddress
;
981 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= CurrentEndpointDescriptor
->bInterval
;
982 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)CurrentEndpointDescriptor
->bmAttributes
;
983 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)CurrentEndpointDescriptor
;
986 // move start position beyond the current endpoint descriptor
988 StartPosition
= (PVOID
)(CurrentEndpointDescriptor
+ 1);
994 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
)((ULONG_PTR
)PtrToUlong(InterfaceInfo
) + InterfaceInfo
->Length
);
998 // now build setup packet
1000 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1001 CtrlSetup
.bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1002 CtrlSetup
.wValue
.W
= ConfigurationDescriptor
->bConfigurationValue
;
1005 // select configuration
1007 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1010 // informal debug print
1012 DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationDescriptor
->iConfiguration
, m_ConfigurationIndex
, Status
);
1014 if (NT_SUCCESS(Status
))
1017 // store configuration device index
1019 m_ConfigurationIndex
= ConfigurationDescriptor
->iConfiguration
;
1022 // store configuration handle
1024 *ConfigurationHandle
= m_ConfigurationDescriptors
[0];
1033 //----------------------------------------------------------------------------------------
1035 CUSBDevice::SelectInterface(
1036 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
,
1037 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo
)
1039 PUSB_CONFIGURATION_DESCRIPTOR Configuration
;
1041 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1043 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
1044 PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
;
1045 PVOID StartPosition
;
1048 // FIXME support multiple configurations
1050 PC_ASSERT(m_ConfigurationDescriptors
[0] == (PUSB_CONFIGURATION_DESCRIPTOR
)ConfigurationHandle
);
1053 // get configuration struct
1055 Configuration
= (PUSB_CONFIGURATION_DESCRIPTOR
)ConfigurationHandle
;
1060 PC_ASSERT(Configuration
->bNumInterfaces
> InterfaceInfo
->InterfaceNumber
);
1062 //PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1066 // FIXME: check bandwidth
1070 // find interface number
1072 InterfaceDescriptor
= USBD_ParseConfigurationDescriptor(Configuration
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
1073 ASSERT(InterfaceDescriptor
);
1076 // initialize setup packet
1078 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1079 CtrlSetup
.bRequest
= USB_REQUEST_SET_INTERFACE
;
1080 CtrlSetup
.wValue
.W
= InterfaceDescriptor
->bAlternateSetting
;
1081 CtrlSetup
.wIndex
.W
= InterfaceDescriptor
->bInterfaceNumber
;
1082 CtrlSetup
.bmRequestType
.B
= 0x01;
1087 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1090 // informal debug print
1092 DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo
->AlternateSetting
, InterfaceInfo
->InterfaceNumber
, Status
);
1093 DPRINT1("CUSBDevice::SelectInterface bInterfaceNumber %u bAlternateSetting %u NumberOfPipes %u Length %lu\n",
1094 InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, InterfaceInfo
->NumberOfPipes
, InterfaceInfo
->Length
);
1095 InterfaceInfo
->InterfaceHandle
= InterfaceDescriptor
;
1096 InterfaceInfo
->NumberOfPipes
= InterfaceDescriptor
->bNumEndpoints
;
1099 // are there end points
1101 if (InterfaceDescriptor
->bNumEndpoints
)
1106 ASSERT(InterfaceInfo
->Length
== sizeof(USBD_INTERFACE_INFORMATION
) + (InterfaceDescriptor
->bNumEndpoints
> 1 ? sizeof(USBD_PIPE_INFORMATION
) * (InterfaceDescriptor
->bNumEndpoints
- 1) : 0));
1109 // store number of pipes
1111 InterfaceInfo
->NumberOfPipes
= InterfaceDescriptor
->bNumEndpoints
;
1113 StartPosition
= InterfaceDescriptor
;
1114 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
1117 // find corresponding endpoint descriptor
1119 CurrentEndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)USBD_ParseDescriptors(Configuration
, Configuration
->wTotalLength
, StartPosition
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
1124 ASSERT(CurrentEndpointDescriptor
);
1125 ASSERT(CurrentEndpointDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1130 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= CurrentEndpointDescriptor
->wMaxPacketSize
;
1131 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= CurrentEndpointDescriptor
->bEndpointAddress
;
1132 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= CurrentEndpointDescriptor
->bInterval
;
1133 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)CurrentEndpointDescriptor
->bmAttributes
;
1134 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)CurrentEndpointDescriptor
;
1137 // move start position beyond the current endpoint descriptor
1139 StartPosition
= (PVOID
)(CurrentEndpointDescriptor
+ 1);
1148 //----------------------------------------------------------------------------------------
1151 PUSBDEVICE
*OutDevice
)
1156 // allocate controller
1158 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBDevice(0);
1162 // failed to allocate
1164 return STATUS_INSUFFICIENT_RESOURCES
;
1168 // add reference count
1175 *OutDevice
= (PUSBDEVICE
)This
;
1180 return STATUS_SUCCESS
;