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)
16 class CUSBDevice
: public IUSBDevice
19 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
21 STDMETHODIMP_(ULONG
) AddRef()
23 InterlockedIncrement(&m_Ref
);
26 STDMETHODIMP_(ULONG
) Release()
28 InterlockedDecrement(&m_Ref
);
38 // IUSBDevice interface functions
39 virtual NTSTATUS
Initialize(IN PHUBCONTROLLER HubController
, IN PUSBHARDWAREDEVICE Device
, IN PVOID Parent
, IN ULONG Port
, IN ULONG PortStatus
);
40 virtual BOOLEAN
IsHub();
41 virtual NTSTATUS
GetParent(PVOID
* Parent
);
42 virtual UCHAR
GetDeviceAddress();
43 virtual ULONG
GetPort();
44 virtual USB_DEVICE_SPEED
GetSpeed();
45 virtual USB_DEVICE_TYPE
GetType();
46 virtual ULONG
GetState();
47 virtual void SetDeviceHandleData(PVOID Data
);
48 virtual NTSTATUS
SetDeviceAddress(UCHAR DeviceAddress
);
49 virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
);
50 virtual UCHAR
GetConfigurationValue();
51 virtual NTSTATUS
SubmitIrp(PIRP Irp
);
52 virtual VOID
GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
, IN ULONG BufferLength
, OUT PULONG OutBufferLength
);
53 virtual ULONG
GetConfigurationDescriptorsLength();
54 virtual NTSTATUS
SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
, OUT ULONG BufferLength
, OUT PVOID Buffer
);
55 virtual NTSTATUS
SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
, IN PUSBD_INTERFACE_INFORMATION Interface
, OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
);
56 virtual NTSTATUS
SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
, IN OUT PUSBD_INTERFACE_INFORMATION Interface
);
57 virtual NTSTATUS
AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
);
58 virtual UCHAR
GetMaxPacketSize();
62 virtual NTSTATUS
CommitIrp(PIRP Irp
);
63 virtual NTSTATUS
CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
, IN ULONG BufferLength
, IN OUT PMDL Mdl
);
64 virtual NTSTATUS
CreateConfigurationDescriptor(UCHAR ConfigurationIndex
);
65 virtual NTSTATUS
CreateDeviceDescriptor();
66 virtual VOID
DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
);
67 virtual VOID
DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
);
68 virtual NTSTATUS
GetConfigurationDescriptor(UCHAR ConfigurationIndex
, USHORT BufferSize
, PVOID Buffer
);
69 virtual NTSTATUS
BuildInterfaceDescriptor(IN ULONG ConfigurationIndex
, IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
, OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo
, OUT PUSB_INTERFACE
*OutUsbInterface
);
72 // constructor / destructor
73 CUSBDevice(IUnknown
*OuterUnknown
){}
74 virtual ~CUSBDevice(){}
78 PHUBCONTROLLER m_HubController
;
79 PUSBHARDWAREDEVICE m_Device
;
82 UCHAR m_DeviceAddress
;
84 UCHAR m_ConfigurationIndex
;
86 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
;
89 PDMAMEMORYMANAGER m_DmaManager
;
92 PUSB_CONFIGURATION m_ConfigurationDescriptors
;
95 //----------------------------------------------------------------------------------------
98 CUSBDevice::QueryInterface(
102 return STATUS_UNSUCCESSFUL
;
105 //----------------------------------------------------------------------------------------
107 CUSBDevice::Initialize(
108 IN PHUBCONTROLLER HubController
,
109 IN PUSBHARDWAREDEVICE Device
,
117 // initialize members
119 m_HubController
= HubController
;
123 m_PortStatus
= PortStatus
;
124 m_USBType
= m_Device
->GetUSBType();
127 // initialize device lock
129 KeInitializeSpinLock(&m_Lock
);
132 // no device address has been set yet
137 // get usb request queue
139 Status
= m_Device
->GetUSBQueue(&m_Queue
);
140 if (!NT_SUCCESS(Status
))
143 // failed to get usb queue
145 DPRINT1("[%s] GetUsbQueue failed with %x\n", m_USBType
, Status
);
152 Status
= m_Device
->GetDMA(&m_DmaManager
);
153 if (!NT_SUCCESS(Status
))
156 // failed to get dma manager
158 DPRINT1("[%s] GetDMA failed with %x\n", m_USBType
, Status
);
165 PC_ASSERT(m_DmaManager
);
168 // get device descriptor
170 Status
= CreateDeviceDescriptor();
171 if (!NT_SUCCESS(Status
))
174 // failed to get device descriptor
176 DPRINT1("[%s] Failed to get device descriptor with %x\n", m_USBType
, Status
);
186 //----------------------------------------------------------------------------------------
191 // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h
194 return (m_DeviceDescriptor
.bDeviceClass
== 0x09 && m_DeviceDescriptor
.bDeviceSubClass
== 0x00);
197 //----------------------------------------------------------------------------------------
199 CUSBDevice::GetParent(
210 return STATUS_SUCCESS
;
213 //----------------------------------------------------------------------------------------
215 CUSBDevice::GetDeviceAddress()
218 // get device address
220 return m_DeviceAddress
;
223 //----------------------------------------------------------------------------------------
225 CUSBDevice::GetPort()
228 // get port to which this device is connected to
233 //----------------------------------------------------------------------------------------
235 CUSBDevice::GetSpeed()
237 if (m_PortStatus
& USB_PORT_STATUS_LOW_SPEED
)
244 else if (m_PortStatus
& USB_PORT_STATUS_HIGH_SPEED
)
253 // default to full speed
258 //----------------------------------------------------------------------------------------
260 CUSBDevice::GetType()
263 // device is encoded into bcdUSB
265 if (m_DeviceDescriptor
.bcdUSB
== 0x110)
272 else if (m_DeviceDescriptor
.bcdUSB
== 0x200)
280 DPRINT1("[%s] GetType Unknown bcdUSB Type %x\n", m_USBType
, m_DeviceDescriptor
.bcdUSB
);
286 //----------------------------------------------------------------------------------------
288 CUSBDevice::GetState()
294 //----------------------------------------------------------------------------------------
296 CUSBDevice::SetDeviceHandleData(
300 // set device data, for debugging issues
305 //----------------------------------------------------------------------------------------
307 CUSBDevice::SetDeviceAddress(
310 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
314 DPRINT1("[%s] SetDeviceAddress> Address %x\n", m_USBType
, DeviceAddress
);
316 CtrlSetup
= (PUSB_DEFAULT_PIPE_SETUP_PACKET
)ExAllocatePoolWithTag(NonPagedPool
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
), TAG_USBLIB
);
318 return STATUS_INSUFFICIENT_RESOURCES
;
321 RtlZeroMemory(CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
323 // initialize request
324 CtrlSetup
->bRequest
= USB_REQUEST_SET_ADDRESS
;
325 CtrlSetup
->wValue
.W
= DeviceAddress
;
327 // set device address
328 Status
= CommitSetupPacket(CtrlSetup
, NULL
, 0, NULL
);
331 ExFreePoolWithTag(CtrlSetup
, TAG_USBLIB
);
334 if (!NT_SUCCESS(Status
))
336 // failed to set device address
337 DPRINT1("[%s] SetDeviceAddress> failed to set device address with %lx Address %x\n", m_USBType
, Status
, DeviceAddress
);
341 // lets have a short nap
342 KeStallExecutionProcessor(300);
344 // store new device address
345 m_DeviceAddress
= DeviceAddress
;
347 // fetch device descriptor
348 Status
= CreateDeviceDescriptor();
349 if (!NT_SUCCESS(Status
))
351 DPRINT1("[%s] SetDeviceAddress failed to retrieve device descriptor with device address set Error %lx\n", m_USBType
, Status
);
352 // return error status
356 // check for invalid device descriptor
357 if (m_DeviceDescriptor
.bLength
!= sizeof(USB_DEVICE_DESCRIPTOR
) ||
358 m_DeviceDescriptor
.bDescriptorType
!= USB_DEVICE_DESCRIPTOR_TYPE
||
359 m_DeviceDescriptor
.bNumConfigurations
== 0)
361 // failed to retrieve device descriptor
362 DPRINT1("[%s] SetDeviceAddress> device returned bogus device descriptor\n", m_USBType
);
363 DumpDeviceDescriptor(&m_DeviceDescriptor
);
365 // return error status
366 return STATUS_UNSUCCESSFUL
;
369 // dump device descriptor
370 DumpDeviceDescriptor(&m_DeviceDescriptor
);
373 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
);
375 // allocate configuration descriptor
376 m_ConfigurationDescriptors
= (PUSB_CONFIGURATION
) ExAllocatePoolWithTag(NonPagedPool
, sizeof(USB_CONFIGURATION
) * m_DeviceDescriptor
.bNumConfigurations
, TAG_USBLIB
);
378 // zero configuration descriptor
379 RtlZeroMemory(m_ConfigurationDescriptors
, sizeof(USB_CONFIGURATION
) * m_DeviceDescriptor
.bNumConfigurations
);
381 // retrieve the configuration descriptors
382 for (Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
384 // retrieve configuration descriptors from device
385 Status
= CreateConfigurationDescriptor(Index
);
386 if (!NT_SUCCESS(Status
))
388 DPRINT1("[%s] SetDeviceAddress> failed to retrieve configuration %lu\n", m_USBType
, Index
);
400 //----------------------------------------------------------------------------------------
402 CUSBDevice::GetDeviceDescriptor(
403 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
405 RtlMoveMemory(DeviceDescriptor
, &m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
408 //----------------------------------------------------------------------------------------
410 CUSBDevice::GetConfigurationValue()
413 // return configuration index
415 return m_ConfigurationIndex
;
418 //----------------------------------------------------------------------------------------
420 CUSBDevice::CommitIrp(
426 if (!m_Queue
|| !m_DmaManager
)
431 DPRINT1("[%s] CommitIrp> no queue / dma !!!\n", m_USBType
);
432 return STATUS_UNSUCCESSFUL
;
438 Status
= m_Queue
->CreateUSBRequest(&Request
);
439 if (!NT_SUCCESS(Status
))
442 // failed to build request
444 DPRINT1("[%s] CommitIrp> CreateUSBRequest failed with %lx\n", m_USBType
, Status
);
449 // initialize request
451 Status
= Request
->InitializeWithIrp(m_DmaManager
, PUSBDEVICE(this), Irp
);
454 // mark irp as pending
456 IoMarkIrpPending(Irp
);
459 // now add the request
461 Status
= m_Queue
->AddUSBRequest(Request
);
462 if (!NT_SUCCESS(Status
))
465 // failed to add request
467 DPRINT1("[%s] failed add request to queue with %lx\n", m_USBType
, Status
);
475 return STATUS_PENDING
;
478 //----------------------------------------------------------------------------------------
480 CUSBDevice::SubmitIrp(
487 // acquire device lock
489 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
494 Status
= CommitIrp(Irp
);
499 KeReleaseSpinLock(&m_Lock
, OldLevel
);
504 //----------------------------------------------------------------------------------------
506 CUSBDevice::CommitSetupPacket(
507 IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet
,
508 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor
,
509 IN ULONG BufferLength
,
520 DPRINT1("[%s] CommitSetupPacket> no queue!!!\n", m_USBType
);
521 return STATUS_UNSUCCESSFUL
;
527 Status
= m_Queue
->CreateUSBRequest(&Request
);
528 if (!NT_SUCCESS(Status
))
531 // failed to build request
533 DPRINT1("[%s] CommitSetupPacket> CreateUSBRequest failed with %x\n", m_USBType
, Status
);
538 // initialize request
540 Status
= Request
->InitializeWithSetupPacket(m_DmaManager
, Packet
, PUSBDEVICE(this), EndpointDescriptor
, BufferLength
, Mdl
);
541 if (!NT_SUCCESS(Status
))
544 // failed to initialize request
546 DPRINT1("[%s] CommitSetupPacket failed to initialize usb request with %x\n", m_USBType
, Status
);
552 // now add the request
554 Status
= m_Queue
->AddUSBRequest(Request
);
555 if (!NT_SUCCESS(Status
))
558 // failed to add request
560 DPRINT1("[%s] CommitSetupPacket> failed add request to queue with %x\n", m_USBType
, Status
);
566 // get the result code when the operation has been finished
568 Request
->GetResultStatus(&Status
, NULL
);
581 //----------------------------------------------------------------------------------------
583 CUSBDevice::CreateDeviceDescriptor()
585 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
593 RtlZeroMemory(&m_DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
594 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
599 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
600 CtrlSetup
.wValue
.HiByte
= USB_DEVICE_DESCRIPTOR_TYPE
;
601 CtrlSetup
.wLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
602 CtrlSetup
.bmRequestType
.B
= 0x80;
607 Buffer
= ExAllocatePool(NonPagedPool
, PAGE_SIZE
);
611 // failed to allocate
613 return STATUS_INSUFFICIENT_RESOURCES
;
619 RtlZeroMemory(Buffer
, PAGE_SIZE
);
622 // allocate mdl describing the device descriptor
624 Mdl
= IoAllocateMdl(Buffer
, sizeof(USB_DEVICE_DESCRIPTOR
), FALSE
, FALSE
, 0);
628 // failed to allocate mdl
630 return STATUS_INSUFFICIENT_RESOURCES
;
634 // build mdl for non paged pool
636 MmBuildMdlForNonPagedPool(Mdl
);
639 // commit setup packet
641 Status
= CommitSetupPacket(&CtrlSetup
, NULL
, sizeof(USB_DEVICE_DESCRIPTOR
), Mdl
);
648 if (NT_SUCCESS(Status
))
651 // copy device descriptor
653 RtlCopyMemory(&m_DeviceDescriptor
, Buffer
, sizeof(USB_DEVICE_DESCRIPTOR
));
668 //----------------------------------------------------------------------------------------
670 CUSBDevice::GetConfigurationDescriptor(
671 IN UCHAR ConfigurationIndex
,
672 IN USHORT BufferSize
,
675 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
681 // now build MDL describing the buffer
683 Mdl
= IoAllocateMdl(Buffer
, BufferSize
, FALSE
, FALSE
, 0);
687 // failed to allocate mdl
689 return STATUS_INSUFFICIENT_RESOURCES
;
693 // build mdl for non paged pool
695 MmBuildMdlForNonPagedPool(Mdl
);
699 // build setup packet
701 CtrlSetup
.bmRequestType
._BM
.Recipient
= BMREQUEST_TO_DEVICE
;
702 CtrlSetup
.bmRequestType
._BM
.Type
= BMREQUEST_STANDARD
;
703 CtrlSetup
.bmRequestType
._BM
.Reserved
= 0;
704 CtrlSetup
.bmRequestType
._BM
.Dir
= BMREQUEST_DEVICE_TO_HOST
;
705 CtrlSetup
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
706 CtrlSetup
.wValue
.LowByte
= ConfigurationIndex
;
707 CtrlSetup
.wValue
.HiByte
= USB_CONFIGURATION_DESCRIPTOR_TYPE
;
708 CtrlSetup
.wIndex
.W
= 0;
709 CtrlSetup
.wLength
= BufferSize
;
714 Status
= CommitSetupPacket(&CtrlSetup
, NULL
, BufferSize
, Mdl
);
727 //----------------------------------------------------------------------------------------
729 CUSBDevice::CreateConfigurationDescriptor(
733 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
738 PC_ASSERT(m_ConfigurationDescriptors
);
741 // first allocate a buffer which should be enough to store all different interfaces and endpoints
743 ConfigurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_USBLIB
);
744 if (!ConfigurationDescriptor
)
747 // failed to allocate buffer
749 return STATUS_INSUFFICIENT_RESOURCES
;
753 // get partial configuration descriptor
755 Status
= GetConfigurationDescriptor(Index
, sizeof(USB_CONFIGURATION_DESCRIPTOR
), ConfigurationDescriptor
);
756 if (!NT_SUCCESS(Status
))
759 // failed to get partial configuration descriptor
761 DPRINT1("[%s] Failed to get partial configuration descriptor Status %x Index %x\n", m_USBType
, Status
, Index
);
762 ExFreePoolWithTag(ConfigurationDescriptor
, TAG_USBLIB
);
767 // now get full descriptor
769 Status
= GetConfigurationDescriptor(Index
, ConfigurationDescriptor
->wTotalLength
, ConfigurationDescriptor
);
770 if (!NT_SUCCESS(Status
))
773 // failed to get full configuration descriptor
775 DPRINT1("[%s] Failed to get full configuration descriptor Status %x Index %x\n", m_USBType
, Status
, Index
);
776 ExFreePoolWithTag(ConfigurationDescriptor
, TAG_USBLIB
);
781 // informal debug print
783 DumpConfigurationDescriptor(ConfigurationDescriptor
);
788 PC_ASSERT(ConfigurationDescriptor
->bLength
== sizeof(USB_CONFIGURATION_DESCRIPTOR
));
789 PC_ASSERT(ConfigurationDescriptor
->wTotalLength
<= PAGE_SIZE
);
790 PC_ASSERT(ConfigurationDescriptor
->bNumInterfaces
);
793 // request is complete, initialize configuration descriptor
795 m_ConfigurationDescriptors
[Index
].ConfigurationDescriptor
= ConfigurationDescriptor
;
796 InitializeListHead(&m_ConfigurationDescriptors
[Index
].InterfaceList
);
803 //----------------------------------------------------------------------------------------
805 CUSBDevice::GetConfigurationDescriptors(
806 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer
,
807 IN ULONG BufferLength
,
808 OUT PULONG OutBufferLength
)
813 ASSERT(BufferLength
>= sizeof(USB_CONFIGURATION_DESCRIPTOR
));
814 ASSERT(ConfigDescriptorBuffer
);
815 ASSERT(OutBufferLength
);
817 // reset copied length
818 *OutBufferLength
= 0;
820 // FIXME: support multiple configurations
821 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
823 // copy configuration descriptor
824 Length
= min(m_ConfigurationDescriptors
[0].ConfigurationDescriptor
->wTotalLength
, BufferLength
);
825 RtlCopyMemory(ConfigDescriptorBuffer
, m_ConfigurationDescriptors
[0].ConfigurationDescriptor
, Length
);
826 *OutBufferLength
= Length
;
829 //----------------------------------------------------------------------------------------
831 CUSBDevice::GetConfigurationDescriptorsLength()
834 // FIXME: support multiple configurations
836 PC_ASSERT(m_DeviceDescriptor
.bNumConfigurations
== 1);
838 return m_ConfigurationDescriptors
[0].ConfigurationDescriptor
->wTotalLength
;
840 //----------------------------------------------------------------------------------------
842 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
844 DPRINT1("Dumping Device Descriptor %p\n", DeviceDescriptor
);
845 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
846 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
847 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
848 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
849 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
850 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
851 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
852 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
853 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
854 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
855 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
856 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
857 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
858 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
861 //----------------------------------------------------------------------------------------
863 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
865 DPRINT1("Dumping ConfigurationDescriptor %p\n", ConfigurationDescriptor
);
866 DPRINT1("bLength %x\n", ConfigurationDescriptor
->bLength
);
867 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor
->bDescriptorType
);
868 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor
->wTotalLength
);
869 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
870 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor
->bConfigurationValue
);
871 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor
->iConfiguration
);
872 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor
->bmAttributes
);
873 DPRINT1("MaxPower %x\n", ConfigurationDescriptor
->MaxPower
);
875 //----------------------------------------------------------------------------------------
877 CUSBDevice::SubmitSetupPacket(
878 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket
,
879 IN OUT ULONG BufferLength
,
890 Mdl
= IoAllocateMdl(Buffer
, BufferLength
, FALSE
, FALSE
, 0);
896 return STATUS_INSUFFICIENT_RESOURCES
;
900 // HACK HACK HACK: assume the buffer is build from non paged pool
902 MmBuildMdlForNonPagedPool(Mdl
);
906 // commit setup packet
908 Status
= CommitSetupPacket(SetupPacket
, NULL
, BufferLength
, Mdl
);
923 //----------------------------------------------------------------------------------------
925 CUSBDevice::BuildInterfaceDescriptor(
926 IN ULONG ConfigurationIndex
,
927 IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
928 OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo
,
929 OUT PUSB_INTERFACE
*OutUsbInterface
)
931 PUSB_INTERFACE UsbInterface
;
932 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
935 // allocate interface handle
936 UsbInterface
= (PUSB_INTERFACE
)ExAllocatePool(NonPagedPool
, sizeof(USB_INTERFACE
) + (InterfaceDescriptor
->bNumEndpoints
- 1) * sizeof(USB_ENDPOINT
));
939 // failed to allocate memory
940 return STATUS_INSUFFICIENT_RESOURCES
;
944 RtlZeroMemory(UsbInterface
, sizeof(USB_INTERFACE
) + (InterfaceDescriptor
->bNumEndpoints
- 1) * sizeof(USB_ENDPOINT
));
947 InterfaceInfo
->InterfaceHandle
= (USBD_INTERFACE_HANDLE
)UsbInterface
;
948 InterfaceInfo
->Class
= InterfaceDescriptor
->bInterfaceClass
;
949 InterfaceInfo
->SubClass
= InterfaceDescriptor
->bInterfaceSubClass
;
950 InterfaceInfo
->Protocol
= InterfaceDescriptor
->bInterfaceProtocol
;
951 InterfaceInfo
->Reserved
= 0;
954 // init interface handle
955 UsbInterface
->InterfaceDescriptor
= InterfaceDescriptor
;
956 InsertTailList(&m_ConfigurationDescriptors
[ConfigurationIndex
].InterfaceList
, &UsbInterface
->ListEntry
);
958 // grab first endpoint descriptor
959 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) (InterfaceDescriptor
+ 1);
961 // now copy all endpoint information
962 for(PipeIndex
= 0; PipeIndex
< InterfaceDescriptor
->bNumEndpoints
; PipeIndex
++)
964 while(EndpointDescriptor
->bDescriptorType
!= USB_ENDPOINT_DESCRIPTOR_TYPE
)
966 // skip intermediate descriptors
967 if (EndpointDescriptor
->bLength
== 0 || EndpointDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
969 // bogus configuration descriptor
970 DPRINT1("[%s] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", m_USBType
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, PipeIndex
,
971 EndpointDescriptor
->bLength
, EndpointDescriptor
->bDescriptorType
);
974 return STATUS_UNSUCCESSFUL
;
977 // move to next descriptor
978 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)((ULONG_PTR
)EndpointDescriptor
+ EndpointDescriptor
->bLength
);
981 // store in interface info
982 RtlCopyMemory(&UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
, EndpointDescriptor
, sizeof(USB_ENDPOINT_DESCRIPTOR
));
984 DPRINT("Configuration Descriptor %p Length %lu\n", m_ConfigurationDescriptors
[ConfigurationIndex
].ConfigurationDescriptor
, m_ConfigurationDescriptors
[ConfigurationIndex
].ConfigurationDescriptor
->wTotalLength
);
985 DPRINT("EndpointDescriptor %p DescriptorType %x bLength %x\n", EndpointDescriptor
, EndpointDescriptor
->bDescriptorType
, EndpointDescriptor
->bLength
);
986 DPRINT("EndpointDescriptorHandle %p bAddress %x bmAttributes %x\n",&UsbInterface
->EndPoints
[PipeIndex
], UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bEndpointAddress
,
987 UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bmAttributes
);
990 InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
= UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.wMaxPacketSize
;
991 InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
= UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bEndpointAddress
;
992 InterfaceInfo
->Pipes
[PipeIndex
].Interval
= UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bInterval
;
993 InterfaceInfo
->Pipes
[PipeIndex
].PipeType
= (USBD_PIPE_TYPE
)UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bmAttributes
;
994 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= (PVOID
)&UsbInterface
->EndPoints
[PipeIndex
];
996 // move to next descriptor
997 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)((ULONG_PTR
)EndpointDescriptor
+ EndpointDescriptor
->bLength
);
1000 if (OutUsbInterface
)
1003 *OutUsbInterface
= UsbInterface
;
1005 return STATUS_SUCCESS
;
1010 //----------------------------------------------------------------------------------------
1012 CUSBDevice::SelectConfiguration(
1013 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
1014 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo
,
1015 OUT USBD_CONFIGURATION_HANDLE
*ConfigurationHandle
)
1017 ULONG InterfaceIndex
;
1018 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1020 UCHAR bConfigurationValue
= 0;
1021 ULONG ConfigurationIndex
= 0, Index
;
1022 UCHAR Found
= FALSE
;
1023 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
1024 PUSB_INTERFACE UsbInterface
;
1027 if (ConfigurationDescriptor
)
1029 // find configuration index
1030 for (Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
1032 if (m_ConfigurationDescriptors
[Index
].ConfigurationDescriptor
->bConfigurationValue
== ConfigurationDescriptor
->bConfigurationValue
)
1034 // found configuration index
1035 ConfigurationIndex
= Index
;
1042 DPRINT1("[%s] invalid configuration value %u\n", m_USBType
, ConfigurationDescriptor
->bConfigurationValue
);
1043 return STATUS_INVALID_PARAMETER
;
1047 ASSERT(ConfigurationDescriptor
->bNumInterfaces
<= m_ConfigurationDescriptors
[ConfigurationIndex
].ConfigurationDescriptor
->bNumInterfaces
);
1049 // get configuration value
1050 bConfigurationValue
= ConfigurationDescriptor
->bConfigurationValue
;
1053 // now build setup packet
1054 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1055 CtrlSetup
.bRequest
= USB_REQUEST_SET_CONFIGURATION
;
1056 CtrlSetup
.wValue
.W
= bConfigurationValue
;
1058 // select configuration
1059 Status
= CommitSetupPacket(&CtrlSetup
, NULL
, 0, NULL
);
1061 if (!ConfigurationDescriptor
)
1063 // unconfigure request
1064 DPRINT1("[%s] SelectConfiguration Unconfigure Request Status %lx\n", m_USBType
, Status
);
1065 m_ConfigurationIndex
= 0;
1069 // informal debug print
1070 DPRINT("[%s] SelectConfiguration New Configuration %x Old Configuration %x Result %lx\n", m_USBType
, ConfigurationIndex
, m_ConfigurationIndex
, Status
);
1071 if (!NT_SUCCESS(Status
))
1079 // destroy old interface info
1080 while (!IsListEmpty(&m_ConfigurationDescriptors
[m_ConfigurationIndex
].InterfaceList
))
1083 Entry
= RemoveHeadList(&m_ConfigurationDescriptors
[m_ConfigurationIndex
].InterfaceList
);
1085 // get interface info
1086 UsbInterface
= (PUSB_INTERFACE
)CONTAINING_RECORD(Entry
, USB_INTERFACE
, ListEntry
);
1088 // free interface info
1089 ExFreePool(UsbInterface
);
1093 ASSERT(IsListEmpty(&m_ConfigurationDescriptors
[ConfigurationIndex
].InterfaceList
));
1095 // store new configuration device index
1096 m_ConfigurationIndex
= ConfigurationIndex
;
1098 // store configuration handle
1099 *ConfigurationHandle
= &m_ConfigurationDescriptors
[ConfigurationIndex
];
1101 // copy interface info and pipe info
1102 for(InterfaceIndex
= 0; InterfaceIndex
< ConfigurationDescriptor
->bNumInterfaces
; InterfaceIndex
++)
1104 // interface info checks
1105 ASSERT(InterfaceInfo
->Length
!= 0);
1108 PC_ASSERT(InterfaceInfo
->Length
== FIELD_OFFSET(USBD_INTERFACE_INFORMATION
, Pipes
[InterfaceInfo
->NumberOfPipes
]));
1111 // find interface descriptor
1112 InterfaceDescriptor
= USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors
[ConfigurationIndex
].ConfigurationDescriptor
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
1115 ASSERT(InterfaceDescriptor
!= NULL
);
1117 // check if the number of pipes have been properly set
1118 ASSERT(InterfaceInfo
->NumberOfPipes
== InterfaceDescriptor
->bNumEndpoints
);
1120 // copy interface info
1121 Status
= BuildInterfaceDescriptor(ConfigurationIndex
, InterfaceDescriptor
, InterfaceInfo
, NULL
);
1122 if (!NT_SUCCESS(Status
))
1125 DPRINT1("[%s] Failed to copy interface descriptor Index %lu InterfaceDescriptor %p InterfaceInfo %p\n", m_USBType
, ConfigurationIndex
, InterfaceDescriptor
, InterfaceInfo
);
1130 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
)((PUCHAR
)InterfaceInfo
+ InterfaceInfo
->Length
);
1139 //----------------------------------------------------------------------------------------
1141 CUSBDevice::SelectInterface(
1142 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle
,
1143 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo
)
1146 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup
;
1148 ULONG Index
, ConfigurationIndex
= 0, Found
= FALSE
;
1149 PUSB_INTERFACE UsbInterface
;
1151 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
1153 // check if handle is valid
1154 for(Index
= 0; Index
< m_DeviceDescriptor
.bNumConfigurations
; Index
++)
1156 if (&m_ConfigurationDescriptors
[Index
] == ConfigurationHandle
)
1158 // found configuration index
1159 ConfigurationIndex
= Index
;
1166 // invalid handle passed
1167 DPRINT1("[%s] Invalid configuration handle passed %p\n", m_USBType
, ConfigurationHandle
);
1168 return STATUS_INVALID_PARAMETER
;
1171 // initialize setup packet
1172 RtlZeroMemory(&CtrlSetup
, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
));
1173 CtrlSetup
.bRequest
= USB_REQUEST_SET_INTERFACE
;
1174 CtrlSetup
.wValue
.W
= InterfaceInfo
->AlternateSetting
;
1175 CtrlSetup
.wIndex
.W
= InterfaceInfo
->InterfaceNumber
;
1176 CtrlSetup
.bmRequestType
.B
= 0x01;
1179 Status
= CommitSetupPacket(&CtrlSetup
, NULL
, 0, NULL
);
1181 // informal debug print
1182 DPRINT1("[%s] SelectInterface AlternateSetting %x InterfaceNumber %x Status %lx\n", m_USBType
, InterfaceInfo
->AlternateSetting
, InterfaceInfo
->InterfaceNumber
, Status
);
1184 if (!NT_SUCCESS(Status
))
1186 // failed to select interface
1191 Status
= STATUS_SUCCESS
;
1195 Entry
= m_ConfigurationDescriptors
[ConfigurationIndex
].InterfaceList
.Flink
;
1196 while (Entry
!= &m_ConfigurationDescriptors
[ConfigurationIndex
].InterfaceList
)
1198 // grab interface descriptor
1199 UsbInterface
= (PUSB_INTERFACE
)CONTAINING_RECORD(Entry
, USB_INTERFACE
, ListEntry
);
1200 if (UsbInterface
->InterfaceDescriptor
->bAlternateSetting
== InterfaceInfo
->AlternateSetting
&&
1201 UsbInterface
->InterfaceDescriptor
->bInterfaceNumber
== InterfaceInfo
->InterfaceNumber
)
1209 Entry
= Entry
->Flink
;
1214 // find interface descriptor
1215 InterfaceDescriptor
= USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors
[ConfigurationIndex
].ConfigurationDescriptor
, InterfaceInfo
->InterfaceNumber
, InterfaceInfo
->AlternateSetting
);
1216 if (!InterfaceDescriptor
)
1218 DPRINT1("[%s] No such interface Alternate %x InterfaceNumber %x\n", m_USBType
, InterfaceInfo
->AlternateSetting
, InterfaceInfo
->InterfaceNumber
);
1219 return STATUS_UNSUCCESSFUL
;
1222 // build interface descriptor
1223 Status
= BuildInterfaceDescriptor(ConfigurationIndex
, InterfaceDescriptor
, InterfaceInfo
, &UsbInterface
);
1224 if (!NT_SUCCESS(Status
))
1227 DPRINT1("[%s] Failed to build interface descriptor Status %x\n", m_USBType
, Status
);
1232 // assert on pipe length mismatch
1233 DPRINT1("NumberOfPipes %lu Endpoints %lu Length %lu\n", InterfaceInfo
->NumberOfPipes
, UsbInterface
->InterfaceDescriptor
->bNumEndpoints
, InterfaceInfo
->Length
);
1236 ASSERT(GET_USBD_INTERFACE_SIZE(UsbInterface
->InterfaceDescriptor
->bNumEndpoints
) == InterfaceInfo
->Length
);
1238 // store number of pipes
1239 InterfaceInfo
->NumberOfPipes
= UsbInterface
->InterfaceDescriptor
->bNumEndpoints
;
1241 // copy pipe handles
1242 for (PipeIndex
= 0; PipeIndex
< UsbInterface
->InterfaceDescriptor
->bNumEndpoints
; PipeIndex
++)
1245 DPRINT1("PipeIndex %lu\n", PipeIndex
);
1246 DPRINT1("EndpointAddress %x\n", InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
);
1247 DPRINT1("Interval %c\n", InterfaceInfo
->Pipes
[PipeIndex
].Interval
);
1248 DPRINT1("MaximumPacketSize %hu\n", InterfaceInfo
->Pipes
[PipeIndex
].MaximumPacketSize
);
1249 DPRINT1("MaximumTransferSize %lu\n", InterfaceInfo
->Pipes
[PipeIndex
].MaximumTransferSize
);
1250 DPRINT1("PipeFlags %lu\n", InterfaceInfo
->Pipes
[PipeIndex
].PipeFlags
);
1251 DPRINT1("PipeType %d\n", InterfaceInfo
->Pipes
[PipeIndex
].PipeType
);
1252 DPRINT1("UsbEndPoint %x\n", InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
);
1255 ASSERT(InterfaceInfo
->Pipes
[PipeIndex
].EndpointAddress
== UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bEndpointAddress
);
1256 ASSERT(InterfaceInfo
->Pipes
[PipeIndex
].Interval
== UsbInterface
->EndPoints
[PipeIndex
].EndPointDescriptor
.bInterval
);
1258 // store pipe handle
1259 InterfaceInfo
->Pipes
[PipeIndex
].PipeHandle
= &UsbInterface
->EndPoints
[PipeIndex
];
1261 // data toggle is reset on select interface requests
1262 UsbInterface
->EndPoints
[PipeIndex
].DataToggle
= FALSE
;
1272 CUSBDevice::AbortPipe(
1273 IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
)
1276 // let it handle usb queue
1279 ASSERT(m_DeviceAddress
);
1284 return m_Queue
->AbortDevicePipe(m_DeviceAddress
, EndpointDescriptor
);
1288 CUSBDevice::GetMaxPacketSize()
1290 return m_DeviceDescriptor
.bMaxPacketSize0
;
1294 //----------------------------------------------------------------------------------------
1298 PUSBDEVICE
*OutDevice
)
1303 // allocate controller
1305 This
= new(NonPagedPool
, TAG_USBLIB
) CUSBDevice(0);
1309 // failed to allocate
1311 return STATUS_INSUFFICIENT_RESOURCES
;
1315 // add reference count
1322 *OutDevice
= (PUSBDEVICE
)This
;
1327 return STATUS_SUCCESS
;