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.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 USBSTOR_HandleInternalDeviceControl(
16 IN PDEVICE_OBJECT DeviceObject
,
19 PIO_STACK_LOCATION IoStack
;
20 PSCSI_REQUEST_BLOCK Request
;
21 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
25 // get current stack location
27 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
32 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
40 // get device extension
42 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
47 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
49 switch(Request
->Function
)
51 case SRB_FUNCTION_EXECUTE_SCSI
:
53 DPRINT("SRB_FUNCTION_EXECUTE_SCSI\n");
56 // check if request is valid
58 if (Request
->SrbFlags
& (SRB_FLAGS_DATA_IN
| SRB_FLAGS_DATA_OUT
))
61 // data is transferred with this irp
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
)
70 Status
= STATUS_INVALID_PARAMETER
;
77 // sense buffer request
79 if (Request
->DataTransferLength
||
80 Request
->DataBuffer
||
86 Status
= STATUS_INVALID_PARAMETER
;
94 if (!USBSTOR_QueueAddIrp(PDODeviceExtension
->LowerDeviceObject
, Irp
))
97 // irp was not added to the queue
99 IoStartPacket(PDODeviceExtension
->LowerDeviceObject
, Irp
, &Request
->QueueSortKey
, USBSTOR_CancelIo
);
105 return STATUS_PENDING
;
107 case SRB_FUNCTION_RELEASE_DEVICE
:
109 DPRINT1("SRB_FUNCTION_RELEASE_DEVICE\n");
113 ASSERT(PDODeviceExtension
->Claimed
== TRUE
);
118 PDODeviceExtension
->Claimed
= TRUE
;
119 Status
= STATUS_SUCCESS
;
122 case SRB_FUNCTION_CLAIM_DEVICE
:
124 DPRINT1("SRB_FUNCTION_CLAIM_DEVICE\n");
126 // check if the device has been claimed
128 if (PDODeviceExtension
->Claimed
)
131 // device has already been claimed
133 Status
= STATUS_DEVICE_BUSY
;
134 Request
->SrbStatus
= SRB_STATUS_BUSY
;
141 PDODeviceExtension
->Claimed
= TRUE
;
144 // output device object
146 Request
->DataBuffer
= DeviceObject
;
149 // completed successfully
151 Status
= STATUS_SUCCESS
;
154 case SRB_FUNCTION_RELEASE_QUEUE
:
156 DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
161 USBSTOR_QueueRelease(PDODeviceExtension
->LowerDeviceObject
);
164 // set status success
166 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
167 Status
= STATUS_SUCCESS
;
171 case SRB_FUNCTION_FLUSH
:
172 case SRB_FUNCTION_FLUSH_QUEUE
:
174 DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE\n");
177 // flush all requests
179 USBSTOR_QueueFlushIrps(PDODeviceExtension
->LowerDeviceObject
);
182 // set status success
184 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
185 Status
= STATUS_SUCCESS
;
193 Status
= STATUS_NOT_SUPPORTED
;
194 Request
->SrbStatus
= SRB_STATUS_ERROR
;
201 Irp
->IoStatus
.Status
= Status
;
202 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
207 USBSTOR_GetFieldLength(
212 ULONG LastCharacterPosition
= 0;
215 // scan the field and return last positon which contains a valid character
217 for(Index
= 0; Index
< MaxLength
; Index
++)
219 if (Name
[Index
] != ' ')
222 // trim white spaces from field
224 LastCharacterPosition
= Index
;
229 // convert from zero based index to length
231 return LastCharacterPosition
+ 1;
235 USBSTOR_HandleQueryProperty(
236 IN PDEVICE_OBJECT DeviceObject
,
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
;
244 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
245 PUFI_INQUIRY_RESPONSE InquiryData
;
246 PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
;
249 DPRINT1("USBSTOR_HandleQueryProperty\n");
252 // get current stack location
254 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
259 ASSERT(IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(STORAGE_PROPERTY_QUERY
));
260 ASSERT(Irp
->AssociatedIrp
.SystemBuffer
);
263 // get property query
265 PropertyQuery
= (PSTORAGE_PROPERTY_QUERY
)Irp
->AssociatedIrp
.SystemBuffer
;
268 // check property type
270 if (PropertyQuery
->PropertyId
!= StorageDeviceProperty
&&
271 PropertyQuery
->PropertyId
!= StorageAdapterProperty
)
274 // only device property / adapter property are supported
276 return STATUS_INVALID_PARAMETER_1
;
282 if (PropertyQuery
->QueryType
== PropertyExistsQuery
)
285 // device property / adapter property is supported
287 return STATUS_SUCCESS
;
290 if (PropertyQuery
->QueryType
!= PropertyStandardQuery
)
293 // only standard query and exists query are supported
295 return STATUS_INVALID_PARAMETER_2
;
299 // check if it is a device property
301 if (PropertyQuery
->PropertyId
== StorageDeviceProperty
)
303 DPRINT1("USBSTOR_HandleQueryProperty StorageDeviceProperty OutputBufferLength %lu\n", IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
306 // get device extension
308 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
309 ASSERT(PDODeviceExtension
);
314 InquiryData
= (PUFI_INQUIRY_RESPONSE
)PDODeviceExtension
->InquiryData
;
318 // compute extra parameters length
320 FieldLengthVendor
= USBSTOR_GetFieldLength(InquiryData
->Vendor
, 8);
321 FieldLengthProduct
= USBSTOR_GetFieldLength(InquiryData
->Product
, 16);
322 FieldLengthRevision
= USBSTOR_GetFieldLength(InquiryData
->Revision
, 4);
325 // FIXME handle serial number
329 // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 3 extra null bytes - 1
330 // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
332 TotalLength
= sizeof(STORAGE_DEVICE_DESCRIPTOR
) + FieldLengthVendor
+ FieldLengthProduct
+ FieldLengthRevision
+ 2;
335 // check if output buffer is long enough
337 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< TotalLength
)
342 DescriptorHeader
= (PSTORAGE_DESCRIPTOR_HEADER
)Irp
->AssociatedIrp
.SystemBuffer
;
343 ASSERT(IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= sizeof(STORAGE_DESCRIPTOR_HEADER
));
346 // return required size
348 DescriptorHeader
->Version
= TotalLength
;
349 DescriptorHeader
->Size
= TotalLength
;
351 Irp
->IoStatus
.Information
= sizeof(STORAGE_DESCRIPTOR_HEADER
);
352 return STATUS_SUCCESS
;
356 // get device descriptor
358 DeviceDescriptor
= (PSTORAGE_DEVICE_DESCRIPTOR
)Irp
->AssociatedIrp
.SystemBuffer
;
361 // initialize device descriptor
363 DeviceDescriptor
->Version
= TotalLength
;
364 DeviceDescriptor
->Size
= TotalLength
;
365 DeviceDescriptor
->DeviceType
= InquiryData
->DeviceType
;
366 DeviceDescriptor
->DeviceTypeModifier
= (InquiryData
->RMB
& 0x7F);
367 DeviceDescriptor
->RemovableMedia
= TRUE
;
368 DeviceDescriptor
->CommandQueueing
= FALSE
;
369 DeviceDescriptor
->BusType
= BusTypeUsb
;
370 DeviceDescriptor
->VendorIdOffset
= sizeof(STORAGE_DEVICE_DESCRIPTOR
) - sizeof(UCHAR
);
371 DeviceDescriptor
->ProductIdOffset
= DeviceDescriptor
->VendorIdOffset
+ FieldLengthVendor
+ 1;
372 DeviceDescriptor
->ProductRevisionOffset
= DeviceDescriptor
->ProductIdOffset
+ FieldLengthProduct
+ 1;
373 DeviceDescriptor
->SerialNumberOffset
= 0; //FIXME
374 DeviceDescriptor
->RawPropertiesLength
= FieldLengthVendor
+ FieldLengthProduct
+ FieldLengthRevision
+ 3;
379 Buffer
= (PUCHAR
)((ULONG_PTR
)DeviceDescriptor
+ sizeof(STORAGE_DEVICE_DESCRIPTOR
) - sizeof(UCHAR
));
384 RtlCopyMemory(Buffer
, InquiryData
->Vendor
, FieldLengthVendor
);
385 Buffer
[FieldLengthVendor
] = '\0';
386 Buffer
+= FieldLengthVendor
+ 1;
391 RtlCopyMemory(Buffer
, InquiryData
->Product
, FieldLengthProduct
);
392 Buffer
[FieldLengthProduct
] = '\0';
393 Buffer
+= FieldLengthProduct
+ 1;
398 RtlCopyMemory(Buffer
, InquiryData
->Revision
, FieldLengthRevision
);
399 Buffer
[FieldLengthRevision
] = '\0';
400 Buffer
+= FieldLengthRevision
+ 1;
403 // TODO: copy revision
406 DPRINT("Vendor %s\n", (LPCSTR
)((ULONG_PTR
)DeviceDescriptor
+ DeviceDescriptor
->VendorIdOffset
));
407 DPRINT("Product %s\n", (LPCSTR
)((ULONG_PTR
)DeviceDescriptor
+ DeviceDescriptor
->ProductIdOffset
));
408 DPRINT("Revision %s\n", (LPCSTR
)((ULONG_PTR
)DeviceDescriptor
+ DeviceDescriptor
->ProductRevisionOffset
));
413 Irp
->IoStatus
.Information
= TotalLength
;
414 return STATUS_SUCCESS
;
419 // adapter property query request
421 DPRINT1("USBSTOR_HandleQueryProperty StorageAdapterProperty OutputBufferLength %lu\n", IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
423 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(STORAGE_ADAPTER_DESCRIPTOR
))
428 DescriptorHeader
= (PSTORAGE_DESCRIPTOR_HEADER
)Irp
->AssociatedIrp
.SystemBuffer
;
429 ASSERT(IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= sizeof(STORAGE_DESCRIPTOR_HEADER
));
432 // return required size
434 DescriptorHeader
->Version
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
435 DescriptorHeader
->Size
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
437 Irp
->IoStatus
.Information
= sizeof(STORAGE_DESCRIPTOR_HEADER
);
438 return STATUS_SUCCESS
;
442 // get adapter descriptor, information is returned in the same buffer
444 AdapterDescriptor
= (PSTORAGE_ADAPTER_DESCRIPTOR
)Irp
->AssociatedIrp
.SystemBuffer
;
447 // fill out descriptor
449 AdapterDescriptor
->Version
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
450 AdapterDescriptor
->Size
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
451 AdapterDescriptor
->MaximumTransferLength
= MAXULONG
; //FIXME compute some sane value
452 AdapterDescriptor
->MaximumPhysicalPages
= 25; //FIXME compute some sane value
453 AdapterDescriptor
->AlignmentMask
= 0;
454 AdapterDescriptor
->AdapterUsesPio
= FALSE
;
455 AdapterDescriptor
->AdapterScansDown
= FALSE
;
456 AdapterDescriptor
->CommandQueueing
= FALSE
;
457 AdapterDescriptor
->AcceleratedTransfer
= FALSE
;
458 AdapterDescriptor
->BusType
= BusTypeUsb
;
459 AdapterDescriptor
->BusMajorVersion
= 0x2; //FIXME verify
460 AdapterDescriptor
->BusMinorVersion
= 0x00; //FIXME
463 // store returned length
465 Irp
->IoStatus
.Information
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
470 return STATUS_SUCCESS
;
475 USBSTOR_HandleDeviceControl(
476 IN PDEVICE_OBJECT DeviceObject
,
479 PIO_STACK_LOCATION IoStack
;
483 // get current stack location
485 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
487 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_STORAGE_QUERY_PROPERTY
)
492 Status
= USBSTOR_HandleQueryProperty(DeviceObject
, Irp
);
494 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SCSI_GET_ADDRESS
)
497 // query get scsi address
499 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_GET_ADDRESS NOT implemented\n");
500 Status
= STATUS_NOT_SUPPORTED
;
502 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SCSI_PASS_THROUGH
)
505 // query scsi pass through
507 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH NOT implemented\n");
508 Status
= STATUS_NOT_SUPPORTED
;
510 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SCSI_PASS_THROUGH_DIRECT
)
513 // query scsi pass through direct
515 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH_DIRECT NOT implemented\n");
516 Status
= STATUS_NOT_SUPPORTED
;
518 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER
)
521 // query serial number
523 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
524 Status
= STATUS_NOT_SUPPORTED
;
531 DPRINT("USBSTOR_HandleDeviceControl IoControl %x not supported\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
532 Status
= STATUS_NOT_SUPPORTED
;