Asked by:
Usb Mass Storage transaction
Question
-
Hello guys!
I'm writing Usb LowFilters driver and in AddDevice routine i want send directly to usb mass storage device some scsi command:
(before this I configure usb mass storage device and get pipes handles - pipeIn/pipeOut)
typedef struct _CBW //command block wrapper
{
unsigned int Signature;
unsigned int Tag;
unsigned int dataTransferLength;
unsigned char Flags;
unsigned char Lun;
unsigned char cbdLength; //scsi command block length
unsigned char cbd[16]; //scsi command block data
} CBW, * PCBW;
...
typedef struct _CSW //command status wrapper
{
unsigned int Signature;
unsigned int Tag;
unsigned int dataResidue;
unsigned char Status;
} CSW, * PCSW;
URB urb;
NTSTATUS ntStatus = STATUS_SUCCESS;
PCBW commandBlock;
PCSW statusBlock;
char* buffer;
int dataLen = 36; //INQURY data len
commandBlock = (PCBW *)ExAllocatePool(PagedPool,sizeof(CBW ));
statusBlock = (PCSW *)ExAllocatePool(PagedPool,sizeof(CSW));
buffer = (char*) ExAllocatePool(PagedPool,sizeof(char)*dataLen );
commandBlock->Signature = 0x43425355; // command block signature 'USBC'
commandBlock->Flags = 0x80;//80->data in
commandBlock->Lun = 0; //default Logical Unit Number
RtlZeroMemory(commandBlock->cbd, 16);
//[b]now i try get INQURY iinfo from device[/b]
commandBlock->Tag = - TAG_INQUIRY; // TAG_INQUIRY = 18
commandBlock->dataTransferLength = 36; //INQUIRY_REPLY_LENGTH
commandBlock->Flags = 0x80; //inquiry data will flow In
commandBlock->cbdLength = 6; //inquiry command length
[i]//scsi command block[/i]
commandBlock->cbd[0] = 0x12; //inquiry operation code
commandBlock->cbd[1] = 0; //lun/reserved
commandBlock->cbd[2] = 0; //page code
commandBlock->cbd[3] = 0; //reserved
commandBlock->cbd[4] = 36; //inquiry reply length
commandBlock->cbd[5] = 0; //reserved/flag/link/
//[b]start mass storage transaction - CBW-DATA-CSW[/b]
[i]//scsi command block[/i]
UsbBuildInterruptOrBulkTransferRequest(&urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pipeOut,
block,
NULL,
31,
USBD_TRANSFER_DIRECTION_OUT,
NULL);
ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
[i]//data[/i]
if (NT_SUCCESS(ntStatus))
{
UsbBuildInterruptOrBulkTransferRequest(&urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pipeIn,
buffer,
NULL,
dataLen,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL);
ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
}
[i]//status command block[/i]
statusBlock->Signature = 0x53425355 // 'USBS'
statusBlock->Tag = -TAG_CSW; // TAG_CSW = 37
statusBlock->dataResidue = 0;//residue;
statusBlock->Status = 0;
if (NT_SUCCESS(ntStatus))
{
UsbBuildInterruptOrBulkTransferRequest(&urb,
sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
pipeIn,
packet,
NULL,
13,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL);
ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
}
ASSERT(statusBlock->Status == 0); [b]//FINE!Info recived![/b]
.....
And it work fine ((statusBlock->Status == 0 and buffer include inqury info)! But if I want to get TEST UNIT READY command or REPORT LUNS command it failed...
May be I don't undestan transaction mechanism?
This code for TEST UNIT READY
URB urb;
NTSTATUS ntStatus = STATUS_SUCCESS;
PCBW commandBlock;
PCSW statusBlock;
char* buffer;
commandBlock = (PCBW *)ExAllocatePool(PagedPool,sizeof(CBW ));
statusBlock = (PCSW *)ExAllocatePool(PagedPool,sizeof(CSW));
commandBlock->Signature = 0x43425355; // command block signature 'USBC'
commandBlock->Flags = 0x80;//80->data in
commandBlock->Lun = 0; //Logical Unit Number
RtlZeroMemory(commandBlock->cbd,16);
//[b]now i try send TEST UNIT READY[/b]
commandBlock->Tag = - TAG_UNIT_READY; // TAG_INQUIRY = 25
commandBlock->dataTransferLength = 0; //INQUIRY_REPLY_LENGTH
commandBlock->Flags = 0x80; //inquiry data will flow In
commandBlock->cbdLength = 6; //test unit ready command length
[i]//scsi command block[/i]
commandBlock->cbd[0] = 0x0; //inquiry operation code
commandBlock->cbd[1] = 0; //lun/reserved
commandBlock->cbd[2] = 0; //page code
commandBlock->cbd[3] = 0; //reserved
commandBlock->cbd[4] = 0; //inquiry reply length
commandBlock->cbd[5] = 0; //reserved/flag/link/
//[b]start mass storage transaction - CBW-DATA-CSW[/b]
[i]//scsi command block[/i]
UsbBuildInterruptOrBulkTransferRequest(&urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pipeOut,
block,
NULL,
31,
USBD_TRANSFER_DIRECTION_OUT,
NULL);
ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
[i]//status command block[/i]
statusBlock->Signature = 0x53425355 // 'USBS'
statusBlock->Tag = -TAG_CSW; // TAG_CSW = 37
statusBlock->dataResidue = 0;//residue;
statusBlock->Status = 0;
if (NT_SUCCESS(ntStatus))
{
UsbBuildInterruptOrBulkTransferRequest(&urb,
sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
pipeIn,
packet,
NULL,
13,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL);
ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
}
ASSERT(statusBlock->Status == 0); // [b]status always return 1 for LUN =0 and other LUN (0...256), but sometimes return 0 for LUN = 0 and etc. - it's WRONG [/b]
...
Usb mass storage device 'A' hase 1 LUN - 0,but TEST UNIT READY return 1 for this,usb mass storage device 'B' hase 2 LUNs,but TEST UNIT READY 1 for each lun...
And when I try to read some info from device :
URB urb;
NTSTATUS ntStatus = STATUS_SUCCESS;
PCBW commandBlock;
PCSW statusBlock;
char* buffer;
int dataLen = 128;
commandBlock = (PCBW *)ExAllocatePool(PagedPool,sizeof(CBW ));
statusBlock = (PCSW *)ExAllocatePool(PagedPool,sizeof(CSW));
buffer = (char*) ExAllocatePool(PagedPool,sizeof(char)*dataLen );
commandBlock->Signature = 0x43425355; // command block signature 'USBC'
commandBlock->Flags = 0x80;//80->data in
commandBlock->Lun = 0; //Logical Unit Number
RtlZeroMemory(commandBlock->cbd,16);
//[b]now i try get INQURY iinfo from device[/b]
commandBlock->Tag = - TAG_READ_6; // TAG_INQUIRY = 14
commandBlock->dataTransferLength = dataLen ; //READ LEN
commandBlock->Flags = 0x80; //read data will flow In
commandBlock->cbdLength = 6; //read command length
[i]//scsi command block[/i]
commandBlock->cbd[0] = 0x28; //read 6 operation code
commandBlock->cbd[1] = 0; //lun/reserved
commandBlock->cbd[2] = 0; //page code
commandBlock->cbd[3] = 0; //try read first sector
commandBlock->cbd[4] = dataLen; //readreply length
commandBlock->cbd[5] = 0; //reserved/flag/link/
//[b]start mass storage transaction - CBW-DATA-CSW[/b]
[i]//scsi command block[/i]
UsbBuildInterruptOrBulkTransferRequest(&urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pipeOut,
block,
NULL,
31,
USBD_TRANSFER_DIRECTION_OUT,
NULL);
ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
[i]//read data[/i]
if (NT_SUCCESS(ntStatus))
{
UsbBuildInterruptOrBulkTransferRequest(&urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pipeIn,
buffer,
NULL,
dataLen,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL);
ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
[b][i]//now buffer contain 'USBS' signature in first bytes![/i][/b]
}
[i]//status command block[/i]
statusBlock->Signature = 0x53425355 // 'USBS'
statusBlock->Tag = -TAG_CSW; // TAG_CSW = 37
statusBlock->dataResidue = 0;//residue;
statusBlock->Status = 0;
if (NT_SUCCESS(ntStatus))
{
UsbBuildInterruptOrBulkTransferRequest(&urb,
sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
pipeIn,
packet,
NULL,
13,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL);
ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE); // ***
}
[b][i]//and now i'm don't return from SendAndWaitUrb(***)....deadlock [/i][/b]
.....
In this case (read 6 command) after send command block I'm recived in buffer 'USBS' signature,but WHY?
Could you please guide me on this ?Mrutyunjaya
Wednesday, August 22, 2018 6:56 PM
All replies
-
the documented behavior is that a driver is not allowed to configure the device until the pnp start request is sent to the driver. this means you are relying on undocumented behavior in AddDevice and it may stop working in the future. You should do this work in start device
d -- This posting is provided "AS IS" with no warranties, and confers no rights.
Wednesday, August 22, 2018 8:17 PM