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
->bmRequestType
.B
= 0xB;
319 CtrlSetup
->bRequest
= USB_REQUEST_SET_ADDRESS
;
320 CtrlSetup
->wValue
.W
= (USHORT
)DeviceAddress
;
323 // set device address
325 Status
= CommitSetupPacket(CtrlSetup
, 0, 0, 0);
330 ExFreePoolWithTag(CtrlSetup
, TAG_USBOHCI
);
335 if (!NT_SUCCESS(Status
))
338 // failed to set device address
340 DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status
, DeviceAddress
);
345 // lets have a short nap
347 KeStallExecutionProcessor(300);
350 // back up old address
352 OldAddress
= m_DeviceAddress
;
355 // store new device address
357 m_DeviceAddress
= DeviceAddress
;
360 // check that setting device address succeeded by retrieving the device descriptor
362 Status
= CreateDeviceDescriptor();
363 if (!NT_SUCCESS(Status
))
366 // failed to retrieve device descriptor
368 DPRINT1("CUSBbDevice::SetDeviceAddress> failed to retrieve device descriptor with device address set Error %x\n", Status
);
369 m_DeviceAddress
= OldAddress
;
372 // return error status
380 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
);
383 // allocate configuration descriptor
385 m_ConfigurationDescriptors
= (PUSB_CONFIGURATION_DESCRIPTOR
*) ExAllocatePoolWithTag(NonPagedPool
, sizeof(PUSB_CONFIGURATION_DESCRIPTOR
) * m_DeviceDescriptor
.bNumConfigurations
, TAG_USBOHCI
);
388 // zero configuration descriptor
390 RtlZeroMemory(m_ConfigurationDescriptors
, sizeof(PUSB_CONFIGURATION_DESCRIPTOR
) * m_DeviceDescriptor
.bNumConfigurations
);
393 // retrieve the configuration descriptors
395 for(Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
398 // retrieve configuration descriptors from device
400 Status
= CreateConfigurationDescriptor(Index
);
401 if (!NT_SUCCESS(Status
))
403 DPRINT1("CUSBDevice::SetDeviceAddress> failed to retrieve configuration %lu\n", Index
);
415 //----------------------------------------------------------------------------------------
417 CUSBDevice::GetDeviceDescriptor(
418 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
420 RtlMoveMemory(DeviceDescriptor
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
423 //----------------------------------------------------------------------------------------
425 CUSBDevice::GetConfigurationValue()
428 // return configuration index
430 return m_ConfigurationIndex
;
433 //----------------------------------------------------------------------------------------
435 CUSBDevice::CommitIrp(
441 if (!m_Queue
|| !m_DmaManager
)
446 DPRINT1("CUSBDevice::CommitUrb> no queue / dma !!!\n");
447 return STATUS_UNSUCCESSFUL
;
453 Status
= m_Queue
->CreateUSBRequest(&Request
);
454 if (!NT_SUCCESS(Status
))
457 // failed to build request
459 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status
);
464 // initialize request
466 Status
= Request
->InitializeWithIrp(m_DmaManager
, Irp
);
469 // mark irp as pending
471 IoMarkIrpPending(Irp
);
474 // now add the request
476 Status
= m_Queue
->AddUSBRequest(Request
);
477 if (!NT_SUCCESS(Status
))
480 // failed to add request
482 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status
);
490 return STATUS_PENDING
;
493 //----------------------------------------------------------------------------------------
495 CUSBDevice::SubmitIrp(
502 // acquire device lock
504 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
509 Status
= CommitIrp(Irp
);
514 KeReleaseSpinLock(&m_Lock
, OldLevel
);
518 //----------------------------------------------------------------------------------------
520 CUSBDevice::CommitSetupPacket(
521 IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
,
522 IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
,
523 IN ULONG BufferLength
,
534 DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
535 return STATUS_UNSUCCESSFUL
;
541 Status
= m_Queue
->CreateUSBRequest(&Request
);
542 if (!NT_SUCCESS(Status
))
545 // failed to build request
547 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status
);
552 // initialize request
554 Status
= Request
->InitializeWithSetupPacket(m_DmaManager
, Packet
, m_DeviceAddress
, EndpointDescriptor
, BufferLength
, Mdl
);
555 if (!NT_SUCCESS(Status
))
558 // failed to initialize request
560 DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status
);
566 // now add the request
568 Status
= m_Queue
->AddUSBRequest(Request
);
569 if (!NT_SUCCESS(Status
))
572 // failed to add request
574 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status
);
580 // get the result code when the operation has been finished
582 Request
->GetResultStatus(&Status
, NULL
);
595 //----------------------------------------------------------------------------------------
597 CUSBDevice::CreateDeviceDescriptor()
599 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
606 RtlZeroMemory(&m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
607 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
612 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
613 CtrlSetup
.wValue
.HiByte
= USB_DEVICE_DESCRIPTOR_TYPE
;
614 CtrlSetup
.wLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
615 CtrlSetup
.bmRequestType
.B
= 0x80;
618 // allocate mdl describing the device descriptor
620 Mdl
= IoAllocateMdl(&m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
), FALSE
, FALSE
, 0);
624 // failed to allocate mdl
626 return STATUS_INSUFFICIENT_RESOURCES
;
630 // build mdl for non paged pool
632 MmBuildMdlForNonPagedPool(Mdl
);
635 // commit setup packet
637 Status
= CommitSetupPacket(&CtrlSetup
, 0, sizeof(USB_DEVICE_DESCRIPTOR
), Mdl
);
644 if (NT_SUCCESS(Status
))
647 // informal dbg print
649 DumpDeviceDescriptor(&m_DeviceDescriptor
);
659 //----------------------------------------------------------------------------------------
661 CUSBDevice::CreateConfigurationDescriptor(
665 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
668 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
674 PC_ASSERT(m_ConfigurationDescriptors
);
677 // first allocate a buffer which should be enough to store all different interfaces and endpoints
679 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_USBOHCI
);
683 // failed to allocate buffer
685 return STATUS_INSUFFICIENT_RESOURCES
;
691 RtlZeroMemory(Buffer
, PAGE_SIZE
);
694 // build setup packet
696 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
697 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_STANDARD
;
698 CtrlSetup
.bmRequestType
._BM
.Reserved
= 0;
699 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
700 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
701 CtrlSetup
.wValue
.LowByte
= 0;
702 CtrlSetup
.wValue
.HiByte
= USB_CONFIGURATION_DESCRIPTOR_TYPE
;
703 CtrlSetup
.wIndex
.W
= 0;
704 CtrlSetup
.wLength
= PAGE_SIZE
;
707 // FIXME: where put configuration index?
711 // now build MDL describing the buffer
713 Mdl
= IoAllocateMdl(Buffer
, PAGE_SIZE
, FALSE
, FALSE
, 0);
717 // failed to allocate mdl
719 ExFreePoolWithTag(Buffer
, TAG_USBOHCI
);
720 return STATUS_INSUFFICIENT_RESOURCES
;
724 // build mdl for non paged pool
726 MmBuildMdlForNonPagedPool(Mdl
);
731 Status
= CommitSetupPacket(&CtrlSetup
, 0, PAGE_SIZE
, Mdl
);
732 if (!NT_SUCCESS(Status
))
735 // failed to issue request, cleanup
748 // get configuration descriptor
750 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Buffer
;
753 // informal debug print
755 DumpConfigurationDescriptor(ConfigurationDescriptor
);
760 PC_ASSERT(ConfigurationDescriptor
->bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
761 PC_ASSERT(ConfigurationDescriptor
->wTotalLength
<= PAGE_SIZE
);
762 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
);
765 // store configuration descriptor
767 m_ConfigurationDescriptors
[Index
] = ConfigurationDescriptor
;
774 //----------------------------------------------------------------------------------------
776 CUSBDevice::GetConfigurationDescriptors(
777 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
,
778 IN ULONG BufferLength
,
779 OUT PULONG OutBufferLength
)
784 PC_ASSERT(BufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
785 PC_ASSERT(ConfigDescriptorBuffer
);
786 PC_ASSERT(OutBufferLength
);
789 // reset copied length
791 *OutBufferLength
= 0;
794 // FIXME: support multiple configurations
796 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
799 // copy configuration descriptor
801 RtlCopyMemory(ConfigDescriptorBuffer
, m_ConfigurationDescriptors
[0], min(m_ConfigurationDescriptors
[0]->wTotalLength
, BufferLength
));
802 *OutBufferLength
= m_ConfigurationDescriptors
[0]->wTotalLength
;
805 //----------------------------------------------------------------------------------------
807 CUSBDevice::GetConfigurationDescriptorsLength()
810 // FIXME: support multiple configurations
812 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
814 ASSERT(m_ConfigurationDescriptors
[0]);
815 ASSERT(m_ConfigurationDescriptors
[0]->wTotalLength
);
817 return m_ConfigurationDescriptors
[0]->wTotalLength
;
819 //----------------------------------------------------------------------------------------
821 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
823 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor
);
824 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
825 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
826 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
827 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
828 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
829 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
830 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
831 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
832 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
833 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
834 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
835 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
836 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
837 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
840 //----------------------------------------------------------------------------------------
842 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
844 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor
);
845 DPRINT1("bLength %x\n", ConfigurationDescriptor
->bLength
);
846 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor
->bDescriptorType
);
847 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor
->wTotalLength
);
848 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
849 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor
->bConfigurationValue
);
850 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor
->iConfiguration
);
851 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor
->bmAttributes
);
852 DPRINT1("MaxPower %x\n", ConfigurationDescriptor
->MaxPower
);
854 //----------------------------------------------------------------------------------------
856 CUSBDevice::SubmitSetupPacket(
857 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
858 IN OUT ULONG BufferLength
,
867 Mdl
= IoAllocateMdl(Buffer
, BufferLength
, FALSE
, FALSE
, 0);
870 // HACK HACK HACK: assume the buffer is build from non paged pool
872 MmBuildMdlForNonPagedPool(Mdl
);
875 // commit setup packet
877 Status
= CommitSetupPacket(SetupPacket
, 0, BufferLength
, Mdl
);
890 //----------------------------------------------------------------------------------------
892 CUSBDevice::SelectConfiguration(
893 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
894 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo
,
895 OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
)
897 ULONG InterfaceIndex
, PipeIndex
;
898 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
900 PUSB_CONFIGURATION_DESCRIPTOR CurrentConfigurationDescriptor
;
901 PUSB_INTERFACE_DESCRIPTOR CurrentInterfaceDescriptor
;
902 PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
;
906 // FIXME: support multiple configurations
908 ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
909 ASSERT(m_ConfigurationDescriptors
[0]);
910 CurrentConfigurationDescriptor
= m_ConfigurationDescriptors
[0];
915 PC_ASSERT(ConfigurationDescriptor
->iConfiguration
== CurrentConfigurationDescriptor
->iConfiguration
);
916 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
<= CurrentConfigurationDescriptor
->bNumInterfaces
);
917 DPRINT1("CUSBDevice::SelectConfiguration NumInterfaces %lu\n", ConfigurationDescriptor
->bNumInterfaces
);
921 // copy interface info and pipe info
923 for(InterfaceIndex
= 0; InterfaceIndex
< ConfigurationDescriptor
->bNumInterfaces
; InterfaceIndex
++)
926 // find interface descriptor
928 CurrentInterfaceDescriptor
= USBD_ParseConfigurationDescriptor(CurrentConfigurationDescriptor
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
933 ASSERT(CurrentInterfaceDescriptor
);
934 ASSERT(CurrentInterfaceDescriptor
->bLength
!= 0);
935 ASSERT(InterfaceInfo
->NumberOfPipes
== CurrentInterfaceDescriptor
->bNumEndpoints
);
936 ASSERT(InterfaceInfo
->Length
!= 0);
938 PC_ASSERT(InterfaceInfo
->Length
== FIELD_OFFSET(USBD_INTERFACE_INFORMATION
, Pipes
[InterfaceInfo
->NumberOfPipes
]));
941 DPRINT1("CUSBDevice::SelectConfiguration InterfaceNumber %lu AlternativeSetting %lu bNumEndpoints %lu\n", InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
, CurrentInterfaceDescriptor
->bNumEndpoints
);
944 // copy interface info
946 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)CurrentInterfaceDescriptor
;
947 InterfaceInfo
->Class
= CurrentInterfaceDescriptor
->bInterfaceClass
;
948 InterfaceInfo
->SubClass
= CurrentInterfaceDescriptor
->bInterfaceSubClass
;
949 InterfaceInfo
->Protocol
= CurrentInterfaceDescriptor
->bInterfaceProtocol
;
950 InterfaceInfo
->Reserved
= 0;
953 // copy endpoint info
955 StartPosition
= CurrentInterfaceDescriptor
;
956 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
959 // find corresponding endpoint descriptor
961 CurrentEndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)USBD_ParseDescriptors(CurrentConfigurationDescriptor
, CurrentConfigurationDescriptor
->wTotalLength
, StartPosition
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
966 ASSERT(CurrentEndpointDescriptor
);
967 ASSERT(CurrentEndpointDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
972 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= CurrentEndpointDescriptor
->wMaxPacketSize
;
973 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= CurrentEndpointDescriptor
->bEndpointAddress
;
974 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= CurrentEndpointDescriptor
->bInterval
;
975 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)CurrentEndpointDescriptor
->bmAttributes
;
976 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)CurrentEndpointDescriptor
;
979 // move start position beyond the current endpoint descriptor
981 StartPosition
= (PVOID
)(CurrentEndpointDescriptor
+ 1);
987 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
)((ULONG_PTR
)PtrToUlong(InterfaceInfo
) + InterfaceInfo
->Length
);
991 // now build setup packet
993 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
994 CtrlSetup
.bRequest
= USB_REQUEST_SET_CONFIGURATION
;
995 CtrlSetup
.wValue
.W
= ConfigurationDescriptor
->bConfigurationValue
;
998 // select configuration
1000 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1003 // informal debug print
1005 DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationDescriptor
->iConfiguration
, m_ConfigurationIndex
, Status
);
1007 if (NT_SUCCESS(Status
))
1010 // store configuration device index
1012 m_ConfigurationIndex
= ConfigurationDescriptor
->iConfiguration
;
1015 // store configuration handle
1017 *ConfigurationHandle
= m_ConfigurationDescriptors
[0];
1026 //----------------------------------------------------------------------------------------
1028 CUSBDevice::SelectInterface(
1029 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
,
1030 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo
)
1032 PUSB_CONFIGURATION_DESCRIPTOR Configuration
;
1034 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1036 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
1037 PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
;
1038 PVOID StartPosition
;
1041 // FIXME support multiple configurations
1043 PC_ASSERT(m_ConfigurationDescriptors
[0] == (PUSB_CONFIGURATION_DESCRIPTOR
)ConfigurationHandle
);
1046 // get configuration struct
1048 Configuration
= (PUSB_CONFIGURATION_DESCRIPTOR
)ConfigurationHandle
;
1053 PC_ASSERT(Configuration
->bNumInterfaces
> InterfaceInfo
->InterfaceNumber
);
1055 //PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1059 // FIXME: check bandwidth
1063 // find interface number
1065 InterfaceDescriptor
= USBD_ParseConfigurationDescriptor(Configuration
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
1066 ASSERT(InterfaceDescriptor
);
1069 // initialize setup packet
1071 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1072 CtrlSetup
.bRequest
= USB_REQUEST_SET_INTERFACE
;
1073 CtrlSetup
.wValue
.W
= InterfaceDescriptor
->bAlternateSetting
;
1074 CtrlSetup
.wIndex
.W
= InterfaceDescriptor
->bInterfaceNumber
;
1075 CtrlSetup
.bmRequestType
.B
= 0x01;
1080 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1083 // informal debug print
1085 DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo
->AlternateSetting
, InterfaceInfo
->InterfaceNumber
, Status
);
1086 DPRINT1("CUSBDevice::SelectInterface bInterfaceNumber %u bAlternateSetting %u NumberOfPipes %u Length %lu\n",
1087 InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, InterfaceInfo
->NumberOfPipes
, InterfaceInfo
->Length
);
1088 InterfaceInfo
->InterfaceHandle
= InterfaceDescriptor
;
1089 InterfaceInfo
->NumberOfPipes
= InterfaceDescriptor
->bNumEndpoints
;
1092 // are there end points
1094 if (InterfaceDescriptor
->bNumEndpoints
)
1099 ASSERT(InterfaceInfo
->Length
== sizeof(USBD_INTERFACE_INFORMATION
) + (InterfaceDescriptor
->bNumEndpoints
> 1 ? sizeof(USBD_PIPE_INFORMATION
) * (InterfaceDescriptor
->bNumEndpoints
- 1) : 0));
1102 // store number of pipes
1104 InterfaceInfo
->NumberOfPipes
= InterfaceDescriptor
->bNumEndpoints
;
1106 StartPosition
= InterfaceDescriptor
;
1107 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
1110 // find corresponding endpoint descriptor
1112 CurrentEndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)USBD_ParseDescriptors(Configuration
, Configuration
->wTotalLength
, StartPosition
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
1117 ASSERT(CurrentEndpointDescriptor
);
1118 ASSERT(CurrentEndpointDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1123 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= CurrentEndpointDescriptor
->wMaxPacketSize
;
1124 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= CurrentEndpointDescriptor
->bEndpointAddress
;
1125 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= CurrentEndpointDescriptor
->bInterval
;
1126 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)CurrentEndpointDescriptor
->bmAttributes
;
1127 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)CurrentEndpointDescriptor
;
1130 // move start position beyond the current endpoint descriptor
1132 StartPosition
= (PVOID
)(CurrentEndpointDescriptor
+ 1);
1141 //----------------------------------------------------------------------------------------
1144 PUSBDEVICE
*OutDevice
)
1149 // allocate controller
1151 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBDevice(0);
1155 // failed to allocate
1157 return STATUS_INSUFFICIENT_RESOURCES
;
1161 // add reference count
1168 *OutDevice
= (PUSBDEVICE
)This
;
1173 return STATUS_SUCCESS
;