ReactOS  0.4.14-dev-384-g5b37caa
descriptor.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: drivers/usb/usbccgp/descriptor.c
5  * PURPOSE: USB device driver.
6  * PROGRAMMERS:
7  * Michael Martin (michael.martin@reactos.org)
8  * Johannes Anderwald (johannes.anderwald@reactos.org)
9  * Cameron Gutman
10  */
11 
12 #include "usbccgp.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
18 NTAPI
22  IN ULONG DescriptorLength,
23  IN UCHAR DescriptorIndex,
24  IN LANGID LanguageId,
25  OUT PVOID *OutDescriptor)
26 {
27  PURB Urb;
30 
31  //
32  // sanity checks
33  //
35  ASSERT(OutDescriptor);
36  ASSERT(DescriptorLength);
37 
38  //
39  // first allocate descriptor buffer
40  //
41  Descriptor = AllocateItem(NonPagedPool, DescriptorLength);
42  if (!Descriptor)
43  {
44  //
45  // no memory
46  //
48  }
49 
50  //
51  // allocate urb
52  //
53  Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB));
54  if (!Urb)
55  {
56  //
57  // no memory
58  //
61  }
62 
63  //
64  // initialize urb
65  //
67  sizeof(Urb->UrbControlDescriptorRequest),
69  DescriptorIndex,
70  LanguageId,
71  Descriptor,
72  NULL,
73  DescriptorLength,
74  NULL);
75 
76  //
77  // submit urb
78  //
80 
81  //
82  // free urb
83  //
84  FreeItem(Urb);
85 
86  if (NT_SUCCESS(Status))
87  {
88  //
89  // store result
90  //
91  *OutDescriptor = Descriptor;
92  }
93 
94  //
95  // done
96  //
97  return Status;
98 }
99 
100 NTSTATUS
101 NTAPI
104  IN ULONG DescriptorLength,
105  IN UCHAR DescriptorIndex,
106  IN LANGID LanguageId,
107  OUT PVOID *OutDescriptor)
108 {
110  PUSB_STRING_DESCRIPTOR StringDescriptor;
111  ULONG Size;
112  PVOID Buffer;
113 
114  // retrieve descriptor
115  Status = USBCCGP_GetDescriptor(DeviceObject, USB_STRING_DESCRIPTOR_TYPE, DescriptorLength, DescriptorIndex, LanguageId, OutDescriptor);
116  if (!NT_SUCCESS(Status))
117  {
118  // failed
119  return Status;
120  }
121 
122  // get descriptor structure
123  StringDescriptor = (PUSB_STRING_DESCRIPTOR)*OutDescriptor;
124 
125  // sanity check
126  ASSERT(StringDescriptor->bLength < DescriptorLength - 2);
127 
128  if (StringDescriptor->bLength == 2)
129  {
130  // invalid descriptor
131  FreeItem(StringDescriptor);
133  }
134 
135  // calculate size
136  Size = StringDescriptor->bLength + sizeof(WCHAR);
137 
138  // allocate buffer
140  if (!Buffer)
141  {
142  // no memory
143  FreeItem(StringDescriptor);
145  }
146 
147  // copy result
148  RtlCopyMemory(Buffer, StringDescriptor->bString, Size - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString));
149 
150  // free buffer
151  FreeItem(StringDescriptor);
152 
153  // store result
154  *OutDescriptor = (PVOID)Buffer;
155  return STATUS_SUCCESS;
156 }
157 
158 
159 NTSTATUS
162 {
164  PFDO_DEVICE_EXTENSION DeviceExtension;
165  USHORT DescriptorLength;
166 
167  //
168  // get device extension
169  //
171 
172  //
173  // first get device descriptor
174  //
175  Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor);
176  if (!NT_SUCCESS(Status))
177  {
178  //
179  // failed to get device descriptor
180  //
181  DeviceExtension->DeviceDescriptor = NULL;
182  return Status;
183  }
184 
185  //
186  // now get basic configuration descriptor
187  //
188  Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
189  if (!NT_SUCCESS(Status))
190  {
191  //
192  // failed to get configuration descriptor
193  //
194  FreeItem(DeviceExtension->DeviceDescriptor);
195  DeviceExtension->DeviceDescriptor = NULL;
196  return Status;
197  }
198 
199  //
200  // backup length
201  //
202  DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength;
203 
204  //
205  // release basic descriptor
206  //
207  FreeItem(DeviceExtension->ConfigurationDescriptor);
208  DeviceExtension->ConfigurationDescriptor = NULL;
209 
210  //
211  // allocate full descriptor
212  //
213  Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
214  if (!NT_SUCCESS(Status))
215  {
216  //
217  // failed to get configuration descriptor
218  //
219  FreeItem(DeviceExtension->DeviceDescriptor);
220  DeviceExtension->DeviceDescriptor = NULL;
221  return Status;
222  }
223  return Status;
224 }
225 
226 NTSTATUS
228  IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
229  OUT PUSB_INTERFACE_DESCRIPTOR **OutArray)
230 {
231  PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
232  ULONG Count = 0;
234 
235  //
236  // allocate array
237  //
238  Array = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * ConfigurationDescriptor->bNumInterfaces);
239  if (!Array)
241 
242  //
243  // enumerate all interfaces
244  //
245  Count = 0;
246  do
247  {
248  //
249  // find next descriptor
250  //
251  InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, Count, 0, -1, -1, -1);
252  if (!InterfaceDescriptor)
253  break;
254 
255  //
256  // store descriptor
257  //
258  Array[Count] = InterfaceDescriptor;
259  Count++;
260 
261  }while(TRUE);
262 
263  //
264  // store result
265  //
266  *OutArray = Array;
267 
268  //
269  // done
270  //
271  return STATUS_SUCCESS;
272 }
273 
274 VOID
276  IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
277  IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
278 {
280 
281  Descriptor = (PUSB_COMMON_DESCRIPTOR)ConfigurationDescriptor;
282 
283  DbgPrint("Bogus ConfigurationDescriptor Found\n");
284  DbgPrint("InterfaceCount %x\n", ConfigurationDescriptor->bNumInterfaces);
285 
286  do
287  {
288  if (((ULONG_PTR)Descriptor) >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
289  break;
290 
291  DbgPrint("Descriptor Type %x Length %lu Offset %lu\n", Descriptor->bDescriptorType, Descriptor->bLength, ((ULONG_PTR)Descriptor - (ULONG_PTR)ConfigurationDescriptor));
292 
293  // check for invalid descriptors
294  if (!Descriptor->bLength)
295  {
296  DbgPrint("Bogus Descriptor!!!\n");
297  break;
298  }
299 
300  // advance to next descriptor
302 
303  }while(TRUE);
304 
305 
306 }
307 
308 
309 NTSTATUS
310 NTAPI
312  IN OUT PFDO_DEVICE_EXTENSION FDODeviceExtension,
313  IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
314 {
315  PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
316  ULONG InterfaceIndex = 0;
317  ULONG DescriptorCount;
318 
319  //
320  // sanity checks
321  //
322  ASSERT(ConfigurationDescriptor);
323  ASSERT(ConfigurationDescriptor->bNumInterfaces);
324 
325  //
326  // count all interface descriptors
327  //
328  DescriptorCount = ConfigurationDescriptor->bNumInterfaces;
329  if (DescriptorCount == 0)
330  {
331  DPRINT1("[USBCCGP] DescriptorCount is zero\n");
333  }
334 
335  //
336  // allocate array holding the interface descriptors
337  //
338  FDODeviceExtension->InterfaceList = AllocateItem(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (DescriptorCount + 1));
339  if (!FDODeviceExtension->InterfaceList)
340  {
341  //
342  // no memory
343  //
345  }
346 
347  //
348  // reset interface list count
349  //
350  FDODeviceExtension->InterfaceListCount = 0;
351 
352  do
353  {
354  //
355  // parse configuration descriptor
356  //
357  InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, InterfaceIndex, -1, -1, -1, -1);
358  if (InterfaceDescriptor)
359  {
360  //
361  // store in interface list
362  //
363  ASSERT(FDODeviceExtension->InterfaceListCount < DescriptorCount);
364  FDODeviceExtension->InterfaceList[FDODeviceExtension->InterfaceListCount].InterfaceDescriptor = InterfaceDescriptor;
365  FDODeviceExtension->InterfaceListCount++;
366  }
367  else
368  {
369  DumpConfigurationDescriptor(ConfigurationDescriptor);
370  DumpFullConfigurationDescriptor(FDODeviceExtension, ConfigurationDescriptor);
371 
372  //
373  // see issue
374  // CORE-6574 Test 3 (USB Web Cam)
375  //
376  if (FDODeviceExtension->DeviceDescriptor && FDODeviceExtension->DeviceDescriptor->idVendor == 0x0458 && FDODeviceExtension->DeviceDescriptor->idProduct == 0x705f)
377  ASSERT(FALSE);
378  }
379 
380  //
381  // move to next interface
382  //
383  InterfaceIndex++;
384 
385  }while(InterfaceIndex < DescriptorCount);
386 
387  //
388  // sanity check
389  //
390  ASSERT(FDODeviceExtension->InterfaceListCount);
391 
392  //
393  // done
394  //
395  return STATUS_SUCCESS;
396 }
397 
398 VOID
400 {
401  DbgPrint("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
402  DbgPrint("bLength %x\n", ConfigurationDescriptor->bLength);
403  DbgPrint("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
404  DbgPrint("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
405  DbgPrint("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
406  DbgPrint("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
407  DbgPrint("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
408  DbgPrint("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
409  DbgPrint("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
410 }
411 
412 NTSTATUS
415  IN PFDO_DEVICE_EXTENSION DeviceExtension,
416  IN ULONG InterfaceIndex)
417 {
419  PURB Urb;
420 
421  //
422  // allocate urb
423  //
424  Urb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints));
425  if (!Urb)
426  {
427  //
428  // no memory
429  //
431  }
432 
433  //
434  // now prepare interface urb
435  //
436  UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bInterfaceNumber, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bAlternateSetting);
437 
438  //
439  // now select the interface
440  //
441  Status = USBCCGP_SyncUrbRequest(DeviceExtension->NextDeviceObject, Urb);
442 
443  //
444  // did it succeed
445  //
446  if (NT_SUCCESS(Status))
447  {
448  //
449  // update configuration info
450  //
451  ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceList[InterfaceIndex].Interface->Length);
452  RtlCopyMemory(DeviceExtension->InterfaceList[InterfaceIndex].Interface, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length);
453  }
454 
455  //
456  // free urb
457  //
458  FreeItem(Urb);
459 
460  //
461  // done
462  //
463  return Status;
464 }
465 
466 NTSTATUS
469  IN PFDO_DEVICE_EXTENSION DeviceExtension)
470 {
471  PUSBD_INTERFACE_INFORMATION InterfaceInformation;
473  PURB Urb;
474  ULONG Index;
475 
476  //
477  // now scan configuration descriptors
478  //
479  Status = USBCCGP_ScanConfigurationDescriptor(DeviceExtension, DeviceExtension->ConfigurationDescriptor);
480  if (!NT_SUCCESS(Status))
481  {
482  //
483  // failed to scan
484  //
485  return Status;
486  }
487 
488  //
489  // now allocate the urb
490  //
491  Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->InterfaceList);
492  if (!Urb)
493  {
494  //
495  // no memory
496  //
498  }
499 
500  //
501  // submit urb
502  //
503  Status = USBCCGP_SyncUrbRequest(DeviceExtension->NextDeviceObject, Urb);
504  if (!NT_SUCCESS(Status))
505  {
506  //
507  // failed to set configuration
508  //
509  DPRINT1("USBCCGP_SyncUrbRequest failed to set interface %x\n", Status);
510  ExFreePool(Urb);
511  return Status;
512  }
513 
514  //
515  // get interface information
516  //
517  InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
518  for(Index = 0; Index < DeviceExtension->InterfaceListCount; Index++)
519  {
520  //
521  // allocate buffer to store interface information
522  //
523  DeviceExtension->InterfaceList[Index].Interface = AllocateItem(NonPagedPool, InterfaceInformation->Length);
524  if (!DeviceExtension->InterfaceList[Index].Interface)
525  {
526  //
527  // no memory
528  //
530  }
531 
532  //
533  // copy interface information
534  //
535  RtlCopyMemory(DeviceExtension->InterfaceList[Index].Interface, InterfaceInformation, InterfaceInformation->Length);
536 
537  //
538  // move to next interface
539  //
540  InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
541  }
542 
543 
544  //
545  // store pipe handle
546  //
547  DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
548 
549  //
550  // free interface list & urb
551  //
552  ExFreePool(Urb);
553 
554  //
555  // done
556  //
557  return Status;
558 }
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define DbgPrint
Definition: loader.c:25
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:30
LONG NTSTATUS
Definition: precomp.h:26
#define GET_SELECT_INTERFACE_REQUEST_SIZE(totalPipes)
Definition: usbdlib.h:104
struct _USBD_INTERFACE_INFORMATION * PUSBD_INTERFACE_INFORMATION
NTSTATUS USBCCGP_SelectConfiguration(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: descriptor.c:467
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
WORD LANGID
Definition: typedefs.h:79
#define UsbBuildGetDescriptorRequest(urb, length, descriptorType, descriptorIndex, languageId, transferBuffer, transferBufferMDL, transferBufferLength, link)
Definition: usbdlib.h:23
#define USB_STRING_DESCRIPTOR_TYPE
Definition: usb100.h:51
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
uint32_t ULONG_PTR
Definition: typedefs.h:63
Definition: usbdlib.h:7
VOID FreeItem(IN PVOID Item)
Definition: misc.c:43
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define USB_DEVICE_DESCRIPTOR_TYPE
Definition: usb100.h:49
VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
Definition: descriptor.c:399
#define USB_CONFIGURATION_DESCRIPTOR_TYPE
Definition: usb100.h:50
PVOID DeviceExtension
Definition: env_spec_w32.h:418
NTSTATUS USBCCGP_SelectInterface(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension, IN ULONG InterfaceIndex)
Definition: descriptor.c:413
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
PUSB_INTERFACE_DESCRIPTOR NTAPI USBD_ParseConfigurationDescriptorEx(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PVOID StartPosition, LONG InterfaceNumber, LONG AlternateSetting, LONG InterfaceClass, LONG InterfaceSubClass, LONG InterfaceProtocol)
Definition: usbd.c:496
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _USB_COMMON_DESCRIPTOR * PUSB_COMMON_DESCRIPTOR
static const UCHAR Index[8]
Definition: usbohci.c:18
NTSTATUS NTAPI USBCCGP_GetDescriptor(IN PDEVICE_OBJECT DeviceObject, IN UCHAR DescriptorType, IN ULONG DescriptorLength, IN UCHAR DescriptorIndex, IN LANGID LanguageId, OUT PVOID *OutDescriptor)
Definition: descriptor.c:19
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
unsigned char UCHAR
Definition: xmlstorage.h:181
NTSTATUS NTAPI USBCCGP_GetStringDescriptor(IN PDEVICE_OBJECT DeviceObject, IN ULONG DescriptorLength, IN UCHAR DescriptorIndex, IN LANGID LanguageId, OUT PVOID *OutDescriptor)
Definition: descriptor.c:102
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
NTSTATUS USBCCGP_GetDescriptors(IN PDEVICE_OBJECT DeviceObject)
Definition: descriptor.c:160
struct _URB * PURB
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
NTSTATUS AllocateInterfaceDescriptorsArray(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, OUT PUSB_INTERFACE_DESCRIPTOR **OutArray)
Definition: descriptor.c:227
struct _URB_SELECT_CONFIGURATION UrbSelectConfiguration
Definition: usb.h:533
struct _USB_STRING_DESCRIPTOR * PUSB_STRING_DESCRIPTOR
Definition: usb.h:529
NTSTATUS USBCCGP_SyncUrbRequest(IN PDEVICE_OBJECT DeviceObject, OUT PURB UrbRequest)
Definition: misc.c:75
unsigned short USHORT
Definition: pedump.c:61
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define DPRINT1
Definition: precomp.h:8
#define UsbBuildSelectInterfaceRequest(urb, length, configurationHandle, interfaceNumber, alternateSetting)
Definition: usbdlib.h:59
VOID DumpFullConfigurationDescriptor(IN PFDO_DEVICE_EXTENSION FDODeviceExtension, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
Definition: descriptor.c:275
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
struct _URB_CONTROL_DESCRIPTOR_REQUEST UrbControlDescriptorRequest
Definition: usb.h:545
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
PURB NTAPI USBD_CreateConfigurationRequestEx(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSBD_INTERFACE_LIST_ENTRY InterfaceList)
Definition: usbd.c:329
return STATUS_SUCCESS
Definition: btrfs.c:2938
_In_ ULONG _In_ PVOID _In_ LONG DescriptorType
Definition: usbdlib.h:145
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS NTAPI USBCCGP_ScanConfigurationDescriptor(IN OUT PFDO_DEVICE_EXTENSION FDODeviceExtension, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
Definition: descriptor.c:311
struct _URB_SELECT_INTERFACE UrbSelectInterface
Definition: usb.h:532
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966