Maestro
Maestro

Reputation: 9518

Send custom commands to Mass Storage device on Microsoft Windows

I have developed a mass-storage device, and I'd a like a PC application to send/receive some custom commands to it. Normally one would create a composite USB device for this (MSC+HID) and send the commands over HID. But is it possible to do this with only the mass-storage class? Some things I thought of:

Can someone think of any other hacks, that would work for this purpose? Or is the only option to create a HID device?

Upvotes: 0

Views: 3567

Answers (1)

liaoo
liaoo

Reputation: 201

The MSC you mentioned is also "USB" Mass Storage Device ?

If yes then you can use SCSI_PATH_THROUGH to communicate with this USB MSC !

Ex. issuing Write command to USB MSC can be achieved by below code snippet:

BOOL LogicalWriteCmd(HANDLE fileHandle,ULONG LBA,ULONG SectorCnt,PVOID DataBuffer)
{
    SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER  sptdwb;
    ULONG returned,length;
    BOOL status;

    ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));    

    length = SectorCnt<<SECTOR_SIZE_SHIFT_BIT;

    sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
    sptdwb.sptd.PathId = 0;
    sptdwb.sptd.TargetId = 0;
    sptdwb.sptd.Lun = 0;
    sptdwb.sptd.CdbLength = CDB10GENERIC_LENGTH;
    sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_OUT;
    sptdwb.sptd.SenseInfoLength = SPT_SENSE_LENGTH;
    sptdwb.sptd.DataTransferLength = length;
    sptdwb.sptd.TimeOutValue = g_ulTimeOut;
    sptdwb.sptd.DataBuffer = DataBuffer;
    sptdwb.sptd.SenseInfoOffset =
       offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
    sptdwb.sptd.Cdb[0] = SCSIOP_WRITE;

    sptdwb.sptd.Cdb[2] = (UCHAR)(LBA>>24);
    sptdwb.sptd.Cdb[3] = (UCHAR)(LBA>>16);
    sptdwb.sptd.Cdb[4] = (UCHAR)(LBA>>8);
    sptdwb.sptd.Cdb[5] = (UCHAR)(LBA);

    sptdwb.sptd.Cdb[7] = SectorCnt>>8;    
    sptdwb.sptd.Cdb[8] = (UCHAR)SectorCnt;

    length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
    status = DeviceIoControl(fileHandle,
                             IOCTL_SCSI_PASS_THROUGH_DIRECT,
                             &sptdwb,
                             length,
                             &sptdwb,
                             length,
                             &returned,
                             FALSE);


    if ((sptdwb.sptd.ScsiStatus == 0) && (status != 0)) {       
        return TRUE;
    }


    return FALSE;

}

And you can create your own vendor/custom commands then send it to USB MSC by above way. But your device should identify them correctly !

Upvotes: 1

Related Questions