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
;
601 PVOID DeviceDescriptor
;
604 // allocate descriptor page aligned
606 DeviceDescriptor
= ExAllocatePool(NonPagedPool
, PAGE_SIZE
);
607 if (!DeviceDescriptor
)
612 return STATUS_INSUFFICIENT_RESOURCES
;
618 RtlZeroMemory(DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
619 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
624 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
625 CtrlSetup
.wValue
.HiByte
= USB_DEVICE_DESCRIPTOR_TYPE
;
626 CtrlSetup
.wLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
627 CtrlSetup
.bmRequestType
.B
= 0x80;
630 // allocate mdl describing the device descriptor
632 Mdl
= IoAllocateMdl(DeviceDescriptor
, PAGE_SIZE
, FALSE
, FALSE
, 0);
636 // failed to allocate mdl
638 return STATUS_INSUFFICIENT_RESOURCES
;
642 // build mdl for non paged pool
644 MmBuildMdlForNonPagedPool(Mdl
);
647 // commit setup packet
649 Status
= CommitSetupPacket(&CtrlSetup
, 0, sizeof(USB_DEVICE_DESCRIPTOR
), Mdl
);
656 if (NT_SUCCESS(Status
))
659 // copy back device descriptor
661 RtlCopyMemory(&m_DeviceDescriptor
, DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
664 // informal dbg print
666 DumpDeviceDescriptor(&m_DeviceDescriptor
);
672 ExFreePool(DeviceDescriptor
);
681 //----------------------------------------------------------------------------------------
683 CUSBDevice::CreateConfigurationDescriptor(
687 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
690 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
696 PC_ASSERT(m_ConfigurationDescriptors
);
699 // first allocate a buffer which should be enough to store all different interfaces and endpoints
701 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_USBOHCI
);
705 // failed to allocate buffer
707 return STATUS_INSUFFICIENT_RESOURCES
;
713 RtlZeroMemory(Buffer
, PAGE_SIZE
);
716 // build setup packet
718 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
719 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_STANDARD
;
720 CtrlSetup
.bmRequestType
._BM
.Reserved
= 0;
721 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
722 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
723 CtrlSetup
.wValue
.LowByte
= 0;
724 CtrlSetup
.wValue
.HiByte
= USB_CONFIGURATION_DESCRIPTOR_TYPE
;
725 CtrlSetup
.wIndex
.W
= 0;
726 CtrlSetup
.wLength
= PAGE_SIZE
;
729 // FIXME: where put configuration index?
733 // now build MDL describing the buffer
735 Mdl
= IoAllocateMdl(Buffer
, PAGE_SIZE
, FALSE
, FALSE
, 0);
739 // failed to allocate mdl
741 ExFreePoolWithTag(Buffer
, TAG_USBOHCI
);
742 return STATUS_INSUFFICIENT_RESOURCES
;
746 // build mdl for non paged pool
748 MmBuildMdlForNonPagedPool(Mdl
);
753 Status
= CommitSetupPacket(&CtrlSetup
, 0, PAGE_SIZE
, Mdl
);
754 if (!NT_SUCCESS(Status
))
757 // failed to issue request, cleanup
770 // get configuration descriptor
772 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Buffer
;
775 // informal debug print
777 DumpConfigurationDescriptor(ConfigurationDescriptor
);
782 PC_ASSERT(ConfigurationDescriptor
->bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
783 PC_ASSERT(ConfigurationDescriptor
->wTotalLength
<= PAGE_SIZE
);
784 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
);
787 // store configuration descriptor
789 m_ConfigurationDescriptors
[Index
] = ConfigurationDescriptor
;
796 //----------------------------------------------------------------------------------------
798 CUSBDevice::GetConfigurationDescriptors(
799 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
,
800 IN ULONG BufferLength
,
801 OUT PULONG OutBufferLength
)
806 PC_ASSERT(BufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
807 PC_ASSERT(ConfigDescriptorBuffer
);
808 PC_ASSERT(OutBufferLength
);
811 // reset copied length
813 *OutBufferLength
= 0;
816 // FIXME: support multiple configurations
818 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
821 // copy configuration descriptor
823 RtlCopyMemory(ConfigDescriptorBuffer
, m_ConfigurationDescriptors
[0], min(m_ConfigurationDescriptors
[0]->wTotalLength
, BufferLength
));
824 *OutBufferLength
= m_ConfigurationDescriptors
[0]->wTotalLength
;
827 //----------------------------------------------------------------------------------------
829 CUSBDevice::GetConfigurationDescriptorsLength()
832 // FIXME: support multiple configurations
834 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
836 ASSERT(m_ConfigurationDescriptors
[0]);
837 ASSERT(m_ConfigurationDescriptors
[0]->wTotalLength
);
839 return m_ConfigurationDescriptors
[0]->wTotalLength
;
841 //----------------------------------------------------------------------------------------
843 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
845 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor
);
846 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
847 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
848 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
849 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
850 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
851 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
852 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
853 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
854 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
855 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
856 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
857 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
858 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
859 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
862 //----------------------------------------------------------------------------------------
864 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
866 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor
);
867 DPRINT1("bLength %x\n", ConfigurationDescriptor
->bLength
);
868 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor
->bDescriptorType
);
869 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor
->wTotalLength
);
870 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
871 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor
->bConfigurationValue
);
872 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor
->iConfiguration
);
873 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor
->bmAttributes
);
874 DPRINT1("MaxPower %x\n", ConfigurationDescriptor
->MaxPower
);
876 //----------------------------------------------------------------------------------------
878 CUSBDevice::SubmitSetupPacket(
879 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
880 IN OUT ULONG BufferLength
,
891 Mdl
= IoAllocateMdl(Buffer
, BufferLength
, FALSE
, FALSE
, 0);
893 return STATUS_INSUFFICIENT_RESOURCES
;
896 // HACK HACK HACK: assume the buffer is build from non paged pool
898 MmBuildMdlForNonPagedPool(Mdl
);
902 // commit setup packet
904 Status
= CommitSetupPacket(SetupPacket
, 0, BufferLength
, Mdl
);
920 //----------------------------------------------------------------------------------------
922 CUSBDevice::SelectConfiguration(
923 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
924 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo
,
925 OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
)
927 ULONG InterfaceIndex
, PipeIndex
;
928 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
930 PUSB_CONFIGURATION_DESCRIPTOR CurrentConfigurationDescriptor
;
931 PUSB_INTERFACE_DESCRIPTOR CurrentInterfaceDescriptor
;
932 PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
;
936 // FIXME: support multiple configurations
938 ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
939 ASSERT(m_ConfigurationDescriptors
[0]);
940 CurrentConfigurationDescriptor
= m_ConfigurationDescriptors
[0];
945 PC_ASSERT(ConfigurationDescriptor
->iConfiguration
== CurrentConfigurationDescriptor
->iConfiguration
);
946 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
<= CurrentConfigurationDescriptor
->bNumInterfaces
);
947 DPRINT1("CUSBDevice::SelectConfiguration NumInterfaces %lu\n", ConfigurationDescriptor
->bNumInterfaces
);
951 // copy interface info and pipe info
953 for(InterfaceIndex
= 0; InterfaceIndex
< ConfigurationDescriptor
->bNumInterfaces
; InterfaceIndex
++)
956 // find interface descriptor
958 CurrentInterfaceDescriptor
= USBD_ParseConfigurationDescriptor(CurrentConfigurationDescriptor
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
963 ASSERT(CurrentInterfaceDescriptor
);
964 ASSERT(CurrentInterfaceDescriptor
->bLength
!= 0);
965 ASSERT(InterfaceInfo
->NumberOfPipes
== CurrentInterfaceDescriptor
->bNumEndpoints
);
966 ASSERT(InterfaceInfo
->Length
!= 0);
968 PC_ASSERT(InterfaceInfo
->Length
== FIELD_OFFSET(USBD_INTERFACE_INFORMATION
, Pipes
[InterfaceInfo
->NumberOfPipes
]));
971 DPRINT1("CUSBDevice::SelectConfiguration InterfaceNumber %lu AlternativeSetting %lu bNumEndpoints %lu\n", InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
, CurrentInterfaceDescriptor
->bNumEndpoints
);
974 // copy interface info
976 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)CurrentInterfaceDescriptor
;
977 InterfaceInfo
->Class
= CurrentInterfaceDescriptor
->bInterfaceClass
;
978 InterfaceInfo
->SubClass
= CurrentInterfaceDescriptor
->bInterfaceSubClass
;
979 InterfaceInfo
->Protocol
= CurrentInterfaceDescriptor
->bInterfaceProtocol
;
980 InterfaceInfo
->Reserved
= 0;
983 // copy endpoint info
985 StartPosition
= CurrentInterfaceDescriptor
;
986 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
989 // find corresponding endpoint descriptor
991 CurrentEndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)USBD_ParseDescriptors(CurrentConfigurationDescriptor
, CurrentConfigurationDescriptor
->wTotalLength
, StartPosition
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
996 ASSERT(CurrentEndpointDescriptor
);
997 ASSERT(CurrentEndpointDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1002 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= CurrentEndpointDescriptor
->wMaxPacketSize
;
1003 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= CurrentEndpointDescriptor
->bEndpointAddress
;
1004 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= CurrentEndpointDescriptor
->bInterval
;
1005 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)CurrentEndpointDescriptor
->bmAttributes
;
1006 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)CurrentEndpointDescriptor
;
1009 // move start position beyond the current endpoint descriptor
1011 StartPosition
= (PVOID
)(CurrentEndpointDescriptor
+ 1);
1017 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
)((ULONG_PTR
)PtrToUlong(InterfaceInfo
) + InterfaceInfo
->Length
);
1021 // now build setup packet
1023 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1024 CtrlSetup
.bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1025 CtrlSetup
.wValue
.W
= ConfigurationDescriptor
->bConfigurationValue
;
1028 // select configuration
1030 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1033 // informal debug print
1035 DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationDescriptor
->iConfiguration
, m_ConfigurationIndex
, Status
);
1037 if (NT_SUCCESS(Status
))
1040 // store configuration device index
1042 m_ConfigurationIndex
= ConfigurationDescriptor
->iConfiguration
;
1045 // store configuration handle
1047 *ConfigurationHandle
= m_ConfigurationDescriptors
[0];
1056 //----------------------------------------------------------------------------------------
1058 CUSBDevice::SelectInterface(
1059 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
,
1060 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo
)
1062 PUSB_CONFIGURATION_DESCRIPTOR Configuration
;
1064 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1066 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
1067 PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor
;
1068 PVOID StartPosition
;
1071 // FIXME support multiple configurations
1073 PC_ASSERT(m_ConfigurationDescriptors
[0] == (PUSB_CONFIGURATION_DESCRIPTOR
)ConfigurationHandle
);
1076 // get configuration struct
1078 Configuration
= (PUSB_CONFIGURATION_DESCRIPTOR
)ConfigurationHandle
;
1083 PC_ASSERT(Configuration
->bNumInterfaces
> InterfaceInfo
->InterfaceNumber
);
1085 //PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1089 // FIXME: check bandwidth
1093 // find interface number
1095 InterfaceDescriptor
= USBD_ParseConfigurationDescriptor(Configuration
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
1096 ASSERT(InterfaceDescriptor
);
1099 // initialize setup packet
1101 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1102 CtrlSetup
.bRequest
= USB_REQUEST_SET_INTERFACE
;
1103 CtrlSetup
.wValue
.W
= InterfaceDescriptor
->bAlternateSetting
;
1104 CtrlSetup
.wIndex
.W
= InterfaceDescriptor
->bInterfaceNumber
;
1105 CtrlSetup
.bmRequestType
.B
= 0x01;
1110 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1113 // informal debug print
1115 DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo
->AlternateSetting
, InterfaceInfo
->InterfaceNumber
, Status
);
1116 DPRINT1("CUSBDevice::SelectInterface bInterfaceNumber %u bAlternateSetting %u NumberOfPipes %u Length %lu\n",
1117 InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, InterfaceInfo
->NumberOfPipes
, InterfaceInfo
->Length
);
1118 InterfaceInfo
->InterfaceHandle
= InterfaceDescriptor
;
1119 InterfaceInfo
->NumberOfPipes
= InterfaceDescriptor
->bNumEndpoints
;
1122 // are there end points
1124 if (InterfaceDescriptor
->bNumEndpoints
)
1129 ASSERT(InterfaceInfo
->Length
== sizeof(USBD_INTERFACE_INFORMATION
) + (InterfaceDescriptor
->bNumEndpoints
> 1 ? sizeof(USBD_PIPE_INFORMATION
) * (InterfaceDescriptor
->bNumEndpoints
- 1) : 0));
1132 // store number of pipes
1134 InterfaceInfo
->NumberOfPipes
= InterfaceDescriptor
->bNumEndpoints
;
1136 StartPosition
= InterfaceDescriptor
;
1137 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
1140 // find corresponding endpoint descriptor
1142 CurrentEndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)USBD_ParseDescriptors(Configuration
, Configuration
->wTotalLength
, StartPosition
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
1147 ASSERT(CurrentEndpointDescriptor
);
1148 ASSERT(CurrentEndpointDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
);
1153 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= CurrentEndpointDescriptor
->wMaxPacketSize
;
1154 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= CurrentEndpointDescriptor
->bEndpointAddress
;
1155 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= CurrentEndpointDescriptor
->bInterval
;
1156 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)CurrentEndpointDescriptor
->bmAttributes
;
1157 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)CurrentEndpointDescriptor
;
1160 // move start position beyond the current endpoint descriptor
1162 StartPosition
= (PVOID
)(CurrentEndpointDescriptor
+ 1);
1171 //----------------------------------------------------------------------------------------
1174 PUSBDEVICE
*OutDevice
)
1179 // allocate controller
1181 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBDevice(0);
1185 // failed to allocate
1187 return STATUS_INSUFFICIENT_RESOURCES
;
1191 // add reference count
1198 *OutDevice
= (PUSBDEVICE
)This
;
1203 return STATUS_SUCCESS
;