ReactOS 0.4.15-dev-7918-g2a2556c
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
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,
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
104{
106 PFDO_DEVICE_EXTENSION DeviceExtension;
107 USHORT DescriptorLength;
108
109 //
110 // get device extension
111 //
112 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
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
201NTAPI
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
334VOID
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
351 IN PFDO_DEVICE_EXTENSION DeviceExtension)
352{
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 //
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
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}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define UNIMPLEMENTED
Definition: debug.h:115
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
#define ULONG_PTR
Definition: config.h:101
VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
Definition: descriptor.c:399
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 USBSTOR_GetDescriptors(IN PDEVICE_OBJECT DeviceObject)
Definition: descriptor.c:75
NTSTATUS USBSTOR_GetPipeHandles(IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: descriptor.c:319
NTSTATUS USBSTOR_SelectConfigurationAndInterface(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: descriptor.c:234
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
NTSTATUS USBSTOR_SyncUrbRequest(IN PDEVICE_OBJECT DeviceObject, OUT PURB UrbRequest)
Definition: misc.c:83
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
Status
Definition: gdiplustypes.h:25
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:29
VOID FreeItem(IN PVOID Item)
Definition: misc.c:37
USHORT LANGID
Definition: mui.h:9
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:619
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: usb.h:529
struct _URB_SELECT_CONFIGURATION UrbSelectConfiguration
Definition: usb.h:533
struct _URB_CONTROL_DESCRIPTOR_REQUEST UrbControlDescriptorRequest
Definition: usb.h:545
struct _URB_SELECT_INTERFACE UrbSelectInterface
Definition: usb.h:532
Definition: usbdlib.h:7
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
Definition: usbdlib.h:8
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct _USB_CONFIGURATION_DESCRIPTOR * PUSB_CONFIGURATION_DESCRIPTOR
#define USB_ENDPOINT_TYPE_INTERRUPT
Definition: usb100.h:65
#define USB_CONFIGURATION_DESCRIPTOR_TYPE
Definition: usb100.h:50
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usb100.h:53
struct _USB_INTERFACE_DESCRIPTOR * PUSB_INTERFACE_DESCRIPTOR
#define USB_DEVICE_DESCRIPTOR_TYPE
Definition: usb100.h:49
#define USB_STRING_DESCRIPTOR_TYPE
Definition: usb100.h:51
struct _USB_ENDPOINT_DESCRIPTOR * PUSB_ENDPOINT_DESCRIPTOR
#define USB_ENDPOINT_TYPE_MASK
Definition: usb100.h:61
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usb100.h:52
#define USB_ENDPOINT_TYPE_BULK
Definition: usb100.h:64
#define USB_ENDPOINT_DIRECTION_IN(x)
Definition: usb100.h:76
struct _USBD_INTERFACE_INFORMATION * PUSBD_INTERFACE_INFORMATION
struct _URB * PURB
@ UsbdPipeTypeBulk
Definition: usb.h:247
PURB NTAPI USBD_CreateConfigurationRequestEx(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSBD_INTERFACE_LIST_ENTRY InterfaceList)
Definition: usbd.c:329
#define UsbBuildGetDescriptorRequest(urb, length, descriptorType, descriptorIndex, languageId, transferBuffer, transferBufferMDL, transferBufferLength, link)
Definition: usbdlib.h:23
_In_ ULONG _In_ PVOID _In_ LONG DescriptorType
Definition: usbdlib.h:160
#define UsbBuildSelectInterfaceRequest(urb, length, configurationHandle, interfaceNumber, alternateSetting)
Definition: usbdlib.h:59
_In_ PUSBD_INTERFACE_LIST_ENTRY InterfaceList
Definition: usbdlib.h:181
#define GET_SELECT_INTERFACE_REQUEST_SIZE(totalPipes)
Definition: usbdlib.h:117
struct _USBD_INTERFACE_LIST_ENTRY * PUSBD_INTERFACE_LIST_ENTRY
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE Interface
Definition: wdffdo.h:465
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_In_ WDFUSBINTERFACE _In_ UCHAR _Out_ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
Definition: wdfusb.h:2334
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180