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)
19 USBSTOR_GetDescriptor(
20 IN PDEVICE_OBJECT DeviceObject
,
21 IN UCHAR DescriptorType
,
22 IN ULONG DescriptorLength
,
23 IN UCHAR DescriptorIndex
,
25 OUT PVOID
*OutDescriptor
)
35 ASSERT(OutDescriptor
);
36 ASSERT(DescriptorLength
);
39 // first allocate descriptor buffer
41 Descriptor
= AllocateItem(NonPagedPool
, DescriptorLength
);
47 return STATUS_INSUFFICIENT_RESOURCES
;
53 Urb
= (PURB
) AllocateItem(NonPagedPool
, sizeof(URB
));
60 return STATUS_INSUFFICIENT_RESOURCES
;
66 UsbBuildGetDescriptorRequest(Urb
,
67 sizeof(Urb
->UrbControlDescriptorRequest
),
79 Status
= USBSTOR_SyncUrbRequest(DeviceObject
, Urb
);
86 if (NT_SUCCESS(Status
))
91 *OutDescriptor
= Descriptor
;
102 USBSTOR_GetDescriptors(
103 IN PDEVICE_OBJECT DeviceObject
)
106 PFDO_DEVICE_EXTENSION DeviceExtension
;
107 USHORT DescriptorLength
;
110 // get device extension
112 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
115 // first get device descriptor
117 Status
= USBSTOR_GetDescriptor(DeviceExtension
->LowerDeviceObject
, USB_DEVICE_DESCRIPTOR_TYPE
, sizeof(USB_DEVICE_DESCRIPTOR
), 0, 0, (PVOID
*)&DeviceExtension
->DeviceDescriptor
);
118 if (!NT_SUCCESS(Status
))
121 // failed to get device descriptor
123 DeviceExtension
->DeviceDescriptor
= NULL
;
128 // now get basic configuration descriptor
130 Status
= USBSTOR_GetDescriptor(DeviceExtension
->LowerDeviceObject
, USB_CONFIGURATION_DESCRIPTOR_TYPE
, sizeof(USB_CONFIGURATION_DESCRIPTOR
), 0, 0, (PVOID
*)&DeviceExtension
->ConfigurationDescriptor
);
131 if (!NT_SUCCESS(Status
))
134 // failed to get configuration descriptor
136 FreeItem(DeviceExtension
->DeviceDescriptor
);
137 DeviceExtension
->DeviceDescriptor
= NULL
;
144 DescriptorLength
= DeviceExtension
->ConfigurationDescriptor
->wTotalLength
;
147 // release basic descriptor
149 FreeItem(DeviceExtension
->ConfigurationDescriptor
);
150 DeviceExtension
->ConfigurationDescriptor
= NULL
;
153 // allocate full descriptor
155 Status
= USBSTOR_GetDescriptor(DeviceExtension
->LowerDeviceObject
, USB_CONFIGURATION_DESCRIPTOR_TYPE
, DescriptorLength
, 0, 0, (PVOID
*)&DeviceExtension
->ConfigurationDescriptor
);
156 if (!NT_SUCCESS(Status
))
159 // failed to get configuration descriptor
161 FreeItem(DeviceExtension
->DeviceDescriptor
);
162 DeviceExtension
->DeviceDescriptor
= NULL
;
167 // check if there is a serial number provided
169 if (DeviceExtension
->DeviceDescriptor
->iSerialNumber
)
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
))
178 // failed to get serial number descriptor, free device descriptor
180 FreeItem(DeviceExtension
->DeviceDescriptor
);
181 DeviceExtension
->DeviceDescriptor
= NULL
;
184 // free configuration descriptor
186 FreeItem(DeviceExtension
->ConfigurationDescriptor
);
187 DeviceExtension
->ConfigurationDescriptor
= NULL
;
190 // set serial number to zero
192 DeviceExtension
->SerialNumber
= NULL
;
202 USBSTOR_ScanConfigurationDescriptor(
203 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
204 OUT PUSB_INTERFACE_DESCRIPTOR
* OutInterfaceDescriptor
,
205 OUT PUSB_ENDPOINT_DESCRIPTOR
* InEndpointDescriptor
,
206 OUT PUSB_ENDPOINT_DESCRIPTOR
* OutEndpointDescriptor
)
208 PUSB_CONFIGURATION_DESCRIPTOR CurrentDescriptor
;
209 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
214 ASSERT(ConfigurationDescriptor
);
215 ASSERT(OutInterfaceDescriptor
);
216 ASSERT(InEndpointDescriptor
);
217 ASSERT(OutEndpointDescriptor
);
222 *OutInterfaceDescriptor
= NULL
;
223 *InEndpointDescriptor
= NULL
;
224 *OutEndpointDescriptor
= NULL
;
229 CurrentDescriptor
= ConfigurationDescriptor
;
234 // check current descriptor type
236 if (CurrentDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
239 // found interface descriptor
241 if (*OutInterfaceDescriptor
)
244 // we only process the first interface descriptor as ms does -> see documentation
250 // store interface descriptor
252 *OutInterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)CurrentDescriptor
;
254 else if (CurrentDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
)
257 // convert to endpoint descriptor
259 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)CurrentDescriptor
;
264 ASSERT(*OutInterfaceDescriptor
);
269 if ((EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
)
272 // bulk endpoint type
274 if (USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor
->bEndpointAddress
))
279 *InEndpointDescriptor
= EndpointDescriptor
;
286 *OutEndpointDescriptor
= EndpointDescriptor
;
289 else if ((EndpointDescriptor
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_INTERRUPT
)
292 // interrupt endpoint type
299 // move to next descriptor
301 CurrentDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
)((ULONG_PTR
)CurrentDescriptor
+ CurrentDescriptor
->bLength
);
304 // was it the last descriptor
306 if ((ULONG_PTR
)CurrentDescriptor
>= ((ULONG_PTR
)ConfigurationDescriptor
+ ConfigurationDescriptor
->wTotalLength
))
309 // reached last descriptor
317 // check if everything has been found
319 if (*OutInterfaceDescriptor
== NULL
|| *InEndpointDescriptor
== NULL
|| *OutEndpointDescriptor
== NULL
)
322 // failed to find interface / endpoint descriptor
324 DPRINT1("USBSTOR_ScanConfigurationDescriptor: Failed to find InterfaceDescriptor %p InEndpointDescriptor %p OutEndpointDescriptor %p\n", *OutInterfaceDescriptor
, *InEndpointDescriptor
, *OutEndpointDescriptor
);
325 return STATUS_UNSUCCESSFUL
;
329 // completed successfully
331 return STATUS_SUCCESS
;
335 DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
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
);
349 USBSTOR_SelectConfigurationAndInterface(
350 IN PDEVICE_OBJECT DeviceObject
,
351 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
353 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
354 PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor
, OutEndpointDescriptor
;
357 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
;
360 // now scan configuration descriptors
362 Status
= USBSTOR_ScanConfigurationDescriptor(DeviceExtension
->ConfigurationDescriptor
, &InterfaceDescriptor
, &InEndpointDescriptor
, &OutEndpointDescriptor
);
363 if (!NT_SUCCESS(Status
))
372 // now allocate one interface entry and terminating null entry
374 InterfaceList
= (PUSBD_INTERFACE_LIST_ENTRY
)AllocateItem(PagedPool
, sizeof(USBD_INTERFACE_LIST_ENTRY
) * 2);
380 return STATUS_INSUFFICIENT_RESOURCES
;
384 // initialize interface list entry
386 InterfaceList
[0].InterfaceDescriptor
= InterfaceDescriptor
;
389 // now allocate the urb
391 Urb
= USBD_CreateConfigurationRequestEx(DeviceExtension
->ConfigurationDescriptor
, InterfaceList
);
397 FreeItem(InterfaceList
);
398 return STATUS_INSUFFICIENT_RESOURCES
;
404 ASSERT(InterfaceList
[0].Interface
);
409 Status
= USBSTOR_SyncUrbRequest(DeviceExtension
->LowerDeviceObject
, Urb
);
410 if (!NT_SUCCESS(Status
))
413 // failed to set configuration
415 DPRINT1("USBSTOR_SelectConfiguration failed to set interface %x\n", Status
);
416 FreeItem(InterfaceList
);
422 // backup interface information
424 DeviceExtension
->InterfaceInformation
= (PUSBD_INTERFACE_INFORMATION
)AllocateItem(NonPagedPool
, Urb
->UrbSelectConfiguration
.Interface
.Length
);
425 if (!NT_SUCCESS(Status
))
428 // failed to allocate interface information structure
430 FreeItem(InterfaceList
);
436 // copy interface information
438 RtlCopyMemory(DeviceExtension
->InterfaceInformation
, &Urb
->UrbSelectConfiguration
.Interface
, Urb
->UrbSelectConfiguration
.Interface
.Length
);
443 DeviceExtension
->ConfigurationHandle
= Urb
->UrbSelectConfiguration
.ConfigurationHandle
;
446 // now prepare interface urb
448 UsbBuildSelectInterfaceRequest(Urb
, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor
->bNumEndpoints
), DeviceExtension
->ConfigurationHandle
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
);
451 // copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ
453 RtlCopyMemory(&Urb
->UrbSelectInterface
.Interface
, DeviceExtension
->InterfaceInformation
, DeviceExtension
->InterfaceInformation
->Length
);
456 // now select the interface
458 Status
= USBSTOR_SyncUrbRequest(DeviceExtension
->LowerDeviceObject
, Urb
);
463 if (NT_SUCCESS(Status
))
466 // update configuration info
468 ASSERT(Urb
->UrbSelectInterface
.Interface
.Length
== DeviceExtension
->InterfaceInformation
->Length
);
469 RtlCopyMemory(DeviceExtension
->InterfaceInformation
, &Urb
->UrbSelectInterface
.Interface
, Urb
->UrbSelectInterface
.Interface
.Length
);
473 // free interface list & urb
475 FreeItem(InterfaceList
);
485 USBSTOR_GetPipeHandles(
486 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
489 BOOLEAN BulkInFound
= FALSE
, BulkOutFound
= FALSE
;
492 // no enumerate all pipes and extract bulk-in / bulk-out pipe handle
494 for(Index
= 0; Index
< DeviceExtension
->InterfaceInformation
->NumberOfPipes
; Index
++)
499 if (DeviceExtension
->InterfaceInformation
->Pipes
[Index
].PipeType
== UsbdPipeTypeBulk
)
504 if (USB_ENDPOINT_DIRECTION_IN(DeviceExtension
->InterfaceInformation
->Pipes
[Index
].EndpointAddress
))
509 DeviceExtension
->BulkInPipeIndex
= Index
;
512 // there should not be another bulk in pipe
514 ASSERT(BulkInFound
== FALSE
);
522 DeviceExtension
->BulkOutPipeIndex
= Index
;
525 // there should not be another bulk out pipe
527 ASSERT(BulkOutFound
== FALSE
);
534 // check if both bulk pipes have been found
536 if (!BulkInFound
|| !BulkOutFound
)
539 // WTF? usb port driver does not give us bulk pipe access
541 DPRINT1("USBSTOR_GetPipeHandles> BulkInFound %c BulkOutFound %c missing!!!\n", BulkInFound
, BulkOutFound
);
542 return STATUS_DEVICE_CONFIGURATION_ERROR
;
546 // device is configured
548 return STATUS_SUCCESS
;