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;