[SHELL32] Remove 2 redundant initializations
[reactos.git] / drivers / usb / usbstor / descriptor.c
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
16 NTSTATUS
17 NTAPI
18 USBSTOR_GetDescriptor(
19 IN PDEVICE_OBJECT DeviceObject,
20 IN UCHAR DescriptorType,
21 IN ULONG DescriptorLength,
22 IN UCHAR DescriptorIndex,
23 IN LANGID LanguageId,
24 OUT PVOID *OutDescriptor)
25 {
26 PURB Urb;
27 NTSTATUS Status;
28 PVOID Descriptor;
29
30 ASSERT(DeviceObject);
31 ASSERT(OutDescriptor);
32 ASSERT(DescriptorLength);
33
34 // first allocate descriptor buffer
35 Descriptor = AllocateItem(NonPagedPool, DescriptorLength);
36 if (!Descriptor)
37 {
38 // no memory
39 return STATUS_INSUFFICIENT_RESOURCES;
40 }
41
42 Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB));
43 if (!Urb)
44 {
45 // no memory
46 FreeItem(Descriptor);
47 return STATUS_INSUFFICIENT_RESOURCES;
48 }
49
50 // initialize urb
51 UsbBuildGetDescriptorRequest(Urb,
52 sizeof(Urb->UrbControlDescriptorRequest),
53 DescriptorType,
54 DescriptorIndex,
55 LanguageId,
56 Descriptor,
57 NULL,
58 DescriptorLength,
59 NULL);
60
61 // submit urb
62 Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
63
64 FreeItem(Urb);
65
66 if (NT_SUCCESS(Status))
67 {
68 *OutDescriptor = Descriptor;
69 }
70
71 return Status;
72 }
73
74 NTSTATUS
75 USBSTOR_GetDescriptors(
76 IN PDEVICE_OBJECT DeviceObject)
77 {
78 NTSTATUS Status;
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, 100 * sizeof(WCHAR), 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
138 NTSTATUS
139 NTAPI
140 USBSTOR_ScanConfigurationDescriptor(
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 {
194 UNIMPLEMENTED;
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
219 VOID
220 DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
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
233 NTSTATUS
234 USBSTOR_SelectConfigurationAndInterface(
235 IN PDEVICE_OBJECT DeviceObject,
236 IN PFDO_DEVICE_EXTENSION DeviceExtension)
237 {
238 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
239 PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor, OutEndpointDescriptor;
240 NTSTATUS Status;
241 PURB Urb;
242 PUSBD_INTERFACE_LIST_ENTRY InterfaceList;
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
251 InterfaceList = (PUSBD_INTERFACE_LIST_ENTRY)AllocateItem(PagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * 2);
252 if (!InterfaceList)
253 {
254 return STATUS_INSUFFICIENT_RESOURCES;
255 }
256
257 // initialize interface list entry
258 InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor;
259
260 // now allocate the urb
261 Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, InterfaceList);
262 if (!Urb)
263 {
264 FreeItem(InterfaceList);
265 return STATUS_INSUFFICIENT_RESOURCES;
266 }
267
268
269 ASSERT(InterfaceList[0].Interface);
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);
277 FreeItem(InterfaceList);
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 {
286 FreeItem(InterfaceList);
287 ExFreePoolWithTag(Urb, 0);
288 return STATUS_INSUFFICIENT_RESOURCES;
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
312 FreeItem(InterfaceList);
313 ExFreePoolWithTag(Urb, 0);
314
315 return Status;
316 }
317
318 NTSTATUS
319 USBSTOR_GetPipeHandles(
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);
353 return STATUS_DEVICE_CONFIGURATION_ERROR;
354 }
355
356 return STATUS_SUCCESS;
357 }