46c63754b162dd18f255a76ec341c4bd30306df5
[reactos.git] / drivers / usb / usbstor / disk.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/disk.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 NTSTATUS
15 USBSTOR_HandleInternalDeviceControl(
16 IN PDEVICE_OBJECT DeviceObject,
17 IN PIRP Irp)
18 {
19 PIO_STACK_LOCATION IoStack;
20 PSCSI_REQUEST_BLOCK Request;
21 PPDO_DEVICE_EXTENSION PDODeviceExtension;
22 NTSTATUS Status;
23
24 //
25 // get current stack location
26 //
27 IoStack = IoGetCurrentIrpStackLocation(Irp);
28
29 //
30 // get request block
31 //
32 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
33
34 //
35 // sanity check
36 //
37 ASSERT(Request);
38
39 //
40 // get device extension
41 //
42 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
43
44 //
45 // sanity check
46 //
47 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
48
49 switch(Request->Function)
50 {
51 case SRB_FUNCTION_EXECUTE_SCSI:
52 {
53 DPRINT("SRB_FUNCTION_EXECUTE_SCSI\n");
54
55 //
56 // check if request is valid
57 //
58 if (Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT))
59 {
60 //
61 // data is transferred with this irp
62 //
63 if ((Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)) == (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT) ||
64 Request->DataTransferLength == 0 ||
65 Irp->MdlAddress == NULL)
66 {
67 //
68 // invalid parameter
69 //
70 Status = STATUS_INVALID_PARAMETER;
71 break;
72 }
73 }
74 else
75 {
76 //
77 // sense buffer request
78 //
79 if (Request->DataTransferLength ||
80 Request->DataBuffer ||
81 Irp->MdlAddress)
82 {
83 //
84 // invalid parameter
85 //
86 Status = STATUS_INVALID_PARAMETER;
87 break;
88 }
89 }
90
91 //
92 // add the request
93 //
94 if (!USBSTOR_QueueAddIrp(PDODeviceExtension->LowerDeviceObject, Irp))
95 {
96 //
97 // irp was not added to the queue
98 //
99 IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
100 }
101
102 //
103 // irp pending
104 //
105 return STATUS_PENDING;
106 }
107 case SRB_FUNCTION_RELEASE_DEVICE:
108 {
109 DPRINT1("SRB_FUNCTION_RELEASE_DEVICE\n");
110 //
111 // sanity check
112 //
113 ASSERT(PDODeviceExtension->Claimed == TRUE);
114
115 //
116 // release claim
117 //
118 PDODeviceExtension->Claimed = FALSE;
119 Status = STATUS_SUCCESS;
120 break;
121 }
122 case SRB_FUNCTION_CLAIM_DEVICE:
123 {
124 DPRINT1("SRB_FUNCTION_CLAIM_DEVICE\n");
125 //
126 // check if the device has been claimed
127 //
128 if (PDODeviceExtension->Claimed)
129 {
130 //
131 // device has already been claimed
132 //
133 Status = STATUS_DEVICE_BUSY;
134 Request->SrbStatus = SRB_STATUS_BUSY;
135 break;
136 }
137
138 //
139 // claim device
140 //
141 PDODeviceExtension->Claimed = TRUE;
142
143 //
144 // output device object
145 //
146 Request->DataBuffer = DeviceObject;
147
148 //
149 // completed successfully
150 //
151 Status = STATUS_SUCCESS;
152 break;
153 }
154 case SRB_FUNCTION_RELEASE_QUEUE:
155 {
156 DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
157
158 //
159 // release queue
160 //
161 USBSTOR_QueueRelease(PDODeviceExtension->LowerDeviceObject);
162
163 //
164 // set status success
165 //
166 Request->SrbStatus = SRB_STATUS_SUCCESS;
167 Status = STATUS_SUCCESS;
168 break;
169 }
170
171 case SRB_FUNCTION_FLUSH:
172 case SRB_FUNCTION_FLUSH_QUEUE:
173 {
174 DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE\n");
175
176 //
177 // flush all requests
178 //
179 USBSTOR_QueueFlushIrps(PDODeviceExtension->LowerDeviceObject);
180
181 //
182 // set status success
183 //
184 Request->SrbStatus = SRB_STATUS_SUCCESS;
185 Status = STATUS_SUCCESS;
186 break;
187 }
188 default:
189 {
190 //
191 // not supported
192 //
193 Status = STATUS_NOT_SUPPORTED;
194 Request->SrbStatus = SRB_STATUS_ERROR;
195 }
196 }
197
198 //
199 // complete request
200 //
201 Irp->IoStatus.Status = Status;
202 IoCompleteRequest(Irp, IO_NO_INCREMENT);
203 return Status;
204 }
205
206 ULONG
207 USBSTOR_GetFieldLength(
208 IN PUCHAR Name,
209 IN ULONG MaxLength)
210 {
211 ULONG Index;
212 ULONG LastCharacterPosition = 0;
213
214 //
215 // scan the field and return last positon which contains a valid character
216 //
217 for(Index = 0; Index < MaxLength; Index++)
218 {
219 if (Name[Index] != ' ')
220 {
221 //
222 // trim white spaces from field
223 //
224 LastCharacterPosition = Index;
225 }
226 }
227
228 //
229 // convert from zero based index to length
230 //
231 return LastCharacterPosition + 1;
232 }
233
234 NTSTATUS
235 USBSTOR_HandleQueryProperty(
236 IN PDEVICE_OBJECT DeviceObject,
237 IN PIRP Irp)
238 {
239 PIO_STACK_LOCATION IoStack;
240 PSTORAGE_PROPERTY_QUERY PropertyQuery;
241 PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader;
242 PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
243 ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength, FieldLengthSerialNumber;
244 PPDO_DEVICE_EXTENSION PDODeviceExtension;
245 PUFI_INQUIRY_RESPONSE InquiryData;
246 PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
247 PUCHAR Buffer;
248 PFDO_DEVICE_EXTENSION FDODeviceExtension;
249 UNICODE_STRING SerialNumber;
250 ANSI_STRING AnsiString;
251 NTSTATUS Status;
252
253 DPRINT1("USBSTOR_HandleQueryProperty\n");
254
255 //
256 // get current stack location
257 //
258 IoStack = IoGetCurrentIrpStackLocation(Irp);
259
260 //
261 // sanity check
262 //
263 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY));
264 ASSERT(Irp->AssociatedIrp.SystemBuffer);
265
266 //
267 // get property query
268 //
269 PropertyQuery = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
270
271 //
272 // check property type
273 //
274 if (PropertyQuery->PropertyId != StorageDeviceProperty &&
275 PropertyQuery->PropertyId != StorageAdapterProperty)
276 {
277 //
278 // only device property / adapter property are supported
279 //
280 return STATUS_INVALID_PARAMETER_1;
281 }
282
283 //
284 // check query type
285 //
286 if (PropertyQuery->QueryType == PropertyExistsQuery)
287 {
288 //
289 // device property / adapter property is supported
290 //
291 return STATUS_SUCCESS;
292 }
293
294 if (PropertyQuery->QueryType != PropertyStandardQuery)
295 {
296 //
297 // only standard query and exists query are supported
298 //
299 return STATUS_INVALID_PARAMETER_2;
300 }
301
302 //
303 // check if it is a device property
304 //
305 if (PropertyQuery->PropertyId == StorageDeviceProperty)
306 {
307 DPRINT1("USBSTOR_HandleQueryProperty StorageDeviceProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
308
309 //
310 // get device extension
311 //
312 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
313 ASSERT(PDODeviceExtension);
314 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
315
316 //
317 // get device extension
318 //
319 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
320 ASSERT(FDODeviceExtension);
321 ASSERT(FDODeviceExtension->Common.IsFDO);
322
323 //
324 // get inquiry data
325 //
326 InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
327 ASSERT(InquiryData);
328
329 //
330 // compute extra parameters length
331 //
332 FieldLengthVendor = USBSTOR_GetFieldLength(InquiryData->Vendor, 8);
333 FieldLengthProduct = USBSTOR_GetFieldLength(InquiryData->Product, 16);
334 FieldLengthRevision = USBSTOR_GetFieldLength(InquiryData->Revision, 4);
335
336 //
337 // is there a serial number
338 //
339 if (FDODeviceExtension->SerialNumber)
340 {
341 //
342 // get length
343 //
344 FieldLengthSerialNumber = wcslen(FDODeviceExtension->SerialNumber->bString);
345 }
346 else
347 {
348 //
349 // no serial number
350 //
351 FieldLengthSerialNumber = 0;
352 }
353
354 //
355 // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 4 extra null bytes - 1
356 // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
357 //
358 TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3;
359
360 //
361 // check if output buffer is long enough
362 //
363 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < TotalLength)
364 {
365 //
366 // buffer too small
367 //
368 DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer;
369 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER));
370
371 //
372 // return required size
373 //
374 DescriptorHeader->Version = TotalLength;
375 DescriptorHeader->Size = TotalLength;
376
377 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
378 return STATUS_SUCCESS;
379 }
380
381 //
382 // get device descriptor
383 //
384 DeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
385
386 //
387 // initialize device descriptor
388 //
389 DeviceDescriptor->Version = TotalLength;
390 DeviceDescriptor->Size = TotalLength;
391 DeviceDescriptor->DeviceType = InquiryData->DeviceType;
392 DeviceDescriptor->DeviceTypeModifier = (InquiryData->RMB & 0x7F);
393 DeviceDescriptor->RemovableMedia = TRUE;
394 DeviceDescriptor->CommandQueueing = FALSE;
395 DeviceDescriptor->BusType = BusTypeUsb;
396 DeviceDescriptor->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR);
397 DeviceDescriptor->ProductIdOffset = DeviceDescriptor->VendorIdOffset + FieldLengthVendor + 1;
398 DeviceDescriptor->ProductRevisionOffset = DeviceDescriptor->ProductIdOffset + FieldLengthProduct + 1;
399 DeviceDescriptor->SerialNumberOffset = (FieldLengthSerialNumber > 0 ? DeviceDescriptor->ProductRevisionOffset + FieldLengthRevision + 1 : 0);
400 DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3 + (FieldLengthSerialNumber > 0 ? + 1 : 0);
401
402 //
403 // copy descriptors
404 //
405 Buffer = (PUCHAR)((ULONG_PTR)DeviceDescriptor + sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR));
406
407 //
408 // copy vendor
409 //
410 RtlCopyMemory(Buffer, InquiryData->Vendor, FieldLengthVendor);
411 Buffer[FieldLengthVendor] = '\0';
412 Buffer += FieldLengthVendor + 1;
413
414 //
415 // copy product
416 //
417 RtlCopyMemory(Buffer, InquiryData->Product, FieldLengthProduct);
418 Buffer[FieldLengthProduct] = '\0';
419 Buffer += FieldLengthProduct + 1;
420
421 //
422 // copy revision
423 //
424 RtlCopyMemory(Buffer, InquiryData->Revision, FieldLengthRevision);
425 Buffer[FieldLengthRevision] = '\0';
426 Buffer += FieldLengthRevision + 1;
427
428 //
429 // copy serial number
430 //
431 if (FieldLengthSerialNumber)
432 {
433 //
434 // init unicode string
435 //
436 RtlInitUnicodeString(&SerialNumber, FDODeviceExtension->SerialNumber->bString);
437
438 //
439 // init ansi string
440 //
441 AnsiString.Buffer = (PCHAR)Buffer;
442 AnsiString.Length = 0;
443 AnsiString.MaximumLength = FieldLengthSerialNumber * sizeof(WCHAR);
444
445 //
446 // convert to ansi code
447 //
448 Status = RtlUnicodeStringToAnsiString(&AnsiString, &SerialNumber, FALSE);
449 ASSERT(Status == STATUS_SUCCESS);
450 }
451
452
453 DPRINT("Vendor %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->VendorIdOffset));
454 DPRINT("Product %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductIdOffset));
455 DPRINT("Revision %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductRevisionOffset));
456 DPRINT("Serial %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->SerialNumberOffset));
457
458 //
459 // done
460 //
461 Irp->IoStatus.Information = TotalLength;
462 return STATUS_SUCCESS;
463 }
464 else
465 {
466 //
467 // adapter property query request
468 //
469 DPRINT1("USBSTOR_HandleQueryProperty StorageAdapterProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
470
471 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_ADAPTER_DESCRIPTOR))
472 {
473 //
474 // buffer too small
475 //
476 DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer;
477 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER));
478
479 //
480 // return required size
481 //
482 DescriptorHeader->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
483 DescriptorHeader->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
484
485 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
486 return STATUS_SUCCESS;
487 }
488
489 //
490 // get adapter descriptor, information is returned in the same buffer
491 //
492 AdapterDescriptor = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
493
494 //
495 // fill out descriptor
496 //
497 AdapterDescriptor->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
498 AdapterDescriptor->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
499 AdapterDescriptor->MaximumTransferLength = MAXULONG; //FIXME compute some sane value
500 AdapterDescriptor->MaximumPhysicalPages = 25; //FIXME compute some sane value
501 AdapterDescriptor->AlignmentMask = 0;
502 AdapterDescriptor->AdapterUsesPio = FALSE;
503 AdapterDescriptor->AdapterScansDown = FALSE;
504 AdapterDescriptor->CommandQueueing = FALSE;
505 AdapterDescriptor->AcceleratedTransfer = FALSE;
506 AdapterDescriptor->BusType = BusTypeUsb;
507 AdapterDescriptor->BusMajorVersion = 0x2; //FIXME verify
508 AdapterDescriptor->BusMinorVersion = 0x00; //FIXME
509
510 //
511 // store returned length
512 //
513 Irp->IoStatus.Information = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
514
515 //
516 // done
517 //
518 return STATUS_SUCCESS;
519 }
520 }
521
522 NTSTATUS
523 USBSTOR_HandleDeviceControl(
524 IN PDEVICE_OBJECT DeviceObject,
525 IN PIRP Irp)
526 {
527 PIO_STACK_LOCATION IoStack;
528 NTSTATUS Status;
529
530 //
531 // get current stack location
532 //
533 IoStack = IoGetCurrentIrpStackLocation(Irp);
534
535 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY)
536 {
537 //
538 // query property
539 //
540 Status = USBSTOR_HandleQueryProperty(DeviceObject, Irp);
541 }
542 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS)
543 {
544 //
545 // query get scsi address
546 //
547 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_GET_ADDRESS NOT implemented\n");
548 Status = STATUS_NOT_SUPPORTED;
549 }
550 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH)
551 {
552 //
553 // query scsi pass through
554 //
555 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH NOT implemented\n");
556 Status = STATUS_NOT_SUPPORTED;
557 }
558 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
559 {
560 //
561 // query scsi pass through direct
562 //
563 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH_DIRECT NOT implemented\n");
564 Status = STATUS_NOT_SUPPORTED;
565 }
566 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
567 {
568 //
569 // query serial number
570 //
571 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
572 Status = STATUS_NOT_SUPPORTED;
573 }
574 else
575 {
576 //
577 // unsupported
578 //
579 DPRINT("USBSTOR_HandleDeviceControl IoControl %x not supported\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
580 Status = STATUS_NOT_SUPPORTED;
581 }
582
583 return Status;
584 }