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