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.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
16 USBSTOR_GetDescriptor(
17 IN PDEVICE_OBJECT DeviceObject
,
18 IN UCHAR DescriptorType
,
19 IN ULONG DescriptorLength
,
20 IN UCHAR DescriptorIndex
,
22 OUT PVOID
*OutDescriptor
)
32 ASSERT(OutDescriptor
);
33 ASSERT(DescriptorLength
);
36 // first allocate descriptor buffer
38 Descriptor
= AllocateItem(NonPagedPool
, DescriptorLength
);
44 return STATUS_INSUFFICIENT_RESOURCES
;
50 Urb
= (PURB
) AllocateItem(NonPagedPool
, sizeof(URB
));
57 return STATUS_INSUFFICIENT_RESOURCES
;
63 UsbBuildGetDescriptorRequest(Urb
,
64 sizeof(Urb
->UrbControlDescriptorRequest
),
76 Status
= USBSTOR_SyncUrbRequest(DeviceObject
, Urb
);
83 if (NT_SUCCESS(Status
))
88 *OutDescriptor
= Descriptor
;
99 USBSTOR_GetDescriptors(
100 IN PDEVICE_OBJECT DeviceObject
)
103 PFDO_DEVICE_EXTENSION DeviceExtension
;
104 USHORT DescriptorLength
;
107 // get device extension
109 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
112 // first get device descriptor
114 Status
= USBSTOR_GetDescriptor(DeviceExtension
->LowerDeviceObject
, USB_DEVICE_DESCRIPTOR_TYPE
, sizeof(USB_DEVICE_DESCRIPTOR
), 0, 0, (PVOID
*)&DeviceExtension
->DeviceDescriptor
);
115 if (!NT_SUCCESS(Status
))
118 // failed to get device descriptor
120 DeviceExtension
->DeviceDescriptor
= NULL
;
125 // now get basic configuration descriptor
127 Status
= USBSTOR_GetDescriptor(DeviceExtension
->LowerDeviceObject
, USB_CONFIGURATION_DESCRIPTOR_TYPE
, sizeof(USB_CONFIGURATION_DESCRIPTOR
), 0, 0, (PVOID
*)&DeviceExtension
->ConfigurationDescriptor
);
128 if (!NT_SUCCESS(Status
))
131 // failed to get configuration descriptor
133 FreeItem(DeviceExtension
->DeviceDescriptor
);
134 DeviceExtension
->DeviceDescriptor
= NULL
;
141 DescriptorLength
= DeviceExtension
->ConfigurationDescriptor
->wTotalLength
;
144 // release basic descriptor
146 FreeItem(DeviceExtension
->ConfigurationDescriptor
);
147 DeviceExtension
->ConfigurationDescriptor
= NULL
;
150 // allocate full descriptor
152 Status
= USBSTOR_GetDescriptor(DeviceExtension
->LowerDeviceObject
, USB_CONFIGURATION_DESCRIPTOR_TYPE
, DescriptorLength
, 0, 0, (PVOID
*)&DeviceExtension
->ConfigurationDescriptor
);
153 if (!NT_SUCCESS(Status
))
156 // failed to get configuration descriptor
158 FreeItem(DeviceExtension
->DeviceDescriptor
);
159 DeviceExtension
->DeviceDescriptor
= NULL
;
164 // check if there is a serial number provided
166 if (DeviceExtension
->DeviceDescriptor
->iSerialNumber
)
171 Status
= USBSTOR_GetDescriptor(DeviceExtension
->LowerDeviceObject
, USB_STRING_DESCRIPTOR_TYPE
, 100 * sizeof(WCHAR
), DeviceExtension
->DeviceDescriptor
->iSerialNumber
, 0x0409, (PVOID
*)&DeviceExtension
->SerialNumber
);
172 if (!NT_SUCCESS(Status
))
175 // failed to get serial number descriptor, free device descriptor
177 FreeItem(DeviceExtension
->DeviceDescriptor
);
178 DeviceExtension
->DeviceDescriptor
= NULL
;
181 // free configuration descriptor
183 FreeItem(DeviceExtension
->ConfigurationDescriptor
);
184 DeviceExtension
->ConfigurationDescriptor
= NULL
;
187 // set serial number to zero
189 DeviceExtension
->SerialNumber
= NULL
;
199 USBSTOR_ScanConfigurationDescriptor(
200 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
201 OUT PUSB_INTERFACE_DESCRIPTOR
* OutInterfaceDescriptor
,
202 OUT PUSB_ENDPOINT_DESCRIPTOR
* InEndpointDescriptor
,
203 OUT PUSB_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
205 PUSB_CONFIGURATION_DESCRIPTOR CurrentDescriptor
;
206 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
211 ASSERT(ConfigurationDescriptor
);
212 ASSERT(OutInterfaceDescriptor
);
213 ASSERT(InEndpointDescriptor
);
214 ASSERT(OutEndpointDescriptor
);
219 *OutInterfaceDescriptor
= NULL
;
220 *InEndpointDescriptor
= NULL
;
221 *OutEndpointDescriptor
= NULL
;
226 CurrentDescriptor
= ConfigurationDescriptor
;
231 // check current descriptor type
233 if (CurrentDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
236 // found interface descriptor
238 if (*OutInterfaceDescriptor
)
241 // we only process the first interface descriptor as ms does -> see documentation
247 // store interface descriptor
249 *OutInterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)CurrentDescriptor
;
251 else if (CurrentDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
)
254 // convert to endpoint descriptor
256 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
;
261 ASSERT(*OutInterfaceDescriptor
);
266 if ((EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
)
269 // bulk endpoint type
271 if (USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor
->bEndpointAddress
))
276 *InEndpointDescriptor
= EndpointDescriptor
;
283 *OutEndpointDescriptor
= EndpointDescriptor
;
286 else if ((EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
)
289 // interrupt endpoint type
296 // move to next descriptor
298 CurrentDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)((ULONG_PTR
)CurrentDescriptor
+ CurrentDescriptor
->bLength
);
301 // was it the last descriptor
303 if ((ULONG_PTR
)CurrentDescriptor
>= ((ULONG_PTR
)ConfigurationDescriptor
+ ConfigurationDescriptor
->wTotalLength
))
306 // reached last descriptor
314 // check if everything has been found
316 if (*OutInterfaceDescriptor
== NULL
|| *InEndpointDescriptor
== NULL
|| *OutEndpointDescriptor
== NULL
)
319 // failed to find interface / endpoint descriptor
321 DPRINT1("USBSTOR_ScanConfigurationDescriptor: Failed to find InterfaceDescriptor %p InEndpointDescriptor %p OutEndpointDescriptor %p\n", *OutInterfaceDescriptor
, *InEndpointDescriptor
, *OutEndpointDescriptor
);
322 return STATUS_UNSUCCESSFUL
;
326 // completed successfully
328 return STATUS_SUCCESS
;
332 DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
334 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor
);
335 DPRINT1("bLength %x\n", ConfigurationDescriptor
->bLength
);
336 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor
->bDescriptorType
);
337 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor
->wTotalLength
);
338 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor
->bNumInterfaces
);
339 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor
->bConfigurationValue
);
340 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor
->iConfiguration
);
341 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor
->bmAttributes
);
342 DPRINT1("MaxPower %x\n", ConfigurationDescriptor
->MaxPower
);
346 USBSTOR_SelectConfigurationAndInterface(
347 IN PDEVICE_OBJECT DeviceObject
,
348 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
350 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
351 PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor
, OutEndpointDescriptor
;
354 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
;
357 // now scan configuration descriptors
359 Status
= USBSTOR_ScanConfigurationDescriptor(DeviceExtension
->ConfigurationDescriptor
, &InterfaceDescriptor
, &InEndpointDescriptor
, &OutEndpointDescriptor
);
360 if (!NT_SUCCESS(Status
))
369 // now allocate one interface entry and terminating null entry
371 InterfaceList
= (PUSBD_INTERFACE_LIST_ENTRY
)AllocateItem(PagedPool
, sizeof(USBD_INTERFACE_LIST_ENTRY
) * 2);
377 return STATUS_INSUFFICIENT_RESOURCES
;
381 // initialize interface list entry
383 InterfaceList
[0].InterfaceDescriptor
= InterfaceDescriptor
;
386 // now allocate the urb
388 Urb
= USBD_CreateConfigurationRequestEx(DeviceExtension
->ConfigurationDescriptor
, InterfaceList
);
394 FreeItem(InterfaceList
);
395 return STATUS_INSUFFICIENT_RESOURCES
;
401 ASSERT(InterfaceList
[0].Interface
);
406 Status
= USBSTOR_SyncUrbRequest(DeviceExtension
->LowerDeviceObject
, Urb
);
407 if (!NT_SUCCESS(Status
))
410 // failed to set configuration
412 DPRINT1("USBSTOR_SelectConfiguration failed to set interface %x\n", Status
);
413 FreeItem(InterfaceList
);
419 // backup interface information
421 DeviceExtension
->InterfaceInformation
= (PUSBD_INTERFACE_INFORMATION
)AllocateItem(NonPagedPool
, Urb
->UrbSelectConfiguration
.Interface
.Length
);
422 if (!NT_SUCCESS(Status
))
425 // failed to allocate interface information structure
427 FreeItem(InterfaceList
);
433 // copy interface information
435 RtlCopyMemory(DeviceExtension
->InterfaceInformation
, &Urb
->UrbSelectConfiguration
.Interface
, Urb
->UrbSelectConfiguration
.Interface
.Length
);
440 DeviceExtension
->ConfigurationHandle
= Urb
->UrbSelectConfiguration
.ConfigurationHandle
;
443 // now prepare interface urb
445 UsbBuildSelectInterfaceRequest(Urb
, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor
->bNumEndpoints
), DeviceExtension
->ConfigurationHandle
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
);
448 // copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ
450 RtlCopyMemory(&Urb
->UrbSelectInterface
.Interface
, DeviceExtension
->InterfaceInformation
, DeviceExtension
->InterfaceInformation
->Length
);
453 // now select the interface
455 Status
= USBSTOR_SyncUrbRequest(DeviceExtension
->LowerDeviceObject
, Urb
);
460 if (NT_SUCCESS(Status
))
463 // update configuration info
465 ASSERT(Urb
->UrbSelectInterface
.Interface
.Length
== DeviceExtension
->InterfaceInformation
->Length
);
466 RtlCopyMemory(DeviceExtension
->InterfaceInformation
, &Urb
->UrbSelectInterface
.Interface
, Urb
->UrbSelectInterface
.Interface
.Length
);
470 // free interface list & urb
472 FreeItem(InterfaceList
);
482 USBSTOR_GetPipeHandles(
483 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
486 BOOLEAN BulkInFound
= FALSE
, BulkOutFound
= FALSE
;
489 // no enumerate all pipes and extract bulk-in / bulk-out pipe handle
491 for(Index
= 0; Index
< DeviceExtension
->InterfaceInformation
->NumberOfPipes
; Index
++)
496 if (DeviceExtension
->InterfaceInformation
->Pipes
[Index
].PipeType
== UsbdPipeTypeBulk
)
501 if (USB_ENDPOINT_DIRECTION_IN(DeviceExtension
->InterfaceInformation
->Pipes
[Index
].EndpointAddress
))
506 DeviceExtension
->BulkInPipeIndex
= Index
;
509 // there should not be another bulk in pipe
511 ASSERT(BulkInFound
== FALSE
);
519 DeviceExtension
->BulkOutPipeIndex
= Index
;
522 // there should not be another bulk out pipe
524 ASSERT(BulkOutFound
== FALSE
);
531 // check if both bulk pipes have been found
533 if (!BulkInFound
|| !BulkOutFound
)
536 // WTF? usb port driver does not give us bulk pipe access
538 DPRINT1("USBSTOR_GetPipeHandles> BulkInFound %d BulkOutFound %d missing!!!\n", BulkInFound
, BulkOutFound
);
539 return STATUS_DEVICE_CONFIGURATION_ERROR
;
543 // device is configured
545 return STATUS_SUCCESS
;