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 switch (endpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
)
130 case USB_ENDPOINT_TYPE_CONTROL
:
131 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeControl
;
133 case USB_ENDPOINT_TYPE_BULK
:
134 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeBulk
;
136 case USB_ENDPOINT_TYPE_INTERRUPT
:
137 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeInterrupt
;
139 case USB_ENDPOINT_TYPE_ISOCHRONOUS
:
140 interfaceInfo
->Pipes
[i
].PipeType
= UsbdPipeTypeIsochronous
;
143 endpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
) USBD_ParseDescriptors(
144 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
145 endpointDescriptor
+ 1, USB_ENDPOINT_DESCRIPTOR_TYPE
);
147 interfaceInfo
->Length
= sizeof(USBD_INTERFACE_INFORMATION
) +
148 (i
- 1) * sizeof(USBD_PIPE_INFORMATION
);
149 interfaceEntry
->Interface
= interfaceInfo
;
150 interfaceInfo
= (USBD_INTERFACE_INFORMATION
*)(((char*)interfaceInfo
)+interfaceInfo
->Length
);
156 VOID WINAPI
USBD_GetUSBDIVersion(
157 PUSBD_VERSION_INFORMATION VersionInformation
)
159 TRACE( "(%p)\n", VersionInformation
);
160 /* Emulate Windows 2000 (= 0x300) for now */
161 VersionInformation
->USBDI_Version
= 0x300;
162 VersionInformation
->Supported_USB_Version
= 0x200;
165 PUSB_INTERFACE_DESCRIPTOR WINAPI
USBD_ParseConfigurationDescriptorEx(
166 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
167 PVOID StartPosition
, LONG InterfaceNumber
,
168 LONG AlternateSetting
, LONG InterfaceClass
,
169 LONG InterfaceSubClass
, LONG InterfaceProtocol
)
171 /* http://blogs.msdn.com/usbcoreblog/archive/2009/12/12/
172 * what-is-the-right-way-to-validate-and-parse-configuration-descriptors.aspx
175 PUSB_INTERFACE_DESCRIPTOR interface
;
177 TRACE( "(%p, %p, %d, %d, %d, %d, %d)\n", ConfigurationDescriptor
,
178 StartPosition
, InterfaceNumber
, AlternateSetting
,
179 InterfaceClass
, InterfaceSubClass
, InterfaceProtocol
);
181 interface
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
182 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
183 StartPosition
, USB_INTERFACE_DESCRIPTOR_TYPE
);
184 while (interface
!= NULL
)
186 if ((InterfaceNumber
== -1 || interface
->bInterfaceNumber
== InterfaceNumber
) &&
187 (AlternateSetting
== -1 || interface
->bAlternateSetting
== AlternateSetting
) &&
188 (InterfaceClass
== -1 || interface
->bInterfaceClass
== InterfaceClass
) &&
189 (InterfaceSubClass
== -1 || interface
->bInterfaceSubClass
== InterfaceSubClass
) &&
190 (InterfaceProtocol
== -1 || interface
->bInterfaceProtocol
== InterfaceProtocol
))
194 interface
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(
195 ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
,
196 interface
+ 1, USB_INTERFACE_DESCRIPTOR_TYPE
);
201 PUSB_COMMON_DESCRIPTOR WINAPI
USBD_ParseDescriptors(
202 PVOID DescriptorBuffer
,
205 LONG DescriptorType
)
207 PUSB_COMMON_DESCRIPTOR common
;
209 TRACE( "(%p, %u, %p, %d)\n", DescriptorBuffer
, TotalLength
, StartPosition
, DescriptorType
);
211 for (common
= (PUSB_COMMON_DESCRIPTOR
)DescriptorBuffer
;
212 ((char*)common
) + sizeof(USB_COMMON_DESCRIPTOR
) <= ((char*)DescriptorBuffer
) + TotalLength
;
213 common
= (PUSB_COMMON_DESCRIPTOR
)(((char*)common
) + common
->bLength
))
215 if (StartPosition
<= (PVOID
)common
&& common
->bDescriptorType
== DescriptorType
)
221 ULONG WINAPI
USBD_GetInterfaceLength(
222 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
225 PUSB_COMMON_DESCRIPTOR common
;
226 ULONG total
= InterfaceDescriptor
->bLength
;
228 TRACE( "(%p, %p)\n", InterfaceDescriptor
, BufferEnd
);
230 for (common
= (PUSB_COMMON_DESCRIPTOR
)(InterfaceDescriptor
+ 1);
231 (((PUCHAR
)common
) + sizeof(USB_COMMON_DESCRIPTOR
)) <= BufferEnd
&&
232 common
->bDescriptorType
!= USB_INTERFACE_DESCRIPTOR_TYPE
;
233 common
= (PUSB_COMMON_DESCRIPTOR
)(((char*)common
) + common
->bLength
))
235 total
+= common
->bLength
;
240 NTSTATUS WINAPI
DriverEntry( DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
242 TRACE( "(%p, %s)\n", driver
, debugstr_w(path
->Buffer
) );
243 return STATUS_SUCCESS
;