ReactOS 0.4.15-dev-7953-g1f49173
descriptor.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: USB block storage device driver.
5 * COPYRIGHT: 2005-2006 James Tabor
6 * 2011-2012 Michael Martin (michael.martin@reactos.org)
7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
8 */
9
10#include "usbstor.h"
11
12#define NDEBUG
13#include <debug.h>
14
15
21 IN ULONG DescriptorLength,
22 IN UCHAR DescriptorIndex,
23 IN LANGID LanguageId,
24 OUT PVOID *OutDescriptor)
25{
26 PURB Urb;
29
31 ASSERT(OutDescriptor);
32 ASSERT(DescriptorLength);
33
34 // first allocate descriptor buffer
35 Descriptor = AllocateItem(NonPagedPool, DescriptorLength);
36 if (!Descriptor)
37 {
38 // no memory
40 }
41
42 Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB));
43 if (!Urb)
44 {
45 // no memory
48 }
49
50 // initialize urb
52 sizeof(Urb->UrbControlDescriptorRequest),
54 DescriptorIndex,
55 LanguageId,
57 NULL,
58 DescriptorLength,
59 NULL);
60
61 // submit urb
63
64 FreeItem(Urb);
65
66 if (NT_SUCCESS(Status))
67 {
68 *OutDescriptor = Descriptor;
69 }
70
71 return Status;
72}
73
77{
79 PFDO_DEVICE_EXTENSION DeviceExtension;
80 USHORT DescriptorLength;
81
82 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
83
84 // first get device descriptor
85 Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor);
86 if (!NT_SUCCESS(Status))
87 {
88 DeviceExtension->DeviceDescriptor = NULL;
89 return Status;
90 }
91
92 // now get basic configuration descriptor
93 Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
94 if (!NT_SUCCESS(Status))
95 {
96 FreeItem(DeviceExtension->DeviceDescriptor);
97 DeviceExtension->DeviceDescriptor = NULL;
98 return Status;
99 }
100
101 // backup length
102 DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength;
103
104 // release basic descriptor
105 FreeItem(DeviceExtension->ConfigurationDescriptor);
106 DeviceExtension->ConfigurationDescriptor = NULL;
107
108 // allocate full descriptor
109 Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
110 if (!NT_SUCCESS(Status))
111 {
112 FreeItem(DeviceExtension->DeviceDescriptor);
113 DeviceExtension->DeviceDescriptor = NULL;
114 return Status;
115 }
116
117 // check if there is a serial number provided
118 if (DeviceExtension->DeviceDescriptor->iSerialNumber)
119 {
120 // get serial number
121 Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_STRING_DESCRIPTOR_TYPE, MAXIMUM_USB_STRING_LENGTH, DeviceExtension->DeviceDescriptor->iSerialNumber, 0x0409, (PVOID*)&DeviceExtension->SerialNumber);
122 if (!NT_SUCCESS(Status))
123 {
124 FreeItem(DeviceExtension->DeviceDescriptor);
125 DeviceExtension->DeviceDescriptor = NULL;
126
127 FreeItem(DeviceExtension->ConfigurationDescriptor);
128 DeviceExtension->ConfigurationDescriptor = NULL;
129
130 DeviceExtension->SerialNumber = NULL;
131 return Status;
132 }
133 }
134
135 return Status;
136}
137
139NTAPI
141 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
142 OUT PUSB_INTERFACE_DESCRIPTOR *OutInterfaceDescriptor,
143 OUT PUSB_ENDPOINT_DESCRIPTOR *InEndpointDescriptor,
144 OUT PUSB_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor)
145{
146 PUSB_CONFIGURATION_DESCRIPTOR CurrentDescriptor;
147 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
148
149 ASSERT(ConfigurationDescriptor);
150 ASSERT(OutInterfaceDescriptor);
151 ASSERT(InEndpointDescriptor);
152 ASSERT(OutEndpointDescriptor);
153
154 *OutInterfaceDescriptor = NULL;
155 *InEndpointDescriptor = NULL;
156 *OutEndpointDescriptor = NULL;
157
158 // start scanning
159 CurrentDescriptor = ConfigurationDescriptor;
160
161 do
162 {
163 if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
164 {
165 if (*OutInterfaceDescriptor)
166 {
167 // we only process the first interface descriptor as ms does -> see documentation
168 break;
169 }
170
171 // store interface descriptor
172 *OutInterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)CurrentDescriptor;
173 }
174 else if (CurrentDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
175 {
176 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)CurrentDescriptor;
177
178 ASSERT(*OutInterfaceDescriptor);
179
180 // get endpoint type
181 if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK)
182 {
183 if (USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor->bEndpointAddress))
184 {
185 *InEndpointDescriptor = EndpointDescriptor;
186 }
187 else
188 {
189 *OutEndpointDescriptor = EndpointDescriptor;
190 }
191 }
192 else if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT)
193 {
195 }
196 }
197
198 // move to next descriptor
199 CurrentDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)CurrentDescriptor + CurrentDescriptor->bLength);
200
201 // was it the last descriptor
202 if ((ULONG_PTR)CurrentDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
203 {
204 break;
205 }
206
207 } while(TRUE);
208
209 // check if everything has been found
210 if (*OutInterfaceDescriptor == NULL || *InEndpointDescriptor == NULL || *OutEndpointDescriptor == NULL)
211 {
212 DPRINT1("USBSTOR_ScanConfigurationDescriptor: Failed to find InterfaceDescriptor %p InEndpointDescriptor %p OutEndpointDescriptor %p\n", *OutInterfaceDescriptor, *InEndpointDescriptor, *OutEndpointDescriptor);
213 return STATUS_UNSUCCESSFUL;
214 }
215
216 return STATUS_SUCCESS;
217}
218
219VOID
221{
222 DPRINT1("Dumping ConfigurationDescriptor %p\n", ConfigurationDescriptor);
223 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
224 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
225 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
226 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
227 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
228 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
229 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
230 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
231}
232
236 IN PFDO_DEVICE_EXTENSION DeviceExtension)
237{
239 PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor, OutEndpointDescriptor;
241 PURB Urb;
243
244 Status = USBSTOR_ScanConfigurationDescriptor(DeviceExtension->ConfigurationDescriptor, &InterfaceDescriptor, &InEndpointDescriptor, &OutEndpointDescriptor);
245 if (!NT_SUCCESS(Status))
246 {
247 return Status;
248 }
249
250 // now allocate one interface entry and terminating null entry
252 if (!InterfaceList)
253 {
255 }
256
257 // initialize interface list entry
259
260 // now allocate the urb
261 Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, InterfaceList);
262 if (!Urb)
263 {
266 }
267
268
270
271 // submit urb
272 Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb);
273 if (!NT_SUCCESS(Status))
274 {
275 // failed to set configuration
276 DPRINT1("USBSTOR_SelectConfiguration failed to set interface %x\n", Status);
278 ExFreePoolWithTag(Urb, 0);
279 return Status;
280 }
281
282 // backup interface information
283 DeviceExtension->InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)AllocateItem(NonPagedPool, Urb->UrbSelectConfiguration.Interface.Length);
284 if (!DeviceExtension->InterfaceInformation)
285 {
287 ExFreePoolWithTag(Urb, 0);
289 }
290
291 // copy interface information
292 RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length);
293
294 // store pipe handle
295 DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
296
297 // now prepare interface urb
298 UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting);
299
300 // copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ
301 RtlCopyMemory(&Urb->UrbSelectInterface.Interface, DeviceExtension->InterfaceInformation, DeviceExtension->InterfaceInformation->Length);
302
303 // now select the interface
304 Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb);
305 if (NT_SUCCESS(Status))
306 {
307 // update configuration info
308 ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceInformation->Length);
309 RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length);
310 }
311
313 ExFreePoolWithTag(Urb, 0);
314
315 return Status;
316}
317
320 IN PFDO_DEVICE_EXTENSION DeviceExtension)
321{
322 ULONG Index;
323 BOOLEAN BulkInFound = FALSE, BulkOutFound = FALSE;
324
325 // enumerate all pipes and extract bulk-in / bulk-out pipe handle
326 for (Index = 0; Index < DeviceExtension->InterfaceInformation->NumberOfPipes; Index++)
327 {
328 if (DeviceExtension->InterfaceInformation->Pipes[Index].PipeType == UsbdPipeTypeBulk)
329 {
330 if (USB_ENDPOINT_DIRECTION_IN(DeviceExtension->InterfaceInformation->Pipes[Index].EndpointAddress))
331 {
332 DeviceExtension->BulkInPipeIndex = Index;
333
334 // there should not be another bulk in pipe
335 ASSERT(BulkInFound == FALSE);
336 BulkInFound = TRUE;
337 }
338 else
339 {
340 DeviceExtension->BulkOutPipeIndex = Index;
341
342 // there should not be another bulk out pipe
343 ASSERT(BulkOutFound == FALSE);
344 BulkOutFound = TRUE;
345 }
346 }
347 }
348
349 if (!BulkInFound || !BulkOutFound)
350 {
351 // WTF? usb port driver does not give us bulk pipe access
352 DPRINT1("USBSTOR_GetPipeHandles> BulkInFound %c BulkOutFound %c missing!!!\n", BulkInFound, BulkOutFound);
354 }
355
356 return STATUS_SUCCESS;
357}
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 MAXIMUM_USB_STRING_LENGTH
Definition: usb100.h:43
#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