2 * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/libusb/usb_device.cpp
5 * PURPOSE: USB Common Driver Library.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 class CUSBDevice
: public IUSBDevice
18 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
20 STDMETHODIMP_(ULONG
) AddRef()
22 InterlockedIncrement(&m_Ref
);
25 STDMETHODIMP_(ULONG
) Release()
27 InterlockedDecrement(&m_Ref
);
37 // IUSBDevice interface functions
38 virtual NTSTATUS
Initialize(IN PHUBCONTROLLER HubController
, IN PUSBHARDWAREDEVICE Device
, IN PVOID Parent
, IN ULONG Port
, IN ULONG PortStatus
);
39 virtual BOOLEAN
IsHub();
40 virtual NTSTATUS
GetParent(PVOID
* Parent
);
41 virtual UCHAR
GetDeviceAddress();
42 virtual ULONG
GetPort();
43 virtual USB_DEVICE_SPEED
GetSpeed();
44 virtual USB_DEVICE_TYPE
GetType();
45 virtual ULONG
GetState();
46 virtual void SetDeviceHandleData(PVOID Data
);
47 virtual NTSTATUS
SetDeviceAddress(UCHAR DeviceAddress
);
48 virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
);
49 virtual UCHAR
GetConfigurationValue();
50 virtual NTSTATUS
SubmitIrp(PIRP Irp
);
51 virtual VOID
GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
, IN ULONG BufferLength
, OUT PULONG OutBufferLength
);
52 virtual ULONG
GetConfigurationDescriptorsLength();
53 virtual NTSTATUS
SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
, OUT ULONG BufferLength
, OUT PVOID Buffer
);
54 virtual NTSTATUS
SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
, IN PUSBD_INTERFACE_INFORMATION Interface
, OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
);
55 virtual NTSTATUS
SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
, IN OUT PUSBD_INTERFACE_INFORMATION Interface
);
56 virtual NTSTATUS
AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
);
60 virtual NTSTATUS
CommitIrp(PIRP Irp
);
61 virtual NTSTATUS
CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
, IN ULONG BufferLength
, IN OUT PMDL Mdl
);
62 virtual NTSTATUS
CreateConfigurationDescriptor(UCHAR ConfigurationIndex
);
63 virtual NTSTATUS
CreateDeviceDescriptor();
64 virtual VOID
DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
);
65 virtual VOID
DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
);
67 // constructor / destructor
68 CUSBDevice(IUnknown
*OuterUnknown
){}
69 virtual ~CUSBDevice(){}
73 PHUBCONTROLLER m_HubController
;
74 PUSBHARDWAREDEVICE m_Device
;
77 UCHAR m_DeviceAddress
;
79 UCHAR m_ConfigurationIndex
;
81 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
84 PDMAMEMORYMANAGER m_DmaManager
;
86 PUSB_CONFIGURATION m_ConfigurationDescriptors
;
89 //----------------------------------------------------------------------------------------
92 CUSBDevice::QueryInterface(
96 return STATUS_UNSUCCESSFUL
;
99 //----------------------------------------------------------------------------------------
101 CUSBDevice::Initialize(
102 IN PHUBCONTROLLER HubController
,
103 IN PUSBHARDWAREDEVICE Device
,
111 // initialize members
113 m_HubController
= HubController
;
117 m_PortStatus
= PortStatus
;
120 // initialize device lock
122 KeInitializeSpinLock(&m_Lock
);
125 // no device address has been set yet
130 // get usb request queue
132 Status
= m_Device
->GetUSBQueue(&m_Queue
);
133 if (!NT_SUCCESS(Status
))
136 // failed to get usb queue
138 DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n", Status
);
145 Status
= m_Device
->GetDMA(&m_DmaManager
);
146 if (!NT_SUCCESS(Status
))
149 // failed to get dma manager
151 DPRINT1("CUSBDevice::Initialize GetDMA failed with %x\n", Status
);
158 PC_ASSERT(m_DmaManager
);
161 // get device descriptor
163 Status
= CreateDeviceDescriptor();
164 if (!NT_SUCCESS(Status
))
167 // failed to get device descriptor
169 DPRINT1("CUSBDevice::Initialize Failed to get device descriptor with %x\n", Status
);
179 //----------------------------------------------------------------------------------------
184 // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h
187 return (m_DeviceDescriptor
.bDeviceClass
== 0x09 && m_DeviceDescriptor
.bDeviceSubClass
== 0x00);
190 //----------------------------------------------------------------------------------------
192 CUSBDevice::GetParent(
203 return STATUS_SUCCESS
;
206 //----------------------------------------------------------------------------------------
208 CUSBDevice::GetDeviceAddress()
211 // get device address
213 return m_DeviceAddress
;
216 //----------------------------------------------------------------------------------------
218 CUSBDevice::GetPort()
221 // get port to which this device is connected to
226 //----------------------------------------------------------------------------------------
228 CUSBDevice::GetSpeed()
230 if (m_PortStatus
& USB_PORT_STATUS_LOW_SPEED
)
237 else if (m_PortStatus
& USB_PORT_STATUS_HIGH_SPEED
)
246 // default to full speed
251 //----------------------------------------------------------------------------------------
253 CUSBDevice::GetType()
256 // device is encoded into bcdUSB
258 if (m_DeviceDescriptor
.bcdUSB
== 0x110)
265 else if (m_DeviceDescriptor
.bcdUSB
== 0x200)
273 DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor
.bcdUSB
);
279 //----------------------------------------------------------------------------------------
281 CUSBDevice::GetState()
287 //----------------------------------------------------------------------------------------
289 CUSBDevice::SetDeviceHandleData(
293 // set device data, for debugging issues
298 //----------------------------------------------------------------------------------------
300 CUSBDevice::SetDeviceAddress(
303 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
308 DPRINT1("CUSBDevice::SetDeviceAddress Address %d\n", DeviceAddress
);
310 CtrlSetup
= (PUSB_DEFAULT_PIPE_SETUP_PACKET
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), TAG_USBLIB
);
312 return STATUS_INSUFFICIENT_RESOURCES
;
315 RtlZeroMemory(CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
317 // initialize request
318 CtrlSetup
->bRequest
= USB_REQUEST_SET_ADDRESS
;
319 CtrlSetup
->wValue
.W
= DeviceAddress
;
321 // set device address
322 Status
= CommitSetupPacket(CtrlSetup
, 0, 0, 0);
325 ExFreePoolWithTag(CtrlSetup
, TAG_USBLIB
);
328 if (!NT_SUCCESS(Status
))
330 // failed to set device address
331 DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status
, DeviceAddress
);
335 // lets have a short nap
336 KeStallExecutionProcessor(300);
338 // back up old address
339 OldAddress
= m_DeviceAddress
;
341 // store new device address
342 m_DeviceAddress
= DeviceAddress
;
344 // check that setting device address succeeded by retrieving the device descriptor
345 Status
= CreateDeviceDescriptor();
346 if (!NT_SUCCESS(Status
))
348 // failed to retrieve device descriptor
349 DPRINT1("CUSBbDevice::SetDeviceAddress> failed to retrieve device descriptor with device address set Error %x\n", Status
);
350 m_DeviceAddress
= OldAddress
;
352 // return error status
357 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
);
359 // allocate configuration descriptor
360 m_ConfigurationDescriptors
= (PUSB_CONFIGURATION
) ExAllocatePoolWithTag(NonPagedPool
, sizeof(USB_CONFIGURATION
) * m_DeviceDescriptor
.bNumConfigurations
, TAG_USBLIB
);
362 // zero configuration descriptor
363 RtlZeroMemory(m_ConfigurationDescriptors
, sizeof(USB_CONFIGURATION
) * m_DeviceDescriptor
.bNumConfigurations
);
365 // retrieve the configuration descriptors
366 for(Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
368 // retrieve configuration descriptors from device
369 Status
= CreateConfigurationDescriptor(Index
);
370 if (!NT_SUCCESS(Status
))
372 DPRINT1("CUSBDevice::SetDeviceAddress> failed to retrieve configuration %lu\n", Index
);
384 //----------------------------------------------------------------------------------------
386 CUSBDevice::GetDeviceDescriptor(
387 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
389 RtlMoveMemory(DeviceDescriptor
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
392 //----------------------------------------------------------------------------------------
394 CUSBDevice::GetConfigurationValue()
397 // return configuration index
399 return m_ConfigurationIndex
;
402 //----------------------------------------------------------------------------------------
404 CUSBDevice::CommitIrp(
410 if (!m_Queue
|| !m_DmaManager
)
415 DPRINT1("CUSBDevice::CommitUrb> no queue / dma !!!\n");
416 return STATUS_UNSUCCESSFUL
;
422 Status
= m_Queue
->CreateUSBRequest(&Request
);
423 if (!NT_SUCCESS(Status
))
426 // failed to build request
428 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status
);
433 // initialize request
435 Status
= Request
->InitializeWithIrp(m_DmaManager
, Irp
);
438 // mark irp as pending
440 IoMarkIrpPending(Irp
);
443 // now add the request
445 Status
= m_Queue
->AddUSBRequest(Request
);
446 if (!NT_SUCCESS(Status
))
449 // failed to add request
451 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status
);
459 return STATUS_PENDING
;
462 //----------------------------------------------------------------------------------------
464 CUSBDevice::SubmitIrp(
471 // acquire device lock
473 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
478 Status
= CommitIrp(Irp
);
483 KeReleaseSpinLock(&m_Lock
, OldLevel
);
487 //----------------------------------------------------------------------------------------
489 CUSBDevice::CommitSetupPacket(
490 IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
,
491 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
,
492 IN ULONG BufferLength
,
503 DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
504 return STATUS_UNSUCCESSFUL
;
510 Status
= m_Queue
->CreateUSBRequest(&Request
);
511 if (!NT_SUCCESS(Status
))
514 // failed to build request
516 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status
);
521 // initialize request
523 Status
= Request
->InitializeWithSetupPacket(m_DmaManager
, Packet
, m_DeviceAddress
, EndpointDescriptor
, BufferLength
, Mdl
);
524 if (!NT_SUCCESS(Status
))
527 // failed to initialize request
529 DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status
);
535 // now add the request
537 Status
= m_Queue
->AddUSBRequest(Request
);
538 if (!NT_SUCCESS(Status
))
541 // failed to add request
543 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status
);
549 // get the result code when the operation has been finished
551 Request
->GetResultStatus(&Status
, NULL
);
564 //----------------------------------------------------------------------------------------
566 CUSBDevice::CreateDeviceDescriptor()
568 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
576 RtlZeroMemory(&m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
577 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
582 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
583 CtrlSetup
.wValue
.HiByte
= USB_DEVICE_DESCRIPTOR_TYPE
;
584 CtrlSetup
.wLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
585 CtrlSetup
.bmRequestType
.B
= 0x80;
590 Buffer
= ExAllocatePool(NonPagedPool
, PAGE_SIZE
);
594 // failed to allocate
596 return STATUS_INSUFFICIENT_RESOURCES
;
602 RtlZeroMemory(Buffer
, PAGE_SIZE
);
605 // allocate mdl describing the device descriptor
607 Mdl
= IoAllocateMdl(Buffer
, sizeof(USB_DEVICE_DESCRIPTOR
), FALSE
, FALSE
, 0);
611 // failed to allocate mdl
613 return STATUS_INSUFFICIENT_RESOURCES
;
617 // build mdl for non paged pool
619 MmBuildMdlForNonPagedPool(Mdl
);
622 // commit setup packet
624 Status
= CommitSetupPacket(&CtrlSetup
, 0, sizeof(USB_DEVICE_DESCRIPTOR
), Mdl
);
631 if (NT_SUCCESS(Status
))
634 // informal dbg print
636 RtlCopyMemory(&m_DeviceDescriptor
, Buffer
, sizeof(USB_DEVICE_DESCRIPTOR
));
637 DumpDeviceDescriptor(&m_DeviceDescriptor
);
652 //----------------------------------------------------------------------------------------
654 CUSBDevice::CreateConfigurationDescriptor(
658 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
661 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
666 PC_ASSERT(m_ConfigurationDescriptors
);
669 // first allocate a buffer which should be enough to store all different interfaces and endpoints
671 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_USBLIB
);
675 // failed to allocate buffer
677 return STATUS_INSUFFICIENT_RESOURCES
;
681 // build setup packet
683 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
684 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_STANDARD
;
685 CtrlSetup
.bmRequestType
._BM
.Reserved
= 0;
686 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
687 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
688 CtrlSetup
.wValue
.LowByte
= Index
;
689 CtrlSetup
.wValue
.HiByte
= USB_CONFIGURATION_DESCRIPTOR_TYPE
;
690 CtrlSetup
.wIndex
.W
= 0;
691 CtrlSetup
.wLength
= PAGE_SIZE
;
694 // now build MDL describing the buffer
696 Mdl
= IoAllocateMdl(Buffer
, PAGE_SIZE
, FALSE
, FALSE
, 0);
700 // failed to allocate mdl
702 ExFreePoolWithTag(Buffer
, TAG_USBLIB
);
703 return STATUS_INSUFFICIENT_RESOURCES
;
707 // build mdl for non paged pool
709 MmBuildMdlForNonPagedPool(Mdl
);
714 Status
= CommitSetupPacket(&CtrlSetup
, 0, PAGE_SIZE
, Mdl
);
715 if (!NT_SUCCESS(Status
))
718 // failed to issue request, cleanup
731 // get configuration descriptor
733 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)Buffer
;
736 // informal debug print
738 DumpConfigurationDescriptor(ConfigurationDescriptor
);
743 PC_ASSERT(ConfigurationDescriptor
->bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
744 PC_ASSERT(ConfigurationDescriptor
->wTotalLength
<= PAGE_SIZE
);
745 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
);
748 // request is complete, initialize configuration descriptor
750 m_ConfigurationDescriptors
[Index
].ConfigurationDescriptor
= ConfigurationDescriptor
;
751 InitializeListHead(&m_ConfigurationDescriptors
[Index
].InterfaceList
);
758 //----------------------------------------------------------------------------------------
760 CUSBDevice::GetConfigurationDescriptors(
761 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
,
762 IN ULONG BufferLength
,
763 OUT PULONG OutBufferLength
)
766 ASSERT(BufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
767 ASSERT(ConfigDescriptorBuffer
);
768 ASSERT(OutBufferLength
);
770 // reset copied length
771 *OutBufferLength
= 0;
773 // FIXME: support multiple configurations
774 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
776 // copy configuration descriptor
777 RtlCopyMemory(ConfigDescriptorBuffer
, m_ConfigurationDescriptors
[0].ConfigurationDescriptor
, min(m_ConfigurationDescriptors
[0].ConfigurationDescriptor
->wTotalLength
, BufferLength
));
778 *OutBufferLength
= m_ConfigurationDescriptors
[0].ConfigurationDescriptor
->wTotalLength
;
781 //----------------------------------------------------------------------------------------
783 CUSBDevice::GetConfigurationDescriptorsLength()
786 // FIXME: support multiple configurations
788 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
790 return m_ConfigurationDescriptors
[0].ConfigurationDescriptor
->wTotalLength
;
792 //----------------------------------------------------------------------------------------
794 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
796 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor
);
797 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
798 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
799 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
800 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
801 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
802 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
803 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
804 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
805 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
806 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
807 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
808 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
809 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
810 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
813 //----------------------------------------------------------------------------------------
815 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
817 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor
);
818 DPRINT1("bLength %x\n", ConfigurationDescriptor
->bLength
);
819 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor
->bDescriptorType
);
820 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor
->wTotalLength
);
821 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
822 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor
->bConfigurationValue
);
823 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor
->iConfiguration
);
824 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor
->bmAttributes
);
825 DPRINT1("MaxPower %x\n", ConfigurationDescriptor
->MaxPower
);
827 //----------------------------------------------------------------------------------------
829 CUSBDevice::SubmitSetupPacket(
830 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
831 IN OUT ULONG BufferLength
,
842 Mdl
= IoAllocateMdl(Buffer
, BufferLength
, FALSE
, FALSE
, 0);
848 return STATUS_INSUFFICIENT_RESOURCES
;
852 // HACK HACK HACK: assume the buffer is build from non paged pool
854 MmBuildMdlForNonPagedPool(Mdl
);
858 // commit setup packet
860 Status
= CommitSetupPacket(SetupPacket
, 0, BufferLength
, Mdl
);
876 //----------------------------------------------------------------------------------------
878 CUSBDevice::SelectConfiguration(
879 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
880 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo
,
881 OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
)
883 ULONG InterfaceIndex
, PipeIndex
;
884 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
886 UCHAR bConfigurationValue
= 0;
887 ULONG ConfigurationIndex
= 0, Index
;
889 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
890 PUSB_INTERFACE UsbInterface
;
891 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
894 if (ConfigurationDescriptor
)
896 // find configuration index
897 for(Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
899 if (m_ConfigurationDescriptors
[Index
].ConfigurationDescriptor
->bConfigurationValue
== ConfigurationDescriptor
->bConfigurationValue
)
901 // found configuration index
902 ConfigurationIndex
= Index
;
909 DPRINT1("[USBUHCI] invalid configuration value %lu\n", ConfigurationDescriptor
->bConfigurationValue
);
910 return STATUS_INVALID_PARAMETER
;
914 ASSERT(ConfigurationDescriptor
->bNumInterfaces
<= m_ConfigurationDescriptors
[ConfigurationIndex
].ConfigurationDescriptor
->bNumInterfaces
);
916 // get configuration value
917 bConfigurationValue
= ConfigurationDescriptor
->bConfigurationValue
;
920 // now build setup packet
921 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
922 CtrlSetup
.bRequest
= USB_REQUEST_SET_CONFIGURATION
;
923 CtrlSetup
.wValue
.W
= bConfigurationValue
;
925 // select configuration
926 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
928 if (!ConfigurationDescriptor
)
930 // unconfigure request
931 DPRINT1("CUsbDevice::SelectConfiguration Unconfigure Request Status %x\n", Status
);
932 m_ConfigurationIndex
= 0;
936 // informal debug print
937 DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationIndex
, m_ConfigurationIndex
, Status
);
938 if (!NT_SUCCESS(Status
))
946 // destroy old interface info
947 while(!IsListEmpty(&m_ConfigurationDescriptors
[m_ConfigurationIndex
].InterfaceList
))
950 Entry
= RemoveHeadList(&m_ConfigurationDescriptors
[m_ConfigurationIndex
].InterfaceList
);
952 // get interface info
953 UsbInterface
= (PUSB_INTERFACE
)CONTAINING_RECORD(Entry
, USB_INTERFACE
, ListEntry
);
955 // free interface info
956 ExFreePool(UsbInterface
);
960 ASSERT(IsListEmpty(&m_ConfigurationDescriptors
[ConfigurationIndex
].InterfaceList
));
962 // store new configuration device index
963 m_ConfigurationIndex
= ConfigurationIndex
;
965 // store configuration handle
966 *ConfigurationHandle
= &m_ConfigurationDescriptors
[ConfigurationIndex
];
968 // copy interface info and pipe info
969 for(InterfaceIndex
= 0; InterfaceIndex
< ConfigurationDescriptor
->bNumInterfaces
; InterfaceIndex
++)
971 // interface info checks
972 ASSERT(InterfaceInfo
->Length
!= 0);
975 PC_ASSERT(InterfaceInfo
->Length
== FIELD_OFFSET(USBD_INTERFACE_INFORMATION
, Pipes
[InterfaceInfo
->NumberOfPipes
]));
978 // find interface descriptor
979 InterfaceDescriptor
= USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors
[ConfigurationIndex
].ConfigurationDescriptor
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
982 ASSERT(InterfaceDescriptor
!= NULL
);
984 // check if the number of pipes have been properly set
985 ASSERT(InterfaceInfo
->NumberOfPipes
== InterfaceDescriptor
->bNumEndpoints
);
987 // copy interface info
988 InterfaceInfo
->Class
= InterfaceDescriptor
->bInterfaceClass
;
989 InterfaceInfo
->SubClass
= InterfaceDescriptor
->bInterfaceSubClass
;
990 InterfaceInfo
->Protocol
= InterfaceDescriptor
->bInterfaceProtocol
;
991 InterfaceInfo
->Reserved
= 0;
993 // allocate interface handle
994 UsbInterface
= (PUSB_INTERFACE
)ExAllocatePool(NonPagedPool
, sizeof(USB_INTERFACE
) + (InterfaceInfo
->NumberOfPipes
- 1) * sizeof(USB_ENDPOINT
));
997 // failed to allocate memory
998 return STATUS_INSUFFICIENT_RESOURCES
;
1002 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)UsbInterface
;
1004 // init interface handle
1005 UsbInterface
->InterfaceDescriptor
= InterfaceDescriptor
;
1006 InsertTailList(&m_ConfigurationDescriptors
[ConfigurationIndex
].InterfaceList
, &UsbInterface
->ListEntry
);
1008 // grab first endpoint descriptor
1009 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) (InterfaceDescriptor
+ 1);
1011 // now copy all endpoint information
1012 for(PipeIndex
= 0; PipeIndex
< InterfaceInfo
->NumberOfPipes
; PipeIndex
++)
1014 while(EndpointDescriptor
->bDescriptorType
!= USB_ENDPOINT_DESCRIPTOR_TYPE
&& EndpointDescriptor
->bLength
!= sizeof(USB_ENDPOINT_DESCRIPTOR
))
1016 // skip intermediate descriptors
1017 if (EndpointDescriptor
->bLength
== 0 || EndpointDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
1019 // bogus configuration descriptor
1020 DPRINT1("[USBEHCI] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, PipeIndex
,
1021 EndpointDescriptor
->bLength
, EndpointDescriptor
->bDescriptorType
);
1024 return STATUS_UNSUCCESSFUL
;
1027 // move to next descriptor
1028 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)((ULONG_PTR
)EndpointDescriptor
+ EndpointDescriptor
->bLength
);
1031 // store in interface info
1032 RtlCopyMemory(&UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
, EndpointDescriptor
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
1035 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.wMaxPacketSize
;
1036 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bEndpointAddress
;
1037 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bInterval
;
1038 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bmAttributes
;
1039 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)&UsbInterface
->EndPoints
[PipeIndex
];
1041 // move to next descriptor
1042 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)((ULONG_PTR
)EndpointDescriptor
+ EndpointDescriptor
->bLength
);
1046 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
)((ULONG_PTR
)PtrToUlong(InterfaceInfo
) + InterfaceInfo
->Length
);
1055 //----------------------------------------------------------------------------------------
1057 CUSBDevice::SelectInterface(
1058 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
,
1059 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo
)
1062 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1064 ULONG Index
, ConfigurationIndex
= 0, Found
= FALSE
;
1065 PUSB_INTERFACE UsbInterface
;
1068 // check if handle is valid
1069 for(Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
1071 if (&m_ConfigurationDescriptors
[Index
] == ConfigurationHandle
)
1073 // found configuration index
1074 ConfigurationIndex
= Index
;
1081 // invalid handle passed
1082 DPRINT1("[USBEHCI] Invalid configuration handle passed %p\n", ConfigurationHandle
);
1083 return STATUS_INVALID_PARAMETER
;
1086 // initialize setup packet
1087 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1088 CtrlSetup
.bRequest
= USB_REQUEST_SET_INTERFACE
;
1089 CtrlSetup
.wValue
.W
= InterfaceInfo
->AlternateSetting
;
1090 CtrlSetup
.wIndex
.W
= InterfaceInfo
->InterfaceNumber
;
1091 CtrlSetup
.bmRequestType
.B
= 0x01;
1094 Status
= CommitSetupPacket(&CtrlSetup
, 0, 0, 0);
1096 // informal debug print
1097 DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo
->AlternateSetting
, InterfaceInfo
->InterfaceNumber
, Status
);
1099 if (!NT_SUCCESS(Status
))
1101 // failed to select interface
1106 Status
= STATUS_SUCCESS
;
1111 Entry
= m_ConfigurationDescriptors
[ConfigurationIndex
].InterfaceList
.Flink
;
1112 while(Entry
!= &m_ConfigurationDescriptors
[ConfigurationIndex
].InterfaceList
)
1114 // grab interface descriptor
1115 UsbInterface
= (PUSB_INTERFACE
)CONTAINING_RECORD(Entry
, USB_INTERFACE
, ListEntry
);
1116 if (UsbInterface
->InterfaceDescriptor
->bAlternateSetting
== InterfaceInfo
->AlternateSetting
&&
1117 UsbInterface
->InterfaceDescriptor
->bInterfaceNumber
== InterfaceInfo
->InterfaceNumber
)
1127 // selected interface but interface not found
1128 // something is really wrong
1129 DPRINT1("[USBEHCI] Error: interface not found!!!\n");
1130 return STATUS_UNSUCCESSFUL
;
1133 // assert on pipe length mismatch
1134 ASSERT(InterfaceInfo
->NumberOfPipes
== UsbInterface
->InterfaceDescriptor
->bNumEndpoints
);
1136 // copy pipe handles
1137 for(PipeIndex
= 0; PipeIndex
< min(InterfaceInfo
->NumberOfPipes
, UsbInterface
->InterfaceDescriptor
->bNumEndpoints
); PipeIndex
++)
1140 DPRINT1("PipeIndex %lu\n", PipeIndex
);
1141 DPRINT1("EndpointAddress %x\n", InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
);
1142 DPRINT1("Interval %d\n", InterfaceInfo
->Pipes
[PipeIndex
].Interval
);
1143 DPRINT1("MaximumPacketSize %d\n", InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
);
1144 DPRINT1("MaximumTransferSize %d\n", InterfaceInfo
->Pipes
[PipeIndex
].MaximumTransferSize
);
1145 DPRINT1("PipeFlags %d\n", InterfaceInfo
->Pipes
[PipeIndex
].PipeFlags
);
1146 DPRINT1("PipeType %dd\n", InterfaceInfo
->Pipes
[PipeIndex
].PipeType
);
1147 DPRINT1("UsbEndPoint %x\n", InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
);
1150 ASSERT(InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
== UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bEndpointAddress
);
1151 ASSERT(InterfaceInfo
->Pipes
[PipeIndex
].Interval
== UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bInterval
);
1153 // store pipe handle
1154 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= &UsbInterface
->EndPoints
[PipeIndex
];
1156 // data toggle is reset on select interface requests
1157 UsbInterface
->EndPoints
[PipeIndex
].DataToggle
= FALSE
;
1168 CUSBDevice::AbortPipe(
1169 IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
1172 // let it handle usb queue
1175 ASSERT(m_DeviceAddress
);
1180 return m_Queue
->AbortDevicePipe(m_DeviceAddress
, EndpointDescriptor
);
1184 //----------------------------------------------------------------------------------------
1187 PUSBDEVICE
*OutDevice
)
1192 // allocate controller
1194 This
= new(NonPagedPool
, TAG_USBLIB
) CUSBDevice(0);
1198 // failed to allocate
1200 return STATUS_INSUFFICIENT_RESOURCES
;
1204 // add reference count
1211 *OutDevice
= (PUSBDEVICE
)This
;
1216 return STATUS_SUCCESS
;