- Create another branch for networking fixes
[reactos.git] / drivers / usb / usbd / usbd.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Driver/Helper Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbd/usbd.c
5 * PURPOSE: Helper Library for USB
6 * PROGRAMMERS:
7 * Filip Navara <xnavara@volny.cz>
8 *
9 */
10
11 /*
12 * Universal Serial Bus Driver/Helper Library
13 *
14 * Written by Filip Navara <xnavara@volny.cz>
15 *
16 * Notes:
17 * This driver was obsoleted in Windows XP and most functions
18 * became pure stubs. But some of them were retained for backward
19 * compatibilty with existing drivers.
20 *
21 * Preserved functions:
22 *
23 * USBD_Debug_GetHeap (implemented)
24 * USBD_Debug_RetHeap (implemented)
25 * USBD_CalculateUsbBandwidth (implemented, tested)
26 * USBD_CreateConfigurationRequestEx (implemented)
27 * USBD_CreateConfigurationRequest
28 * USBD_GetInterfaceLength (implemented)
29 * USBD_ParseConfigurationDescriptorEx (implemented)
30 * USBD_ParseDescriptors (implemented)
31 * USBD_GetPdoRegistryParameters (implemented)
32 */
33
34 #include <ntddk.h>
35 #include <usbdi.h>
36 #ifndef PLUGPLAY_REGKEY_DRIVER
37 #define PLUGPLAY_REGKEY_DRIVER 2
38 #endif
39 typedef struct _USBD_INTERFACE_LIST_ENTRY {
40 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
41 PUSBD_INTERFACE_INFORMATION Interface;
42 } USBD_INTERFACE_LIST_ENTRY, *PUSBD_INTERFACE_LIST_ENTRY;
43
44 NTSTATUS NTAPI
45 DriverEntry(PDRIVER_OBJECT DriverObject,
46 PUNICODE_STRING RegistryPath)
47 {
48 return STATUS_SUCCESS;
49 }
50
51 /*
52 * @implemented
53 */
54 DWORD NTAPI
55 DllInitialize(DWORD Unknown)
56 {
57 return 0;
58 }
59
60 /*
61 * @implemented
62 */
63 DWORD NTAPI
64 DllUnload(VOID)
65 {
66 return 0;
67 }
68
69 /*
70 * @implemented
71 */
72 PVOID NTAPI
73 USBD_Debug_GetHeap(DWORD Unknown1, POOL_TYPE PoolType, ULONG NumberOfBytes,
74 ULONG Tag)
75 {
76 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
77 }
78
79 /*
80 * @implemented
81 */
82 VOID NTAPI
83 USBD_Debug_RetHeap(PVOID Heap, DWORD Unknown2, DWORD Unknown3)
84 {
85 ExFreePool(Heap);
86 }
87
88 /*
89 * @implemented
90 */
91 VOID NTAPI
92 USBD_Debug_LogEntry(PCHAR Name, ULONG_PTR Info1, ULONG_PTR Info2,
93 ULONG_PTR Info3)
94 {
95 }
96
97 /*
98 * @implemented
99 */
100 PVOID NTAPI
101 USBD_AllocateDeviceName(DWORD Unknown)
102 {
103 return NULL;
104 }
105
106 /*
107 * @implemented
108 */
109 DWORD NTAPI
110 USBD_CalculateUsbBandwidth(
111 ULONG MaxPacketSize,
112 UCHAR EndpointType,
113 BOOLEAN LowSpeed
114 )
115 {
116 DWORD OverheadTable[] = {
117 0x00, /* UsbdPipeTypeControl */
118 0x09, /* UsbdPipeTypeIsochronous */
119 0x00, /* UsbdPipeTypeBulk */
120 0x0d /* UsbdPipeTypeInterrupt */
121 };
122 DWORD Result;
123
124 if (OverheadTable[EndpointType] != 0)
125 {
126 Result = ((MaxPacketSize + OverheadTable[EndpointType]) * 8 * 7) / 6;
127 if (LowSpeed)
128 return Result << 3;
129 return Result;
130 }
131 return 0;
132 }
133
134 /*
135 * @implemented
136 */
137 DWORD NTAPI
138 USBD_Dispatch(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4)
139 {
140 return 1;
141 }
142
143 /*
144 * @implemented
145 */
146 VOID NTAPI
147 USBD_FreeDeviceMutex(PVOID Unknown)
148 {
149 }
150
151 /*
152 * @implemented
153 */
154 VOID NTAPI
155 USBD_FreeDeviceName(PVOID Unknown)
156 {
157 }
158
159 /*
160 * @implemented
161 */
162 VOID NTAPI
163 USBD_WaitDeviceMutex(PVOID Unknown)
164 {
165 }
166
167 /*
168 * @implemented
169 */
170 DWORD NTAPI
171 USBD_GetSuspendPowerState(DWORD Unknown1)
172 {
173 return 0;
174 }
175
176 /*
177 * @implemented
178 */
179 NTSTATUS NTAPI
180 USBD_InitializeDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3,
181 DWORD Unknown4, DWORD Unknown5, DWORD Unknown6)
182 {
183 return STATUS_NOT_SUPPORTED;
184 }
185
186 /*
187 * @implemented
188 */
189 NTSTATUS NTAPI
190 USBD_RegisterHostController(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3,
191 DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7,
192 DWORD Unknown8, DWORD Unknown9, DWORD Unknown10)
193 {
194 return STATUS_NOT_SUPPORTED;
195 }
196
197 /*
198 * @implemented
199 */
200 NTSTATUS NTAPI
201 USBD_GetDeviceInformation(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3)
202 {
203 return STATUS_NOT_SUPPORTED;
204 }
205
206 /*
207 * @implemented
208 */
209 NTSTATUS NTAPI
210 USBD_CreateDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3,
211 DWORD Unknown4, DWORD Unknown5)
212 {
213 return STATUS_NOT_SUPPORTED;
214 }
215
216 /*
217 * @implemented
218 */
219 NTSTATUS NTAPI
220 USBD_RemoveDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3)
221 {
222 return STATUS_NOT_SUPPORTED;
223 }
224
225 /*
226 * @implemented
227 */
228 VOID NTAPI
229 USBD_CompleteRequest(DWORD Unknown1, DWORD Unknown2)
230 {
231 }
232
233 /*
234 * @implemented
235 */
236 VOID NTAPI
237 USBD_RegisterHcFilter(
238 PDEVICE_OBJECT DeviceObject,
239 PDEVICE_OBJECT FilterDeviceObject
240 )
241 {
242 }
243
244 /*
245 * @implemented
246 */
247 VOID NTAPI
248 USBD_SetSuspendPowerState(DWORD Unknown1, DWORD Unknown2)
249 {
250 }
251
252 /*
253 * @implemented
254 */
255 NTSTATUS NTAPI
256 USBD_MakePdoName(DWORD Unknown1, DWORD Unknown2)
257 {
258 return STATUS_NOT_SUPPORTED;
259 }
260
261 /*
262 * @implemented
263 */
264 NTSTATUS NTAPI
265 USBD_QueryBusTime(
266 PDEVICE_OBJECT RootHubPdo,
267 PULONG CurrentFrame
268 )
269 {
270 return STATUS_NOT_SUPPORTED;
271 }
272
273 /*
274 * @implemented
275 */
276 VOID NTAPI
277 USBD_GetUSBDIVersion(
278 PUSBD_VERSION_INFORMATION Version
279 )
280 {
281 if (Version != NULL)
282 {
283 Version->USBDI_Version = USBDI_VERSION;
284 Version->Supported_USB_Version = 0x100;
285 }
286 }
287
288 /*
289 * @implemented
290 */
291 NTSTATUS NTAPI
292 USBD_RestoreDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3)
293 {
294 return STATUS_NOT_SUPPORTED;
295 }
296
297 /*
298 * @implemented
299 */
300 VOID NTAPI
301 USBD_RegisterHcDeviceCapabilities(DWORD Unknown1, DWORD Unknown2,
302 DWORD Unknown3)
303 {
304 }
305
306 /*
307 * @implemented
308 * FIXME: Test
309 */
310 PURB
311 NTAPI
312 USBD_CreateConfigurationRequestEx(
313 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
314 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
315 )
316 {
317 PURB Urb;
318 DWORD UrbSize;
319 DWORD InterfaceCount;
320
321 for (InterfaceCount = 0;
322 InterfaceList[InterfaceCount].InterfaceDescriptor != NULL;
323 ++InterfaceCount)
324 ;
325 /* Include the NULL entry */
326 ++InterfaceCount;
327
328 UrbSize = sizeof(Urb->UrbSelectConfiguration) +
329 (InterfaceCount * sizeof(PUSBD_INTERFACE_LIST_ENTRY));
330 Urb = ExAllocatePool(NonPagedPool, UrbSize);
331 Urb->UrbSelectConfiguration.Hdr.Function =
332 URB_FUNCTION_SELECT_CONFIGURATION;
333 Urb->UrbSelectConfiguration.Hdr.Length =
334 sizeof(Urb->UrbSelectConfiguration);
335 Urb->UrbSelectConfiguration.ConfigurationDescriptor =
336 ConfigurationDescriptor;
337 memcpy((PVOID)&Urb->UrbSelectConfiguration.Interface, (PVOID)InterfaceList,
338 InterfaceCount * sizeof(PUSBD_INTERFACE_LIST_ENTRY));
339
340 return Urb;
341 }
342
343 /*
344 * @unimplemented
345 */
346 PURB NTAPI
347 USBD_CreateConfigurationRequest(
348 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
349 PUSHORT Size
350 )
351 {
352 return NULL;
353 }
354
355 /*
356 * @unimplemented
357 */
358 ULONG NTAPI
359 USBD_GetInterfaceLength(
360 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
361 PUCHAR BufferEnd
362 )
363 {
364 ULONG_PTR Current;
365 PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor = InterfaceDescriptor;
366 DWORD Length = CurrentDescriptor->bLength;
367
368 // USB_ENDPOINT_DESCRIPTOR_TYPE
369 if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
370 {
371 for (Current = (ULONG_PTR)CurrentDescriptor;
372 Current < (ULONG_PTR)BufferEnd;
373 Current += CurrentDescriptor->bLength)
374 CurrentDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Current;
375 Length += CurrentDescriptor->bLength;
376
377 }
378 return Length;
379 }
380
381 /*
382 * @implemented
383 */
384 PUSB_COMMON_DESCRIPTOR NTAPI
385 USBD_ParseDescriptors(
386 PVOID DescriptorBuffer,
387 ULONG TotalLength,
388 PVOID StartPosition,
389 LONG DescriptorType
390 )
391 {
392 PUSB_COMMON_DESCRIPTOR PComDes = StartPosition;
393
394 while(PComDes)
395 {
396 if (PComDes >= (PUSB_COMMON_DESCRIPTOR)
397 ((PLONG)DescriptorBuffer + TotalLength) ) break;
398 if (PComDes->bDescriptorType == DescriptorType) return PComDes;
399 if (PComDes->bLength == 0) break;
400 PComDes = PComDes + PComDes->bLength;
401 }
402 return NULL;
403 }
404
405
406 /*
407 * @implemented
408 */
409 PUSB_INTERFACE_DESCRIPTOR NTAPI
410 USBD_ParseConfigurationDescriptorEx(
411 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
412 PVOID StartPosition,
413 LONG InterfaceNumber,
414 LONG AlternateSetting,
415 LONG InterfaceClass,
416 LONG InterfaceSubClass,
417 LONG InterfaceProtocol
418 )
419 {
420 int x = 0;
421 PUSB_INTERFACE_DESCRIPTOR UsbInterfaceDesc = StartPosition;
422
423 while(UsbInterfaceDesc)
424 {
425 UsbInterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)
426 USBD_ParseDescriptors(ConfigurationDescriptor,
427 ConfigurationDescriptor->wTotalLength,
428 UsbInterfaceDesc,
429 USB_INTERFACE_DESCRIPTOR_TYPE);
430
431 if (!UsbInterfaceDesc) break;
432
433 if(InterfaceNumber != -1)
434 {
435 if(InterfaceNumber != UsbInterfaceDesc->bInterfaceNumber) x = 1;
436 }
437 if(AlternateSetting != -1)
438 {
439 if(AlternateSetting != UsbInterfaceDesc->bAlternateSetting) x = 1;
440 }
441 if(InterfaceClass != -1)
442 {
443 if(InterfaceClass != UsbInterfaceDesc->bInterfaceClass) x = 1;
444 }
445 if(InterfaceSubClass != -1)
446 {
447 if(InterfaceSubClass != UsbInterfaceDesc->bInterfaceSubClass) x = 1;
448 }
449 if(InterfaceProtocol != -1)
450 {
451 if(InterfaceProtocol != UsbInterfaceDesc->bInterfaceProtocol) x = 1;
452 }
453
454 if (!x) return UsbInterfaceDesc;
455
456 if (UsbInterfaceDesc->bLength == 0) break;
457 UsbInterfaceDesc = UsbInterfaceDesc + UsbInterfaceDesc->bLength;
458 }
459 return NULL;
460 }
461
462 /*
463 * @implemented
464 */
465 PUSB_INTERFACE_DESCRIPTOR NTAPI
466 USBD_ParseConfigurationDescriptor(
467 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
468 UCHAR InterfaceNumber,
469 UCHAR AlternateSetting
470 )
471 {
472 return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,
473 (PVOID)ConfigurationDescriptor, InterfaceNumber, AlternateSetting,
474 -1, -1, -1);
475 }
476
477
478 /*
479 * @implemented
480 */
481 DWORD NTAPI
482 USBD_GetPdoRegistryParameter(
483 PDEVICE_OBJECT PhysicalDeviceObject,
484 PVOID Parameter,
485 ULONG ParameterLength,
486 PWCHAR KeyName,
487 ULONG KeyNameLength
488 )
489 {
490 NTSTATUS Status;
491 HANDLE DevInstRegKey;
492
493 Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
494 PLUGPLAY_REGKEY_DRIVER, STANDARD_RIGHTS_ALL, &DevInstRegKey);
495 if (NT_SUCCESS(Status))
496 {
497 PKEY_VALUE_FULL_INFORMATION FullInfo;
498 UNICODE_STRING ValueName;
499 ULONG Length;
500
501 RtlInitUnicodeString(&ValueName, KeyName);
502 Length = ParameterLength + KeyNameLength + sizeof(KEY_VALUE_FULL_INFORMATION);
503 FullInfo = ExAllocatePool(PagedPool, Length);
504 if (FullInfo)
505 {
506 Status = ZwQueryValueKey(DevInstRegKey, &ValueName,
507 KeyValueFullInformation, FullInfo, Length, &Length);
508 if (NT_SUCCESS(Status))
509 {
510 RtlCopyMemory(Parameter,
511 ((PUCHAR)FullInfo) + FullInfo->DataOffset,
512 ParameterLength /*FullInfo->DataLength*/);
513 }
514 ExFreePool(FullInfo);
515 } else
516 Status = STATUS_NO_MEMORY;
517 ZwClose(DevInstRegKey);
518 }
519 return Status;
520 }