[DRIVERS] Spelling fixes by Josh Soref. CORE-12286
[reactos.git] / reactos / drivers / usb / usbstor / descriptor.c
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
17 NTSTATUS
18 NTAPI
19 USBSTOR_GetDescriptor(
20 IN PDEVICE_OBJECT DeviceObject,
21 IN UCHAR DescriptorType,
22 IN ULONG DescriptorLength,
23 IN UCHAR DescriptorIndex,
24 IN LANGID LanguageId,
25 OUT PVOID *OutDescriptor)
26 {
27 PURB Urb;
28 NTSTATUS Status;
29 PVOID Descriptor;
30
31 //
32 // sanity checks
33 //
34 ASSERT(DeviceObject);
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 //
47 return STATUS_INSUFFICIENT_RESOURCES;
48 }
49
50 //
51 // allocate urb
52 //
53 Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB));
54 if (!Urb)
55 {
56 //
57 // no memory
58 //
59 FreeItem(Descriptor);
60 return STATUS_INSUFFICIENT_RESOURCES;
61 }
62
63 //
64 // initialize urb
65 //
66 UsbBuildGetDescriptorRequest(Urb,
67 sizeof(Urb->UrbControlDescriptorRequest),
68 DescriptorType,
69 DescriptorIndex,
70 LanguageId,
71 Descriptor,
72 NULL,
73 DescriptorLength,
74 NULL);
75
76 //
77 // submit urb
78 //
79 Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
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
101 NTSTATUS
102 USBSTOR_GetDescriptors(
103 IN PDEVICE_OBJECT DeviceObject)
104 {
105 NTSTATUS Status;
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
200 NTSTATUS
201 NTAPI
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)
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 //
294 UNIMPLEMENTED
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
334 VOID
335 DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
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
348 NTSTATUS
349 USBSTOR_SelectConfigurationAndInterface(
350 IN PDEVICE_OBJECT DeviceObject,
351 IN PFDO_DEVICE_EXTENSION DeviceExtension)
352 {
353 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
354 PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor, OutEndpointDescriptor;
355 NTSTATUS Status;
356 PURB Urb;
357 PUSBD_INTERFACE_LIST_ENTRY InterfaceList;
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 //
374 InterfaceList = (PUSBD_INTERFACE_LIST_ENTRY)AllocateItem(PagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * 2);
375 if (!InterfaceList)
376 {
377 //
378 // no memory
379 //
380 return STATUS_INSUFFICIENT_RESOURCES;
381 }
382
383 //
384 // initialize interface list entry
385 //
386 InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor;
387
388 //
389 // now allocate the urb
390 //
391 Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, InterfaceList);
392 if (!Urb)
393 {
394 //
395 // no memory
396 //
397 FreeItem(InterfaceList);
398 return STATUS_INSUFFICIENT_RESOURCES;
399 }
400
401 //
402 // sanity check
403 //
404 ASSERT(InterfaceList[0].Interface);
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);
416 FreeItem(InterfaceList);
417 ExFreePool(Urb);
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 (!NT_SUCCESS(Status))
426 {
427 //
428 // failed to allocate interface information structure
429 //
430 FreeItem(InterfaceList);
431 ExFreePool(Urb);
432 return Status;
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 //
475 FreeItem(InterfaceList);
476 ExFreePool(Urb);
477
478 //
479 // done
480 //
481 return Status;
482 }
483
484 NTSTATUS
485 USBSTOR_GetPipeHandles(
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);
542 return STATUS_DEVICE_CONFIGURATION_ERROR;
543 }
544
545 //
546 // device is configured
547 //
548 return STATUS_SUCCESS;
549 }