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
22 #define WIN32_NO_STATUS
28 #include "ddk/usbdlib.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(usbd
);
33 PURB WINAPI
USBD_CreateConfigurationRequest(
34 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
, PUSHORT Siz
)
37 USBD_INTERFACE_LIST_ENTRY
*interfaceList
;
38 ULONG interfaceListSize
;
39 USB_INTERFACE_DESCRIPTOR
*interfaceDesc
;
42 TRACE( "(%p, %p)\n", ConfigurationDescriptor
, Siz
);
44 /* http://www.microsoft.com/whdc/archive/usbfaq.mspx
45 * claims USBD_CreateConfigurationRequest doesn't support > 1 interface,
46 * but is this on Windows 98 only or all versions?
50 interfaceListSize
= (ConfigurationDescriptor
->bNumInterfaces
+ 1) * sizeof(USBD_INTERFACE_LIST_ENTRY
);
51 interfaceList
= ExAllocatePool( NonPagedPool
, interfaceListSize
);
54 RtlZeroMemory( interfaceList
, interfaceListSize
);
55 interfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
56 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
57 ConfigurationDescriptor
, USB_INTERFACE_DESCRIPTOR_TYPE
);
58 for (i
= 0; i
< ConfigurationDescriptor
->bNumInterfaces
&& interfaceDesc
!= NULL
; i
++)
60 interfaceList
[i
].InterfaceDescriptor
= interfaceDesc
;
61 interfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
62 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
63 interfaceDesc
+ 1, USB_INTERFACE_DESCRIPTOR_TYPE
);
65 urb
= USBD_CreateConfigurationRequestEx( ConfigurationDescriptor
, interfaceList
);
67 *Siz
= urb
->UrbHeader
.Length
;
68 ExFreePool( interfaceList
);
73 PURB WINAPI
USBD_CreateConfigurationRequestEx(
74 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
75 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
)
79 USBD_INTERFACE_LIST_ENTRY
*interfaceEntry
;
80 ULONG interfaceCount
= 0;
82 TRACE( "(%p, %p)\n", ConfigurationDescriptor
, InterfaceList
);
84 size
= sizeof(struct _URB_SELECT_CONFIGURATION
);
85 for (interfaceEntry
= InterfaceList
; interfaceEntry
->InterfaceDescriptor
; interfaceEntry
++)
88 size
+= (interfaceEntry
->InterfaceDescriptor
->bNumEndpoints
- 1) *
89 sizeof(USBD_PIPE_INFORMATION
);
91 size
+= (interfaceCount
- 1) * sizeof(USBD_INTERFACE_INFORMATION
);
93 urb
= ExAllocatePool( NonPagedPool
, size
);
96 USBD_INTERFACE_INFORMATION
*interfaceInfo
;
98 RtlZeroMemory( urb
, size
);
99 urb
->UrbSelectConfiguration
.Hdr
.Length
= size
;
100 urb
->UrbSelectConfiguration
.Hdr
.Function
= URB_FUNCTION_SELECT_CONFIGURATION
;
101 urb
->UrbSelectConfiguration
.ConfigurationDescriptor
= ConfigurationDescriptor
;
102 interfaceInfo
= &urb
->UrbSelectConfiguration
.Interface
;
103 for (interfaceEntry
= InterfaceList
; interfaceEntry
->InterfaceDescriptor
; interfaceEntry
++)
106 USB_INTERFACE_DESCRIPTOR
*currentInterface
;
107 USB_ENDPOINT_DESCRIPTOR
*endpointDescriptor
;
108 interfaceInfo
->InterfaceNumber
= interfaceEntry
->InterfaceDescriptor
->bInterfaceNumber
;
109 interfaceInfo
->AlternateSetting
= interfaceEntry
->InterfaceDescriptor
->bAlternateSetting
;
110 interfaceInfo
->Class
= interfaceEntry
->InterfaceDescriptor
->bInterfaceClass
;
111 interfaceInfo
->SubClass
= interfaceEntry
->InterfaceDescriptor
->bInterfaceSubClass
;
112 interfaceInfo
->Protocol
= interfaceEntry
->InterfaceDescriptor
->bInterfaceProtocol
;
113 interfaceInfo
->NumberOfPipes
= interfaceEntry
->InterfaceDescriptor
->bNumEndpoints
;
114 currentInterface
= USBD_ParseConfigurationDescriptorEx(
115 ConfigurationDescriptor
, ConfigurationDescriptor
,
116 interfaceEntry
->InterfaceDescriptor
->bInterfaceNumber
, -1, -1, -1, -1 );
117 endpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) USBD_ParseDescriptors(
118 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
119 currentInterface
, USB_ENDPOINT_DESCRIPTOR_TYPE
);
120 for (i
= 0; i
< interfaceInfo
->NumberOfPipes
&& endpointDescriptor
; i
++)
122 interfaceInfo
->Pipes
[i
].MaximumPacketSize
= endpointDescriptor
->wMaxPacketSize
;
123 interfaceInfo
->Pipes
[i
].EndpointAddress
= endpointDescriptor
->bEndpointAddress
;
124 interfaceInfo
->Pipes
[i
].Interval
= endpointDescriptor
->bInterval
;
125 switch (endpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
)
127 case USB_ENDPOINT_TYPE_CONTROL
:
128 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeControl
;
130 case USB_ENDPOINT_TYPE_BULK
:
131 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeBulk
;
133 case USB_ENDPOINT_TYPE_INTERRUPT
:
134 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeInterrupt
;
136 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
137 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeIsochronous
;
140 endpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) USBD_ParseDescriptors(
141 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
142 endpointDescriptor
+ 1, USB_ENDPOINT_DESCRIPTOR_TYPE
);
144 interfaceInfo
->Length
= sizeof(USBD_INTERFACE_INFORMATION
) +
145 (i
- 1) * sizeof(USBD_PIPE_INFORMATION
);
146 interfaceEntry
->Interface
= interfaceInfo
;
147 interfaceInfo
= (USBD_INTERFACE_INFORMATION
*)(((char*)interfaceInfo
)+interfaceInfo
->Length
);
153 VOID WINAPI
USBD_GetUSBDIVersion(
154 PUSBD_VERSION_INFORMATION VersionInformation
)
156 TRACE( "(%p)\n", VersionInformation
);
157 /* Emulate Windows 2000 (= 0x300) for now */
158 VersionInformation
->USBDI_Version
= 0x300;
159 VersionInformation
->Supported_USB_Version
= 0x200;
162 PUSB_INTERFACE_DESCRIPTOR WINAPI
USBD_ParseConfigurationDescriptorEx(
163 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
164 PVOID StartPosition
, LONG InterfaceNumber
,
165 LONG AlternateSetting
, LONG InterfaceClass
,
166 LONG InterfaceSubClass
, LONG InterfaceProtocol
)
168 /* http://blogs.msdn.com/usbcoreblog/archive/2009/12/12/
169 * what-is-the-right-way-to-validate-and-parse-configuration-descriptors.aspx
172 PUSB_INTERFACE_DESCRIPTOR interface
;
174 TRACE( "(%p, %p, %ld, %ld, %ld, %ld, %ld)\n", ConfigurationDescriptor
,
175 StartPosition
, InterfaceNumber
, AlternateSetting
,
176 InterfaceClass
, InterfaceSubClass
, InterfaceProtocol
);
178 interface
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
179 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
180 StartPosition
, USB_INTERFACE_DESCRIPTOR_TYPE
);
181 while (interface
!= NULL
)
183 if ((InterfaceNumber
== -1 || interface
->bInterfaceNumber
== InterfaceNumber
) &&
184 (AlternateSetting
== -1 || interface
->bAlternateSetting
== AlternateSetting
) &&
185 (InterfaceClass
== -1 || interface
->bInterfaceClass
== InterfaceClass
) &&
186 (InterfaceSubClass
== -1 || interface
->bInterfaceSubClass
== InterfaceSubClass
) &&
187 (InterfaceProtocol
== -1 || interface
->bInterfaceProtocol
== InterfaceProtocol
))
191 interface
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
192 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
193 interface
+ 1, USB_INTERFACE_DESCRIPTOR_TYPE
);
198 PUSB_INTERFACE_DESCRIPTOR WINAPI
USBD_ParseConfigurationDescriptor(
199 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
, UCHAR InterfaceNumber
,
200 UCHAR AlternateSetting
)
202 TRACE( "(%p, %u, %u)\n", ConfigurationDescriptor
, InterfaceNumber
, AlternateSetting
);
203 return USBD_ParseConfigurationDescriptorEx( ConfigurationDescriptor
, ConfigurationDescriptor
,
204 InterfaceNumber
, AlternateSetting
, -1, -1, -1 );
207 PUSB_COMMON_DESCRIPTOR WINAPI
USBD_ParseDescriptors(
208 PVOID DescriptorBuffer
,
211 LONG DescriptorType
)
213 PUSB_COMMON_DESCRIPTOR common
;
215 TRACE( "(%p, %lu, %p, %ld)\n", DescriptorBuffer
, TotalLength
, StartPosition
, DescriptorType
);
217 for (common
= (PUSB_COMMON_DESCRIPTOR
)DescriptorBuffer
;
218 ((char*)common
) + sizeof(USB_COMMON_DESCRIPTOR
) <= ((char*)DescriptorBuffer
) + TotalLength
;
219 common
= (PUSB_COMMON_DESCRIPTOR
)(((char*)common
) + common
->bLength
))
221 if (StartPosition
<= (PVOID
)common
&& common
->bDescriptorType
== DescriptorType
)
227 USBD_STATUS WINAPI
USBD_ValidateConfigurationDescriptor(
228 PUSB_CONFIGURATION_DESCRIPTOR descr
,
234 FIXME( "(%p, %lu, %u, %p, %lu) partial stub!\n", descr
, length
, level
, offset
, tag
);
236 if (offset
) *offset
= 0;
239 length
< sizeof(USB_CONFIGURATION_DESCRIPTOR
) ||
240 descr
->bLength
< sizeof(USB_CONFIGURATION_DESCRIPTOR
) ||
241 descr
->wTotalLength
< descr
->bNumInterfaces
* sizeof(USB_CONFIGURATION_DESCRIPTOR
)
242 ) return USBD_STATUS_ERROR
;
244 return USBD_STATUS_SUCCESS
;
247 ULONG WINAPI
USBD_GetInterfaceLength(
248 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
251 PUSB_COMMON_DESCRIPTOR common
;
252 ULONG total
= InterfaceDescriptor
->bLength
;
254 TRACE( "(%p, %p)\n", InterfaceDescriptor
, BufferEnd
);
256 for (common
= (PUSB_COMMON_DESCRIPTOR
)(InterfaceDescriptor
+ 1);
257 (((PUCHAR
)common
) + sizeof(USB_COMMON_DESCRIPTOR
)) <= BufferEnd
&&
258 common
->bDescriptorType
!= USB_INTERFACE_DESCRIPTOR_TYPE
;
259 common
= (PUSB_COMMON_DESCRIPTOR
)(((char*)common
) + common
->bLength
))
261 total
+= common
->bLength
;
266 NTSTATUS WINAPI
DriverEntry( DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
268 TRACE( "(%p, %s)\n", driver
, debugstr_w(path
->Buffer
) );
269 return STATUS_SUCCESS
;