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;