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
24 #define WIN32_NO_STATUS
30 #include "ddk/usbdlib.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(usbd
);
35 PURB WINAPI
USBD_CreateConfigurationRequest(
36 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
, PUSHORT Siz
)
39 USBD_INTERFACE_LIST_ENTRY
*interfaceList
;
40 ULONG interfaceListSize
;
41 USB_INTERFACE_DESCRIPTOR
*interfaceDesc
;
44 TRACE( "(%p, %p)\n", ConfigurationDescriptor
, Siz
);
46 /* http://www.microsoft.com/whdc/archive/usbfaq.mspx
47 * claims USBD_CreateConfigurationRequest doesn't support > 1 interface,
48 * but is this on Windows 98 only or all versions?
52 interfaceListSize
= (ConfigurationDescriptor
->bNumInterfaces
+ 1) * sizeof(USBD_INTERFACE_LIST_ENTRY
);
53 interfaceList
= ExAllocatePool( NonPagedPool
, interfaceListSize
);
56 RtlZeroMemory( interfaceList
, interfaceListSize
);
57 interfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
58 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
59 ConfigurationDescriptor
, USB_INTERFACE_DESCRIPTOR_TYPE
);
60 for (i
= 0; i
< ConfigurationDescriptor
->bNumInterfaces
&& interfaceDesc
!= NULL
; i
++)
62 interfaceList
[i
].InterfaceDescriptor
= interfaceDesc
;
63 interfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
64 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
65 interfaceDesc
+ 1, USB_INTERFACE_DESCRIPTOR_TYPE
);
67 urb
= USBD_CreateConfigurationRequestEx( ConfigurationDescriptor
, interfaceList
);
69 *Siz
= urb
->u
.UrbHeader
.Length
;
70 ExFreePool( interfaceList
);
75 PURB WINAPI
USBD_CreateConfigurationRequestEx(
76 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
77 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
)
81 USBD_INTERFACE_LIST_ENTRY
*interfaceEntry
;
82 ULONG interfaceCount
= 0;
84 TRACE( "(%p, %p)\n", ConfigurationDescriptor
, InterfaceList
);
86 size
= sizeof(struct _URB_SELECT_CONFIGURATION
);
87 for (interfaceEntry
= InterfaceList
; interfaceEntry
->InterfaceDescriptor
; interfaceEntry
++)
90 size
+= (interfaceEntry
->InterfaceDescriptor
->bNumEndpoints
- 1) *
91 sizeof(USBD_PIPE_INFORMATION
);
93 size
+= (interfaceCount
- 1) * sizeof(USBD_INTERFACE_INFORMATION
);
95 urb
= ExAllocatePool( NonPagedPool
, size
);
98 USBD_INTERFACE_INFORMATION
*interfaceInfo
;
100 RtlZeroMemory( urb
, size
);
101 urb
->u
.UrbSelectConfiguration
.Hdr
.Length
= size
;
102 urb
->u
.UrbSelectConfiguration
.Hdr
.Function
= URB_FUNCTION_SELECT_CONFIGURATION
;
103 urb
->u
.UrbSelectConfiguration
.ConfigurationDescriptor
= ConfigurationDescriptor
;
104 interfaceInfo
= &urb
->u
.UrbSelectConfiguration
.Interface
;
105 for (interfaceEntry
= InterfaceList
; interfaceEntry
->InterfaceDescriptor
; interfaceEntry
++)
108 USB_INTERFACE_DESCRIPTOR
*currentInterface
;
109 USB_ENDPOINT_DESCRIPTOR
*endpointDescriptor
;
110 interfaceInfo
->InterfaceNumber
= interfaceEntry
->InterfaceDescriptor
->bInterfaceNumber
;
111 interfaceInfo
->AlternateSetting
= interfaceEntry
->InterfaceDescriptor
->bAlternateSetting
;
112 interfaceInfo
->Class
= interfaceEntry
->InterfaceDescriptor
->bInterfaceClass
;
113 interfaceInfo
->SubClass
= interfaceEntry
->InterfaceDescriptor
->bInterfaceSubClass
;
114 interfaceInfo
->Protocol
= interfaceEntry
->InterfaceDescriptor
->bInterfaceProtocol
;
115 interfaceInfo
->NumberOfPipes
= interfaceEntry
->InterfaceDescriptor
->bNumEndpoints
;
116 currentInterface
= USBD_ParseConfigurationDescriptorEx(
117 ConfigurationDescriptor
, ConfigurationDescriptor
,
118 interfaceEntry
->InterfaceDescriptor
->bInterfaceNumber
, -1, -1, -1, -1 );
119 endpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) USBD_ParseDescriptors(
120 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
121 currentInterface
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
122 for (i
= 0; i
< interfaceInfo
->NumberOfPipes
&& endpointDescriptor
; i
++)
124 interfaceInfo
->Pipes
[i
].MaximumPacketSize
= endpointDescriptor
->wMaxPacketSize
;
125 interfaceInfo
->Pipes
[i
].EndpointAddress
= endpointDescriptor
->bEndpointAddress
;
126 interfaceInfo
->Pipes
[i
].Interval
= endpointDescriptor
->bInterval
;
127 switch (endpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
)
129 case USB_ENDPOINT_TYPE_CONTROL
:
130 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeControl
;
132 case USB_ENDPOINT_TYPE_BULK
:
133 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeBulk
;
135 case USB_ENDPOINT_TYPE_INTERRUPT
:
136 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeInterrupt
;
138 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
139 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeIsochronous
;
142 endpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) USBD_ParseDescriptors(
143 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
144 endpointDescriptor
+ 1, USB_ENDPOINT_DESCRIPTOR_TYPE
);
146 interfaceInfo
->Length
= sizeof(USBD_INTERFACE_INFORMATION
) +
147 (i
- 1) * sizeof(USBD_PIPE_INFORMATION
);
148 interfaceEntry
->Interface
= interfaceInfo
;
149 interfaceInfo
= (USBD_INTERFACE_INFORMATION
*)(((char*)interfaceInfo
)+interfaceInfo
->Length
);
155 VOID WINAPI
USBD_GetUSBDIVersion(
156 PUSBD_VERSION_INFORMATION VersionInformation
)
158 TRACE( "(%p)\n", VersionInformation
);
159 /* Emulate Windows 2000 (= 0x300) for now */
160 VersionInformation
->USBDI_Version
= 0x300;
161 VersionInformation
->Supported_USB_Version
= 0x200;
164 PUSB_INTERFACE_DESCRIPTOR WINAPI
USBD_ParseConfigurationDescriptorEx(
165 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
166 PVOID StartPosition
, LONG InterfaceNumber
,
167 LONG AlternateSetting
, LONG InterfaceClass
,
168 LONG InterfaceSubClass
, LONG InterfaceProtocol
)
170 /* http://blogs.msdn.com/usbcoreblog/archive/2009/12/12/
171 * what-is-the-right-way-to-validate-and-parse-configuration-descriptors.aspx
174 PUSB_INTERFACE_DESCRIPTOR interface
;
176 TRACE( "(%p, %p, %ld, %ld, %ld, %ld, %ld)\n", ConfigurationDescriptor
,
177 StartPosition
, InterfaceNumber
, AlternateSetting
,
178 InterfaceClass
, InterfaceSubClass
, InterfaceProtocol
);
180 interface
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
181 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
182 StartPosition
, USB_INTERFACE_DESCRIPTOR_TYPE
);
183 while (interface
!= NULL
)
185 if ((InterfaceNumber
== -1 || interface
->bInterfaceNumber
== InterfaceNumber
) &&
186 (AlternateSetting
== -1 || interface
->bAlternateSetting
== AlternateSetting
) &&
187 (InterfaceClass
== -1 || interface
->bInterfaceClass
== InterfaceClass
) &&
188 (InterfaceSubClass
== -1 || interface
->bInterfaceSubClass
== InterfaceSubClass
) &&
189 (InterfaceProtocol
== -1 || interface
->bInterfaceProtocol
== InterfaceProtocol
))
193 interface
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
194 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
195 interface
+ 1, USB_INTERFACE_DESCRIPTOR_TYPE
);
200 PUSB_INTERFACE_DESCRIPTOR WINAPI
USBD_ParseConfigurationDescriptor(
201 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
, UCHAR InterfaceNumber
,
202 UCHAR AlternateSetting
)
204 TRACE( "(%p, %u, %u)\n", ConfigurationDescriptor
, InterfaceNumber
, AlternateSetting
);
205 return USBD_ParseConfigurationDescriptorEx( ConfigurationDescriptor
, ConfigurationDescriptor
,
206 InterfaceNumber
, AlternateSetting
, -1, -1, -1 );
209 PUSB_COMMON_DESCRIPTOR WINAPI
USBD_ParseDescriptors(
210 PVOID DescriptorBuffer
,
213 LONG DescriptorType
)
215 PUSB_COMMON_DESCRIPTOR common
;
217 TRACE( "(%p, %lu, %p, %ld)\n", DescriptorBuffer
, TotalLength
, StartPosition
, DescriptorType
);
219 for (common
= (PUSB_COMMON_DESCRIPTOR
)DescriptorBuffer
;
220 ((char*)common
) + sizeof(USB_COMMON_DESCRIPTOR
) <= ((char*)DescriptorBuffer
) + TotalLength
;
221 common
= (PUSB_COMMON_DESCRIPTOR
)(((char*)common
) + common
->bLength
))
223 if (StartPosition
<= (PVOID
)common
&& common
->bDescriptorType
== DescriptorType
)
229 USBD_STATUS WINAPI
USBD_ValidateConfigurationDescriptor(
230 PUSB_CONFIGURATION_DESCRIPTOR descr
,
236 FIXME( "(%p, %lu, %u, %p, %lu) partial stub!\n", descr
, length
, level
, offset
, tag
);
238 if (offset
) *offset
= 0;
241 length
< sizeof(USB_CONFIGURATION_DESCRIPTOR
) ||
242 descr
->bLength
< sizeof(USB_CONFIGURATION_DESCRIPTOR
) ||
243 descr
->wTotalLength
< descr
->bNumInterfaces
* sizeof(USB_CONFIGURATION_DESCRIPTOR
)
244 ) return USBD_STATUS_ERROR
;
246 return USBD_STATUS_SUCCESS
;
249 ULONG WINAPI
USBD_GetInterfaceLength(
250 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
253 PUSB_COMMON_DESCRIPTOR common
;
254 ULONG total
= InterfaceDescriptor
->bLength
;
256 TRACE( "(%p, %p)\n", InterfaceDescriptor
, BufferEnd
);
258 for (common
= (PUSB_COMMON_DESCRIPTOR
)(InterfaceDescriptor
+ 1);
259 (((PUCHAR
)common
) + sizeof(USB_COMMON_DESCRIPTOR
)) <= BufferEnd
&&
260 common
->bDescriptorType
!= USB_INTERFACE_DESCRIPTOR_TYPE
;
261 common
= (PUSB_COMMON_DESCRIPTOR
)(((char*)common
) + common
->bLength
))
263 total
+= common
->bLength
;
268 NTSTATUS WINAPI
DriverEntry( DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
270 TRACE( "(%p, %s)\n", driver
, debugstr_w(path
->Buffer
) );
271 return STATUS_SUCCESS
;