winspool.drv: Implement OpenPrinter2.
[wine.git] / dlls / usbd.sys / usbd.c
blobd562cf1f81ef3e7b84e318da6021e57d37d6c001
1 /*
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
19 #include <stdarg.h>
21 #define NONAMELESSUNION
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winternl.h"
28 #include "ddk/wdm.h"
29 #include "ddk/usb.h"
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 )
38 URB *urb = NULL;
39 USBD_INTERFACE_LIST_ENTRY *interfaceList;
40 ULONG interfaceListSize;
41 USB_INTERFACE_DESCRIPTOR *interfaceDesc;
42 int i;
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?
51 *Siz = 0;
52 interfaceListSize = (ConfigurationDescriptor->bNumInterfaces + 1) * sizeof(USBD_INTERFACE_LIST_ENTRY);
53 interfaceList = ExAllocatePool( NonPagedPool, interfaceListSize );
54 if (interfaceList)
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 );
68 if (urb)
69 *Siz = urb->u.UrbHeader.Length;
70 ExFreePool( interfaceList );
72 return urb;
75 PURB WINAPI USBD_CreateConfigurationRequestEx(
76 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
77 PUSBD_INTERFACE_LIST_ENTRY InterfaceList )
79 URB *urb;
80 ULONG size = 0;
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++)
89 ++interfaceCount;
90 size += (interfaceEntry->InterfaceDescriptor->bNumEndpoints - 1) *
91 sizeof(USBD_PIPE_INFORMATION);
93 size += (interfaceCount - 1) * sizeof(USBD_INTERFACE_INFORMATION);
95 urb = ExAllocatePool( NonPagedPool, size );
96 if (urb)
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++)
107 ULONG i;
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;
131 break;
132 case USB_ENDPOINT_TYPE_BULK:
133 interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeBulk;
134 break;
135 case USB_ENDPOINT_TYPE_INTERRUPT:
136 interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeInterrupt;
137 break;
138 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
139 interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeIsochronous;
140 break;
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);
152 return urb;
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))
191 return interface;
193 interface = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(
194 ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength,
195 interface + 1, USB_INTERFACE_DESCRIPTOR_TYPE );
197 return NULL;
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,
211 ULONG TotalLength,
212 PVOID StartPosition,
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)
224 return common;
226 return NULL;
229 USBD_STATUS WINAPI USBD_ValidateConfigurationDescriptor(
230 PUSB_CONFIGURATION_DESCRIPTOR descr,
231 ULONG length,
232 USHORT level,
233 PUCHAR *offset,
234 ULONG tag )
236 FIXME( "(%p, %lu, %u, %p, %lu) partial stub!\n", descr, length, level, offset, tag );
238 if (offset) *offset = 0;
240 if (!descr ||
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,
251 PUCHAR BufferEnd )
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;
265 return total;
268 NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
270 TRACE( "(%p, %s)\n", driver, debugstr_w(path->Buffer) );
271 return STATUS_SUCCESS;