2 * Copyright (C) 2010 Damjan Jovanovic
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
25 #define WIN32_NO_STATUS
31 #include "ddk/usbdlib.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(usbd
);
36 PURB WINAPI
USBD_CreateConfigurationRequest(
37 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
, PUSHORT Siz
)
40 USBD_INTERFACE_LIST_ENTRY
*interfaceList
;
41 ULONG interfaceListSize
;
42 USB_INTERFACE_DESCRIPTOR
*interfaceDesc
;
45 TRACE( "(%p, %p)\n", ConfigurationDescriptor
, Siz
);
47 /* http://www.microsoft.com/whdc/archive/usbfaq.mspx
48 * claims USBD_CreateConfigurationRequest doesn't support > 1 interface,
49 * but is this on Windows 98 only or all versions?
53 interfaceListSize
= (ConfigurationDescriptor
->bNumInterfaces
+ 1) * sizeof(USBD_INTERFACE_LIST_ENTRY
);
54 interfaceList
= ExAllocatePool( NonPagedPool
, interfaceListSize
);
57 RtlZeroMemory( interfaceList
, interfaceListSize
);
58 interfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
59 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
60 ConfigurationDescriptor
, USB_INTERFACE_DESCRIPTOR_TYPE
);
61 for (i
= 0; i
< ConfigurationDescriptor
->bNumInterfaces
&& interfaceDesc
!= NULL
; i
++)
63 interfaceList
[i
].InterfaceDescriptor
= interfaceDesc
;
64 interfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
65 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
66 interfaceDesc
+ 1, USB_INTERFACE_DESCRIPTOR_TYPE
);
68 urb
= USBD_CreateConfigurationRequestEx( ConfigurationDescriptor
, interfaceList
);
70 *Siz
= urb
->u
.UrbHeader
.Length
;
71 ExFreePool( interfaceList
);
76 PURB WINAPI
USBD_CreateConfigurationRequestEx(
77 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
78 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
)
82 USBD_INTERFACE_LIST_ENTRY
*interfaceEntry
;
83 ULONG interfaceCount
= 0;
85 TRACE( "(%p, %p)\n", ConfigurationDescriptor
, InterfaceList
);
87 size
= sizeof(struct _URB_SELECT_CONFIGURATION
);
88 for (interfaceEntry
= InterfaceList
; interfaceEntry
->InterfaceDescriptor
; interfaceEntry
++)
91 size
+= (interfaceEntry
->InterfaceDescriptor
->bNumEndpoints
- 1) *
92 sizeof(USBD_PIPE_INFORMATION
);
94 size
+= (interfaceCount
- 1) * sizeof(USBD_INTERFACE_INFORMATION
);
96 urb
= ExAllocatePool( NonPagedPool
, size
);
99 USBD_INTERFACE_INFORMATION
*interfaceInfo
;
101 RtlZeroMemory( urb
, size
);
102 urb
->u
.UrbSelectConfiguration
.Hdr
.Length
= size
;
103 urb
->u
.UrbSelectConfiguration
.Hdr
.Function
= URB_FUNCTION_SELECT_CONFIGURATION
;
104 urb
->u
.UrbSelectConfiguration
.ConfigurationDescriptor
= ConfigurationDescriptor
;
105 interfaceInfo
= &urb
->u
.UrbSelectConfiguration
.Interface
;
106 for (interfaceEntry
= InterfaceList
; interfaceEntry
->InterfaceDescriptor
; interfaceEntry
++)
109 USB_INTERFACE_DESCRIPTOR
*currentInterface
;
110 USB_ENDPOINT_DESCRIPTOR
*endpointDescriptor
;
111 interfaceInfo
->InterfaceNumber
= interfaceEntry
->InterfaceDescriptor
->bInterfaceNumber
;
112 interfaceInfo
->AlternateSetting
= interfaceEntry
->InterfaceDescriptor
->bAlternateSetting
;
113 interfaceInfo
->Class
= interfaceEntry
->InterfaceDescriptor
->bInterfaceClass
;
114 interfaceInfo
->SubClass
= interfaceEntry
->InterfaceDescriptor
->bInterfaceSubClass
;
115 interfaceInfo
->Protocol
= interfaceEntry
->InterfaceDescriptor
->bInterfaceProtocol
;
116 interfaceInfo
->NumberOfPipes
= interfaceEntry
->InterfaceDescriptor
->bNumEndpoints
;
117 currentInterface
= USBD_ParseConfigurationDescriptorEx(
118 ConfigurationDescriptor
, ConfigurationDescriptor
,
119 interfaceEntry
->InterfaceDescriptor
->bInterfaceNumber
, -1, -1, -1, -1 );
120 endpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) USBD_ParseDescriptors(
121 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
122 currentInterface
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
123 for (i
= 0; i
< interfaceInfo
->NumberOfPipes
&& endpointDescriptor
; i
++)
125 interfaceInfo
->Pipes
[i
].MaximumPacketSize
= endpointDescriptor
->wMaxPacketSize
;
126 interfaceInfo
->Pipes
[i
].EndpointAddress
= endpointDescriptor
->bEndpointAddress
;
127 interfaceInfo
->Pipes
[i
].Interval
= endpointDescriptor
->bInterval
;
128 if (endpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_CONTROL
)
129 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeControl
;
130 else if (endpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_BULK
)
131 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeBulk
;
132 else if (endpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_INTERRUPT
)
133 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeInterrupt
;
134 else if (endpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_ISOCHRONOUS
)
135 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeIsochronous
;
136 endpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) USBD_ParseDescriptors(
137 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
138 endpointDescriptor
+ 1, USB_ENDPOINT_DESCRIPTOR_TYPE
);
140 interfaceInfo
->Length
= sizeof(USBD_INTERFACE_INFORMATION
) +
141 (i
- 1) * sizeof(USBD_PIPE_INFORMATION
);
142 interfaceEntry
->Interface
= interfaceInfo
;
143 interfaceInfo
= (USBD_INTERFACE_INFORMATION
*)(((char*)interfaceInfo
)+interfaceInfo
->Length
);
149 VOID WINAPI
USBD_GetUSBDIVersion(
150 PUSBD_VERSION_INFORMATION VersionInformation
)
152 TRACE( "(%p)\n", VersionInformation
);
153 /* Emulate Windows 2000 (= 0x300) for now */
154 VersionInformation
->USBDI_Version
= 0x300;
155 VersionInformation
->Supported_USB_Version
= 0x200;
158 PUSB_INTERFACE_DESCRIPTOR WINAPI
USBD_ParseConfigurationDescriptorEx(
159 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
160 PVOID StartPosition
, LONG InterfaceNumber
,
161 LONG AlternateSetting
, LONG InterfaceClass
,
162 LONG InterfaceSubClass
, LONG InterfaceProtocol
)
164 /* http://blogs.msdn.com/usbcoreblog/archive/2009/12/12/
165 * what-is-the-right-way-to-validate-and-parse-configuration-descriptors.aspx
168 PUSB_INTERFACE_DESCRIPTOR interface
;
170 TRACE( "(%p, %p, %d, %d, %d, %d, %d)\n", ConfigurationDescriptor
,
171 StartPosition
, InterfaceNumber
, AlternateSetting
,
172 InterfaceClass
, InterfaceSubClass
, InterfaceProtocol
);
174 interface
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
175 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
176 StartPosition
, USB_INTERFACE_DESCRIPTOR_TYPE
);
177 while (interface
!= NULL
)
179 if ((InterfaceNumber
== -1 || interface
->bInterfaceNumber
== InterfaceNumber
) &&
180 (AlternateSetting
== -1 || interface
->bAlternateSetting
== AlternateSetting
) &&
181 (InterfaceClass
== -1 || interface
->bInterfaceClass
== InterfaceClass
) &&
182 (InterfaceSubClass
== -1 || interface
->bInterfaceSubClass
== InterfaceSubClass
) &&
183 (InterfaceProtocol
== -1 || interface
->bInterfaceProtocol
== InterfaceProtocol
))
187 interface
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
188 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
189 interface
+ 1, USB_INTERFACE_DESCRIPTOR_TYPE
);
194 PUSB_COMMON_DESCRIPTOR WINAPI
USBD_ParseDescriptors(
195 PVOID DescriptorBuffer
,
198 LONG DescriptorType
)
200 PUSB_COMMON_DESCRIPTOR common
;
202 TRACE( "(%p, %u, %p, %d)\n", DescriptorBuffer
, TotalLength
, StartPosition
, DescriptorType
);
204 for (common
= (PUSB_COMMON_DESCRIPTOR
)DescriptorBuffer
;
205 ((char*)common
) + sizeof(USB_COMMON_DESCRIPTOR
) <= ((char*)DescriptorBuffer
) + TotalLength
;
206 common
= (PUSB_COMMON_DESCRIPTOR
)(((char*)common
) + common
->bLength
))
208 if (StartPosition
<= (PVOID
)common
&& common
->bDescriptorType
== DescriptorType
)
214 ULONG WINAPI
USBD_GetInterfaceLength(
215 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
218 PUSB_COMMON_DESCRIPTOR common
;
219 ULONG total
= InterfaceDescriptor
->bLength
;
221 TRACE( "(%p, %p)\n", InterfaceDescriptor
, BufferEnd
);
223 for (common
= (PUSB_COMMON_DESCRIPTOR
)(InterfaceDescriptor
+ 1);
224 (((PUCHAR
)common
) + sizeof(USB_COMMON_DESCRIPTOR
)) <= BufferEnd
&&
225 common
->bDescriptorType
!= USB_INTERFACE_DESCRIPTOR_TYPE
;
226 common
= (PUSB_COMMON_DESCRIPTOR
)(((char*)common
) + common
->bLength
))
228 total
+= common
->bLength
;
233 NTSTATUS WINAPI
DriverEntry( DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
235 TRACE( "(%p, %s)\n", driver
, debugstr_w(path
->Buffer
) );
236 return STATUS_SUCCESS
;