ReactOS  0.4.14-dev-599-g2d4d3f5
descriptor.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: drivers/usb/usbstor/descriptor.c
5  * PURPOSE: USB block storage device driver.
6  * PROGRAMMERS:
7  * James Tabor
8  * Michael Martin (michael.martin@reactos.org)
9  * Johannes Anderwald (johannes.anderwald@reactos.org)
10  */
11 
12 #include "usbstor.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 
101 NTSTATUS
104 {
106  PFDO_DEVICE_EXTENSION DeviceExtension;
107  USHORT DescriptorLength;
108 
109  //
110  // get device extension
111  //
113 
114  //
115  // first get device descriptor
116  //
117  Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor);
118  if (!NT_SUCCESS(Status))
119  {
120  //
121  // failed to get device descriptor
122  //
123  DeviceExtension->DeviceDescriptor = NULL;
124  return Status;
125  }
126 
127  //
128  // now get basic configuration descriptor
129  //
130  Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
131  if (!NT_SUCCESS(Status))
132  {
133  //
134  // failed to get configuration descriptor
135  //
136  FreeItem(DeviceExtension->DeviceDescriptor);
137  DeviceExtension->DeviceDescriptor = NULL;
138  return Status;
139  }
140 
141  //
142  // backup length
143  //
144  DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength;
145 
146  //
147  // release basic descriptor
148  //
149  FreeItem(DeviceExtension->ConfigurationDescriptor);
150  DeviceExtension->ConfigurationDescriptor = NULL;
151 
152  //
153  // allocate full descriptor
154  //
155  Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
156  if (!NT_SUCCESS(Status))
157  {
158  //
159  // failed to get configuration descriptor
160  //
161  FreeItem(DeviceExtension->DeviceDescriptor);
162  DeviceExtension->DeviceDescriptor = NULL;
163  return Status;
164  }
165 
166  //
167  // check if there is a serial number provided
168  //
169  if (DeviceExtension->DeviceDescriptor->iSerialNumber)
170  {
171  //
172  // get serial number
173  //
174  Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_STRING_DESCRIPTOR_TYPE, 100 * sizeof(WCHAR), DeviceExtension->DeviceDescriptor->iSerialNumber, 0x0409, (PVOID*)&DeviceExtension->SerialNumber);
175  if (!NT_SUCCESS(Status))
176  {
177  //
178  // failed to get serial number descriptor, free device descriptor
179  //
180  FreeItem(DeviceExtension->DeviceDescriptor);
181  DeviceExtension->DeviceDescriptor = NULL;
182 
183  //
184  // free configuration descriptor
185  //
186  FreeItem(DeviceExtension->ConfigurationDescriptor);
187  DeviceExtension->ConfigurationDescriptor = NULL;
188 
189  //
190  // set serial number to zero
191  //
192  DeviceExtension->SerialNumber = NULL;
193  return Status;
194  }
195  }
196 
197  return Status;
198 }
199 
200 NTSTATUS
201 NTAPI
203  IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
204  OUT PUSB_INTERFACE_DESCRIPTOR * OutInterfaceDescriptor,
205  OUT PUSB_ENDPOINT_DESCRIPTOR * InEndpointDescriptor,
206  OUT PUSB_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
207 {
208  PUSB_CONFIGURATION_DESCRIPTOR CurrentDescriptor;
209  PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
210 
211  //
212  // sanity checks
213  //
214  ASSERT(ConfigurationDescriptor);
215  ASSERT(OutInterfaceDescriptor);
216  ASSERT(InEndpointDescriptor);
217  ASSERT(OutEndpointDescriptor);
218 
219  //
220  // nullify pointers
221  //
222  *OutInterfaceDescriptor = NULL;
223  *InEndpointDescriptor = NULL;
224  *OutEndpointDescriptor = NULL;
225 
226  //
227  // start scanning
228  //
229  CurrentDescriptor = ConfigurationDescriptor;
230 
231  do
232  {
233  //
234  // check current descriptor type
235  //
236  if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
237  {
238  //
239  // found interface descriptor
240  //
241  if (*OutInterfaceDescriptor)
242  {
243  //
244  // we only process the first interface descriptor as ms does -> see documentation
245  //
246  break;
247  }
248 
249  //
250  // store interface descriptor
251  //
252  *OutInterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)CurrentDescriptor;
253  }
254  else if (CurrentDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
255  {
256  //
257  // convert to endpoint descriptor
258  //
259  EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)CurrentDescriptor;
260 
261  //
262  // sanity check
263  //
264  ASSERT(*OutInterfaceDescriptor);
265 
266  //
267  // get endpoint type
268  //
269  if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK)
270  {
271  //
272  // bulk endpoint type
273  //
274  if (USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor->bEndpointAddress))
275  {
276  //
277  // bulk in
278  //
279  *InEndpointDescriptor = EndpointDescriptor;
280  }
281  else
282  {
283  //
284  // bulk out
285  //
286  *OutEndpointDescriptor = EndpointDescriptor;
287  }
288  }
289  else if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT)
290  {
291  //
292  // interrupt endpoint type
293  //
295  }
296  }
297 
298  //
299  // move to next descriptor
300  //
301  CurrentDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)CurrentDescriptor + CurrentDescriptor->bLength);
302 
303  //
304  // was it the last descriptor
305  //
306  if ((ULONG_PTR)CurrentDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
307  {
308  //
309  // reached last descriptor
310  //
311  break;
312  }
313 
314  }while(TRUE);
315 
316  //
317  // check if everything has been found
318  //
319  if (*OutInterfaceDescriptor == NULL || *InEndpointDescriptor == NULL || *OutEndpointDescriptor == NULL)
320  {
321  //
322  // failed to find interface / endpoint descriptor
323  //
324  DPRINT1("USBSTOR_ScanConfigurationDescriptor: Failed to find InterfaceDescriptor %p InEndpointDescriptor %p OutEndpointDescriptor %p\n", *OutInterfaceDescriptor, *InEndpointDescriptor, *OutEndpointDescriptor);
325  return STATUS_UNSUCCESSFUL;
326  }
327 
328  //
329  // completed successfully
330  //
331  return STATUS_SUCCESS;
332 }
333 
334 VOID
336 {
337  DPRINT1("Dumping ConfigurationDescriptor %p\n", ConfigurationDescriptor);
338  DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
339  DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
340  DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
341  DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
342  DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
343  DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
344  DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
345  DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
346 }
347 
348 NTSTATUS
351  IN PFDO_DEVICE_EXTENSION DeviceExtension)
352 {
353  PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
354  PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor, OutEndpointDescriptor;
356  PURB Urb;
358 
359  //
360  // now scan configuration descriptors
361  //
362  Status = USBSTOR_ScanConfigurationDescriptor(DeviceExtension->ConfigurationDescriptor, &InterfaceDescriptor, &InEndpointDescriptor, &OutEndpointDescriptor);
363  if (!NT_SUCCESS(Status))
364  {
365  //
366  // failed to scan
367  //
368  return Status;
369  }
370 
371  //
372  // now allocate one interface entry and terminating null entry
373  //
375  if (!InterfaceList)
376  {
377  //
378  // no memory
379  //
381  }
382 
383  //
384  // initialize interface list entry
385  //
386  InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor;
387 
388  //
389  // now allocate the urb
390  //
391  Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, InterfaceList);
392  if (!Urb)
393  {
394  //
395  // no memory
396  //
399  }
400 
401  //
402  // sanity check
403  //
405 
406  //
407  // submit urb
408  //
409  Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb);
410  if (!NT_SUCCESS(Status))
411  {
412  //
413  // failed to set configuration
414  //
415  DPRINT1("USBSTOR_SelectConfiguration failed to set interface %x\n", Status);
417  ExFreePoolWithTag(Urb, 0);
418  return Status;
419  }
420 
421  //
422  // backup interface information
423  //
424  DeviceExtension->InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)AllocateItem(NonPagedPool, Urb->UrbSelectConfiguration.Interface.Length);
425  if (!DeviceExtension->InterfaceInformation)
426  {
427  //
428  // failed to allocate interface information structure
429  //
431  ExFreePoolWithTag(Urb, 0);
433  }
434 
435  //
436  // copy interface information
437  //
438  RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length);
439 
440  //
441  // store pipe handle
442  //
443  DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
444 
445  //
446  // now prepare interface urb
447  //
448  UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting);
449 
450  //
451  // copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ
452  //
453  RtlCopyMemory(&Urb->UrbSelectInterface.Interface, DeviceExtension->InterfaceInformation, DeviceExtension->InterfaceInformation->Length);
454 
455  //
456  // now select the interface
457  //
458  Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb);
459 
460  //
461  // did it succeed
462  //
463  if (NT_SUCCESS(Status))
464  {
465  //
466  // update configuration info
467  //
468  ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceInformation->Length);
469  RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length);
470  }
471 
472  //
473  // free interface list & urb
474  //
476  ExFreePoolWithTag(Urb, 0);
477 
478  //
479  // done
480  //
481  return Status;
482 }
483 
484 NTSTATUS
486  IN PFDO_DEVICE_EXTENSION DeviceExtension)
487 {
488  ULONG Index;
489  BOOLEAN BulkInFound = FALSE, BulkOutFound = FALSE;
490 
491  //
492  // no enumerate all pipes and extract bulk-in / bulk-out pipe handle
493  //
494  for(Index = 0; Index < DeviceExtension->InterfaceInformation->NumberOfPipes; Index++)
495  {
496  //
497  // check pipe type
498  //
499  if (DeviceExtension->InterfaceInformation->Pipes[Index].PipeType == UsbdPipeTypeBulk)
500  {
501  //
502  // check direction
503  //
504  if (USB_ENDPOINT_DIRECTION_IN(DeviceExtension->InterfaceInformation->Pipes[Index].EndpointAddress))
505  {
506  //
507  // bulk in pipe
508  //
509  DeviceExtension->BulkInPipeIndex = Index;
510 
511  //
512  // there should not be another bulk in pipe
513  //
514  ASSERT(BulkInFound == FALSE);
515  BulkInFound = TRUE;
516  }
517  else
518  {
519  //
520  // bulk out pipe
521  //
522  DeviceExtension->BulkOutPipeIndex = Index;
523 
524  //
525  // there should not be another bulk out pipe
526  //
527  ASSERT(BulkOutFound == FALSE);
528  BulkOutFound = TRUE;
529  }
530  }
531  }
532 
533  //
534  // check if both bulk pipes have been found
535  //
536  if (!BulkInFound || !BulkOutFound)
537  {
538  //
539  // WTF? usb port driver does not give us bulk pipe access
540  //
541  DPRINT1("USBSTOR_GetPipeHandles> BulkInFound %c BulkOutFound %c missing!!!\n", BulkInFound, BulkOutFound);
543  }
544 
545  //
546  // device is configured
547  //
548  return STATUS_SUCCESS;
549 }
#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 USB_ENDPOINT_DIRECTION_IN(x)
Definition: usb100.h:76
struct _USBD_INTERFACE_LIST_ENTRY * PUSBD_INTERFACE_LIST_ENTRY
_In_ PUSBD_INTERFACE_LIST_ENTRY InterfaceList
Definition: usbdlib.h:168
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:30
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS USBSTOR_GetDescriptors(IN PDEVICE_OBJECT DeviceObject)
Definition: descriptor.c:75
#define GET_SELECT_INTERFACE_REQUEST_SIZE(totalPipes)
Definition: usbdlib.h:104
struct _USBD_INTERFACE_INFORMATION * PUSBD_INTERFACE_INFORMATION
WORD LANGID
Definition: typedefs.h:79
struct _USB_INTERFACE_DESCRIPTOR * PUSB_INTERFACE_DESCRIPTOR
#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
struct _USB_CONFIGURATION_DESCRIPTOR * PUSB_CONFIGURATION_DESCRIPTOR
Definition: usbdlib.h:7
VOID FreeItem(IN PVOID Item)
Definition: misc.c:43
NTSTATUS NTAPI USBSTOR_GetDescriptor(IN PDEVICE_OBJECT DeviceObject, IN UCHAR DescriptorType, IN ULONG DescriptorLength, IN UCHAR DescriptorIndex, IN LANGID LanguageId, OUT PVOID *OutDescriptor)
Definition: descriptor.c:18
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
unsigned char BOOLEAN
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usb100.h:52
NTSTATUS USBSTOR_SelectConfigurationAndInterface(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: descriptor.c:234
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI USBSTOR_ScanConfigurationDescriptor(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, OUT PUSB_INTERFACE_DESCRIPTOR *OutInterfaceDescriptor, OUT PUSB_ENDPOINT_DESCRIPTOR *InEndpointDescriptor, OUT PUSB_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor)
Definition: descriptor.c:140
struct _USB_ENDPOINT_DESCRIPTOR * PUSB_ENDPOINT_DESCRIPTOR
#define USB_ENDPOINT_TYPE_MASK
Definition: usb100.h:61
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const UCHAR Index[8]
Definition: usbohci.c:18
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usb100.h:53
#define USB_ENDPOINT_TYPE_BULK
Definition: usb100.h:64
struct _URB * PURB
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
struct _URB_SELECT_CONFIGURATION UrbSelectConfiguration
Definition: usb.h:533
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
Definition: usbdlib.h:8
Definition: usb.h:529
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS USBSTOR_SyncUrbRequest(IN PDEVICE_OBJECT DeviceObject, OUT PURB UrbRequest)
Definition: misc.c:107
#define DPRINT1
Definition: precomp.h:8
#define UsbBuildSelectInterfaceRequest(urb, length, configurationHandle, interfaceNumber, alternateSetting)
Definition: usbdlib.h:59
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS USBSTOR_GetPipeHandles(IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: descriptor.c:319
#define UNIMPLEMENTED
Definition: debug.h:114
#define ULONG_PTR
Definition: config.h:101
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
struct _URB_CONTROL_DESCRIPTOR_REQUEST UrbControlDescriptorRequest
Definition: usb.h:545
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:605
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
struct _URB_SELECT_INTERFACE UrbSelectInterface
Definition: usb.h:532
#define USB_ENDPOINT_TYPE_INTERRUPT
Definition: usb100.h:65
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966