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