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)
9 * 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
19 USBSTOR_GetDeviceType(
20 IN PINQUIRYDATA InquiryData
,
23 if (InquiryData
->DeviceType
== 0)
31 // direct access device
35 switch (InquiryData
->DeviceType
)
39 // sequential device, i.e magnetic tape
54 // optical memory device
59 // medium change device
71 USBSTOR_GetGenericType(
72 IN PINQUIRYDATA InquiryData
,
75 if (InquiryData
->DeviceType
== 0)
83 // direct access device
87 switch (InquiryData
->DeviceType
)
91 // sequential device, i.e magnetic tape
92 return "GenSequential";
106 // optical memory device
111 // medium change device
117 return "UsbstorOther";
130 for (Index
= 0; Index
< MaxLength
; Index
++)
132 if (Name
[Index
] <= ' ' || Name
[Index
] >= 0x7F /* last printable ascii character */ || Name
[Index
] == ',')
134 // convert to underscore
139 // just copy character
140 Buffer
[Index
] = Name
[Index
];
148 USBSTOR_PdoHandleQueryDeviceText(
149 IN PDEVICE_OBJECT DeviceObject
,
152 PIO_STACK_LOCATION IoStack
;
154 static WCHAR DeviceText
[] = L
"USB Mass Storage Device";
156 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
158 if (IoStack
->Parameters
.QueryDeviceText
.DeviceTextType
== DeviceTextDescription
)
160 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextDescription\n");
162 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, sizeof(DeviceText
));
165 Irp
->IoStatus
.Information
= 0;
166 return STATUS_INSUFFICIENT_RESOURCES
;
169 wcscpy(Buffer
, DeviceText
);
171 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
172 return STATUS_SUCCESS
;
176 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextLocationInformation\n");
178 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, sizeof(DeviceText
));
181 Irp
->IoStatus
.Information
= 0;
182 return STATUS_INSUFFICIENT_RESOURCES
;
185 wcscpy(Buffer
, DeviceText
);
187 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
188 return STATUS_SUCCESS
;
194 USBSTOR_PdoHandleQueryDeviceId(
195 IN PDEVICE_OBJECT DeviceObject
,
198 PPDO_DEVICE_EXTENSION DeviceExtension
;
200 CHAR Buffer
[100] = {0};
203 PINQUIRYDATA InquiryData
;
204 ANSI_STRING AnsiString
;
205 UNICODE_STRING DeviceId
;
207 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
208 ASSERT(DeviceExtension
->InquiryData
);
209 InquiryData
= DeviceExtension
->InquiryData
;
211 DeviceType
= USBSTOR_GetDeviceType(InquiryData
, DeviceExtension
->IsFloppy
);
213 // lets create device string
214 Offset
= sprintf(&Buffer
[Offset
], "USBSTOR\\");
215 Offset
+= sprintf(&Buffer
[Offset
], DeviceType
);
216 Offset
+= sprintf(&Buffer
[Offset
], "&Ven_");
217 Offset
+= CopyField(InquiryData
->VendorId
, &Buffer
[Offset
], 8);
218 Offset
+= sprintf(&Buffer
[Offset
], "&Prod_");
219 Offset
+= CopyField(InquiryData
->ProductId
, &Buffer
[Offset
], 16);
220 Offset
+= sprintf(&Buffer
[Offset
], "&Rev_");
221 Offset
+= CopyField(InquiryData
->ProductRevisionLevel
, &Buffer
[Offset
], 4);
223 RtlInitAnsiString(&AnsiString
, (PCSZ
)Buffer
);
225 // allocate DeviceId string
227 DeviceId
.MaximumLength
= (USHORT
)((strlen((PCHAR
)Buffer
) + 1) * sizeof(WCHAR
));
228 DeviceId
.Buffer
= (LPWSTR
)AllocateItem(PagedPool
, DeviceId
.MaximumLength
);
229 if (!DeviceId
.Buffer
)
231 Irp
->IoStatus
.Information
= 0;
232 return STATUS_INSUFFICIENT_RESOURCES
;
235 Status
= RtlAnsiStringToUnicodeString(&DeviceId
, &AnsiString
, FALSE
);
237 if (NT_SUCCESS(Status
))
239 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceId
.Buffer
;
242 DPRINT("DeviceId %wZ Status %x\n", &DeviceId
, Status
);
248 USBSTOR_ConvertToUnicodeString(
250 IN ULONG ResultBufferLength
,
251 IN ULONG ResultBufferOffset
,
252 OUT LPWSTR ResultBuffer
,
253 OUT PULONG NewResultBufferOffset
)
255 UNICODE_STRING DeviceString
;
256 ANSI_STRING AnsiString
;
259 ASSERT(ResultBufferLength
);
260 ASSERT(ResultBufferLength
> ResultBufferOffset
);
262 DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset
, ResultBufferLength
, Buffer
, strlen(Buffer
));
264 // construct destination string
265 DeviceString
.Buffer
= &ResultBuffer
[ResultBufferOffset
];
266 DeviceString
.Length
= 0;
267 DeviceString
.MaximumLength
= (ResultBufferLength
- ResultBufferOffset
) * sizeof(WCHAR
);
269 // initialize source string
270 RtlInitAnsiString(&AnsiString
, Buffer
);
272 Status
= RtlAnsiStringToUnicodeString(&DeviceString
, &AnsiString
, FALSE
);
273 ASSERT(Status
== STATUS_SUCCESS
);
275 // subtract consumed bytes
276 ResultBufferLength
-= (DeviceString
.Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
277 ResultBufferOffset
+= (DeviceString
.Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
279 *NewResultBufferOffset
= ResultBufferOffset
;
283 USBSTOR_PdoHandleQueryHardwareId(
284 IN PDEVICE_OBJECT DeviceObject
,
287 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
288 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
289 LPCSTR GenericType
, DeviceType
;
291 CHAR Id1
[50], Id2
[50], Id3
[50], Id4
[50], Id5
[50], Id6
[50];
292 ULONG Id1Length
, Id2Length
, Id3Length
, Id4Length
, Id5Length
,Id6Length
;
293 ULONG Offset
, TotalLength
, Length
;
294 PINQUIRYDATA InquiryData
;
296 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
297 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
298 ASSERT(FDODeviceExtension
->DeviceDescriptor
);
299 InquiryData
= PDODeviceExtension
->InquiryData
;
301 DeviceType
= USBSTOR_GetDeviceType(InquiryData
, PDODeviceExtension
->IsFloppy
);
302 GenericType
= USBSTOR_GetGenericType(InquiryData
, PDODeviceExtension
->IsFloppy
);
307 // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(4)
308 RtlZeroMemory(Id1
, sizeof(Id1
));
310 Offset
= sprintf(&Id1
[Offset
], "USBSTOR\\");
311 Offset
+= sprintf(&Id1
[Offset
], DeviceType
);
312 Offset
+= CopyField(InquiryData
->VendorId
, &Id1
[Offset
], 8);
313 Offset
+= CopyField(InquiryData
->ProductId
, &Id1
[Offset
], 16);
314 Offset
+= CopyField(InquiryData
->ProductRevisionLevel
, &Id1
[Offset
], 4);
315 Id1Length
= strlen(Id1
) + 1;
316 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1
);
319 // USBSTOR\SCSIType_VendorId(8)_ProductId(16)
320 RtlZeroMemory(Id2
, sizeof(Id2
));
322 Offset
= sprintf(&Id2
[Offset
], "USBSTOR\\");
323 Offset
+= sprintf(&Id2
[Offset
], DeviceType
);
324 Offset
+= CopyField(InquiryData
->VendorId
, &Id2
[Offset
], 8);
325 Offset
+= CopyField(InquiryData
->ProductId
, &Id2
[Offset
], 16);
326 Id2Length
= strlen(Id2
) + 1;
327 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2
);
330 // USBSTOR\SCSIType_VendorId(8)
331 RtlZeroMemory(Id3
, sizeof(Id3
));
333 Offset
= sprintf(&Id3
[Offset
], "USBSTOR\\");
334 Offset
+= sprintf(&Id3
[Offset
], DeviceType
);
335 Offset
+= CopyField(InquiryData
->VendorId
, &Id3
[Offset
], 8);
336 Id3Length
= strlen(Id3
) + 1;
337 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3
);
340 // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(1)
341 RtlZeroMemory(Id4
, sizeof(Id4
));
343 Offset
= sprintf(&Id4
[Offset
], "USBSTOR\\");
344 Offset
+= sprintf(&Id4
[Offset
], DeviceType
);
345 Offset
+= CopyField(InquiryData
->VendorId
, &Id4
[Offset
], 8);
346 Offset
+= CopyField(InquiryData
->ProductId
, &Id4
[Offset
], 16);
347 Offset
+= CopyField(InquiryData
->ProductRevisionLevel
, &Id4
[Offset
], 1);
348 Id4Length
= strlen(Id4
) + 1;
349 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4
);
353 RtlZeroMemory(Id5
, sizeof(Id5
));
355 Offset
= sprintf(&Id5
[Offset
], "USBSTOR\\");
356 Offset
+= sprintf(&Id5
[Offset
], GenericType
);
357 Id5Length
= strlen(Id5
) + 1;
358 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5
);
362 RtlZeroMemory(Id6
, sizeof(Id6
));
364 Offset
= sprintf(&Id6
[Offset
], GenericType
);
365 Id6Length
= strlen(Id6
) + 1;
366 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6
);
368 TotalLength
= Id1Length
+ Id2Length
+ Id3Length
+ Id4Length
+ Id5Length
+ Id6Length
+ 1;
370 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, TotalLength
* sizeof(WCHAR
));
373 Irp
->IoStatus
.Information
= 0;
374 return STATUS_INSUFFICIENT_RESOURCES
;
379 Length
= TotalLength
;
381 USBSTOR_ConvertToUnicodeString(Id1
, Length
, Offset
, Buffer
, &Offset
);
382 USBSTOR_ConvertToUnicodeString(Id2
, Length
, Offset
, Buffer
, &Offset
);
383 USBSTOR_ConvertToUnicodeString(Id3
, Length
, Offset
, Buffer
, &Offset
);
384 USBSTOR_ConvertToUnicodeString(Id4
, Length
, Offset
, Buffer
, &Offset
);
385 USBSTOR_ConvertToUnicodeString(Id5
, Length
, Offset
, Buffer
, &Offset
);
386 USBSTOR_ConvertToUnicodeString(Id6
, Length
, Offset
, Buffer
, &Offset
);
388 ASSERT(Offset
+ 1 == Length
);
390 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
391 return STATUS_SUCCESS
;
395 USBSTOR_PdoHandleQueryCompatibleId(
396 IN PDEVICE_OBJECT DeviceObject
,
399 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
400 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
401 CHAR Buffer
[100] = {0};
402 ULONG Length
, Offset
;
406 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
407 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
408 ASSERT(FDODeviceExtension
->DeviceDescriptor
);
409 DeviceType
= USBSTOR_GetDeviceType(PDODeviceExtension
->InquiryData
, PDODeviceExtension
->IsFloppy
);
411 // format instance id
412 Length
= sprintf(Buffer
, "USBSTOR\\%s", DeviceType
) + 1;
413 Length
+= sprintf(&Buffer
[Length
], "USBSTOR\\%s", "RAW") + 2;
415 InstanceId
= (LPWSTR
)AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
418 Irp
->IoStatus
.Information
= 0;
419 return STATUS_INSUFFICIENT_RESOURCES
;
422 USBSTOR_ConvertToUnicodeString(Buffer
, Length
, 0, InstanceId
, &Offset
);
423 USBSTOR_ConvertToUnicodeString(&Buffer
[Offset
], Length
, Offset
, InstanceId
, &Offset
);
425 DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId
);
427 Irp
->IoStatus
.Information
= (ULONG_PTR
)InstanceId
;
428 return STATUS_SUCCESS
;
432 USBSTOR_PdoHandleQueryInstanceId(
433 IN PDEVICE_OBJECT DeviceObject
,
436 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
437 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
442 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
443 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
445 // format instance id
446 if (FDODeviceExtension
->SerialNumber
)
448 // using serial number from device
449 swprintf(Buffer
, L
"%s&%c", FDODeviceExtension
->SerialNumber
->bString
, PDODeviceExtension
->LUN
);
453 // use instance count and LUN
454 swprintf(Buffer
, L
"%04lu&%c", FDODeviceExtension
->InstanceCount
, PDODeviceExtension
->LUN
);
457 Length
= wcslen(Buffer
) + 1;
459 InstanceId
= (LPWSTR
)AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
462 Irp
->IoStatus
.Information
= 0;
463 return STATUS_INSUFFICIENT_RESOURCES
;
466 wcscpy(InstanceId
, Buffer
);
468 DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId
);
470 Irp
->IoStatus
.Information
= (ULONG_PTR
)InstanceId
;
471 return STATUS_SUCCESS
;
475 USBSTOR_PdoHandleDeviceRelations(
476 IN PDEVICE_OBJECT DeviceObject
,
479 PDEVICE_RELATIONS DeviceRelations
;
480 PIO_STACK_LOCATION IoStack
;
482 DPRINT("USBSTOR_PdoHandleDeviceRelations\n");
484 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
486 // check if relation type is BusRelations
487 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
489 // PDO handles only target device relation
490 return Irp
->IoStatus
.Status
;
493 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
494 if (!DeviceRelations
)
496 return STATUS_INSUFFICIENT_RESOURCES
;
499 // initialize device relations
500 DeviceRelations
->Count
= 1;
501 DeviceRelations
->Objects
[0] = DeviceObject
;
502 ObReferenceObject(DeviceObject
);
504 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
505 return STATUS_SUCCESS
;
509 USBSTOR_PdoHandlePnp(
510 IN PDEVICE_OBJECT DeviceObject
,
513 PIO_STACK_LOCATION IoStack
;
514 PPDO_DEVICE_EXTENSION DeviceExtension
;
516 PDEVICE_CAPABILITIES Caps
;
519 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
520 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
521 ASSERT(DeviceExtension
->Common
.IsFDO
== FALSE
);
523 switch(IoStack
->MinorFunction
)
525 case IRP_MN_QUERY_DEVICE_RELATIONS
:
527 Status
= USBSTOR_PdoHandleDeviceRelations(DeviceObject
, Irp
);
530 case IRP_MN_QUERY_DEVICE_TEXT
:
532 Status
= USBSTOR_PdoHandleQueryDeviceText(DeviceObject
, Irp
);
535 case IRP_MN_QUERY_ID
:
537 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
539 Status
= USBSTOR_PdoHandleQueryDeviceId(DeviceObject
, Irp
);
542 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
544 Status
= USBSTOR_PdoHandleQueryHardwareId(DeviceObject
, Irp
);
547 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
549 Status
= USBSTOR_PdoHandleQueryInstanceId(DeviceObject
, Irp
);
552 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryCompatibleIDs
)
554 Status
= USBSTOR_PdoHandleQueryCompatibleId(DeviceObject
, Irp
);
558 DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack
->Parameters
.QueryId
.IdType
);
559 Status
= STATUS_NOT_SUPPORTED
;
560 Irp
->IoStatus
.Information
= 0;
563 case IRP_MN_REMOVE_DEVICE
:
565 DPRINT("IRP_MN_REMOVE_DEVICE\n");
567 if(*DeviceExtension
->PDODeviceObject
!= NULL
)
569 *DeviceExtension
->PDODeviceObject
= NULL
;
574 // device object already marked for deletion
578 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
579 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
583 IoDeleteDevice(DeviceObject
);
585 return STATUS_SUCCESS
;
587 case IRP_MN_QUERY_CAPABILITIES
:
589 // just forward irp to lower device
590 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
591 ASSERT(Status
== STATUS_SUCCESS
);
593 if (NT_SUCCESS(Status
))
595 // check if no unique id
596 Caps
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
597 Caps
->UniqueID
= FALSE
; // no unique id is supported
598 Caps
->Removable
= TRUE
; //FIXME
602 case IRP_MN_QUERY_REMOVE_DEVICE
:
603 case IRP_MN_QUERY_STOP_DEVICE
:
607 // if we're not claimed it's ok
609 if (DeviceExtension
->Claimed
)
614 Status
= STATUS_UNSUCCESSFUL
;
615 DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack
->MinorFunction
);
618 Status
= STATUS_SUCCESS
;
621 case IRP_MN_START_DEVICE
:
624 Status
= STATUS_SUCCESS
;
627 case IRP_MN_SURPRISE_REMOVAL
:
629 Status
= STATUS_SUCCESS
;
635 Status
= Irp
->IoStatus
.Status
;
639 if (Status
!= STATUS_PENDING
)
641 Irp
->IoStatus
.Status
= Status
;
642 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
650 USBSTOR_SyncCompletionRoutine(
651 IN PDEVICE_OBJECT DeviceObject
,
655 KeSetEvent((PKEVENT
)Ctx
, IO_NO_INCREMENT
, FALSE
);
656 return STATUS_MORE_PROCESSING_REQUIRED
;
660 * @name USBSTOR_SendInternalCdb
662 * Issues an internal SCSI request to device.
663 * The request is sent in a synchronous way.
667 USBSTOR_SendInternalCdb(
668 IN PDEVICE_OBJECT PdoDevice
,
671 IN ULONG TimeOutValue
,
672 OUT PVOID OutDataBuffer
,
673 OUT PULONG OutDataTransferLength
)
675 PSCSI_REQUEST_BLOCK Srb
;
676 PSENSE_DATA SenseBuffer
;
677 PIO_STACK_LOCATION IoStack
;
682 NTSTATUS Status
= STATUS_INSUFFICIENT_RESOURCES
;
685 DPRINT("USBSTOR_SendInternalCdb SCSIOP %x\n", Cdb
->CDB6GENERIC
.OperationCode
);
687 Srb
= ExAllocatePoolWithTag(NonPagedPool
,
688 sizeof(SCSI_REQUEST_BLOCK
),
693 SenseBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
699 Mdl
= IoAllocateMdl(OutDataBuffer
,
700 *OutDataTransferLength
,
707 ExFreePoolWithTag(SenseBuffer
, USB_STOR_TAG
);
708 ExFreePoolWithTag(Srb
, USB_STOR_TAG
);
712 MmBuildMdlForNonPagedPool(Mdl
);
714 // make 3 attempts - the device may be in STALL state after the first one
717 Irp
= IoAllocateIrp(PdoDevice
->StackSize
, FALSE
);
724 IoStack
= IoGetNextIrpStackLocation(Irp
);
725 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
726 IoStack
->Parameters
.Scsi
.Srb
= Srb
;
728 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
730 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
731 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
732 Srb
->CdbLength
= CdbLength
;
733 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
734 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_NO_QUEUE_FREEZE
;
735 Srb
->DataTransferLength
= *OutDataTransferLength
;
736 Srb
->TimeOutValue
= TimeOutValue
;
737 Srb
->DataBuffer
= OutDataBuffer
;
738 Srb
->SenseInfoBuffer
= SenseBuffer
;
740 RtlCopyMemory(Srb
->Cdb
, Cdb
, CdbLength
);
742 Irp
->MdlAddress
= Mdl
;
744 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
746 IoSetCompletionRoutine(Irp
,
747 USBSTOR_SyncCompletionRoutine
,
753 if (IoCallDriver(PdoDevice
, Irp
) == STATUS_PENDING
)
755 KeWaitForSingleObject(&Event
,
762 SrbStatus
= SRB_STATUS(Srb
->SrbStatus
);
767 if (SrbStatus
== SRB_STATUS_SUCCESS
||
768 SrbStatus
== SRB_STATUS_DATA_OVERRUN
)
770 Status
= STATUS_SUCCESS
;
771 *OutDataTransferLength
= Srb
->DataTransferLength
;
775 Status
= STATUS_UNSUCCESSFUL
;
785 ExFreePoolWithTag(SenseBuffer
, USB_STOR_TAG
);
788 ExFreePoolWithTag(Srb
, USB_STOR_TAG
);
795 * @name USBSTOR_FillInquiryData
797 * Sends a SCSI Inquiry request and fills in the PDODeviceExtension->InquiryData field with a result.
801 USBSTOR_FillInquiryData(
802 IN PDEVICE_OBJECT PDODeviceObject
)
804 NTSTATUS Status
= STATUS_INSUFFICIENT_RESOURCES
;
805 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
807 ULONG DataTransferLength
= INQUIRYDATABUFFERSIZE
;
808 PINQUIRYDATA InquiryData
;
810 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
811 InquiryData
= ExAllocatePoolWithTag(NonPagedPool
, INQUIRYDATABUFFERSIZE
, USB_STOR_TAG
);
815 DPRINT1("USBSTOR_FillInquiryData failed with %x\n", Status
);
819 RtlZeroMemory(&Cdb
, sizeof(Cdb
));
820 Cdb
.CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
821 Cdb
.CDB6INQUIRY
.AllocationLength
= INQUIRYDATABUFFERSIZE
;
823 Status
= USBSTOR_SendInternalCdb(PDODeviceObject
, &Cdb
, CDB6GENERIC_LENGTH
, 20, InquiryData
, &DataTransferLength
);
825 if (!NT_SUCCESS(Status
))
827 DPRINT1("USBSTOR_FillInquiryData failed with %x\n", Status
);
828 ExFreePoolWithTag(InquiryData
, USB_STOR_TAG
);
832 DPRINT("DeviceType %x\n", InquiryData
->DeviceType
);
833 DPRINT("DeviceTypeModifier %x\n", InquiryData
->DeviceTypeModifier
);
834 DPRINT("RemovableMedia %x\n", InquiryData
->RemovableMedia
);
835 DPRINT("Version %x\n", InquiryData
->Versions
);
836 DPRINT("Format %x\n", InquiryData
->ResponseDataFormat
);
837 DPRINT("Length %x\n", InquiryData
->AdditionalLength
);
838 DPRINT("Reserved %p\n", InquiryData
->Reserved
);
839 DPRINT("VendorId %c%c%c%c%c%c%c%c\n", InquiryData
->VendorId
[0], InquiryData
->VendorId
[1], InquiryData
->VendorId
[2], InquiryData
->VendorId
[3], InquiryData
->VendorId
[4], InquiryData
->VendorId
[5], InquiryData
->VendorId
[6], InquiryData
->VendorId
[7]);
840 DPRINT("ProductId %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", InquiryData
->ProductId
[0], InquiryData
->ProductId
[1], InquiryData
->ProductId
[2], InquiryData
->ProductId
[3],
841 InquiryData
->ProductId
[4], InquiryData
->ProductId
[5], InquiryData
->ProductId
[6], InquiryData
->ProductId
[7],
842 InquiryData
->ProductId
[8], InquiryData
->ProductId
[9], InquiryData
->ProductId
[10], InquiryData
->ProductId
[11],
843 InquiryData
->ProductId
[12], InquiryData
->ProductId
[13], InquiryData
->ProductId
[14], InquiryData
->ProductId
[15]);
845 DPRINT("Revision %c%c%c%c\n", InquiryData
->ProductRevisionLevel
[0], InquiryData
->ProductRevisionLevel
[1], InquiryData
->ProductRevisionLevel
[2], InquiryData
->ProductRevisionLevel
[3]);
847 PDODeviceExtension
->InquiryData
= InquiryData
;
853 IN PDEVICE_OBJECT DeviceObject
,
858 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
859 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
861 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
863 // create child device object
864 Status
= IoCreateDevice(DeviceObject
->DriverObject
, sizeof(PDO_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_MASS_STORAGE
, FILE_AUTOGENERATED_DEVICE_NAME
| FILE_DEVICE_SECURE_OPEN
, FALSE
, &PDO
);
865 if (!NT_SUCCESS(Status
))
867 DPRINT1("Failed to create PDO, status %x\n", Status
);
871 // patch the stack size
872 PDO
->StackSize
= DeviceObject
->StackSize
;
874 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDO
->DeviceExtension
;
876 // initialize device extension
877 RtlZeroMemory(PDODeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
878 PDODeviceExtension
->Common
.IsFDO
= FALSE
;
879 PDODeviceExtension
->LowerDeviceObject
= DeviceObject
;
880 PDODeviceExtension
->PDODeviceObject
= &FDODeviceExtension
->ChildPDO
[LUN
];
881 PDODeviceExtension
->Self
= PDO
;
882 PDODeviceExtension
->LUN
= LUN
;
884 PDO
->Flags
|= DO_DIRECT_IO
;
886 // device is initialized
887 PDO
->Flags
&= ~DO_DEVICE_INITIALIZING
;
889 // output device object
890 FDODeviceExtension
->ChildPDO
[LUN
] = PDO
;
892 // send inquiry command by irp
893 Status
= USBSTOR_FillInquiryData(PDO
);
895 if (!NT_SUCCESS(Status
))
900 if (PDODeviceExtension
->InquiryData
->DeviceType
== DIRECT_ACCESS_DEVICE
)
902 PDODeviceExtension
->IsFloppy
= FALSE
; // TODO: implement the actual check
906 // we work only with DIRECT_ACCESS_DEVICE for now
907 return STATUS_NOT_SUPPORTED
;