Exemple #1
0
/* We won't be needing this... */
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
#if MS_WANT_PARSER
        if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
        Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
        Notify(PSTR("---------\r\n"), 0x80);

        CommandBlockWrapper cbw = CommandBlockWrapper();

        cbw.dCBWSignature = MASS_CBW_SIGNATURE;
        cbw.dCBWTag = ++dCBWTag;
        cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
        cbw.bmCBWFlags = MASS_CMD_DIR_IN,
                cbw.bmCBWLUN = lun;
        cbw.bmCBWCBLength = 10;

        cbw.CBWCB[0] = SCSI_CMD_READ_10;
        cbw.CBWCB[8] = blocks;
        cbw.CBWCB[2] = ((addr >> 24) & 0xff);
        cbw.CBWCB[3] = ((addr >> 16) & 0xff);
        cbw.CBWCB[4] = ((addr >> 8) & 0xff);
        cbw.CBWCB[5] = (addr & 0xff);

        return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
#else
        return MASS_ERR_NOT_IMPLEMENTED;
#endif
}
/**
 * Media control, for spindle motor and media tray or door.
 * This includes CDROM, TAPE and anything with a media loader.
 *
 * @param lun Logical Unit Number
 * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media
 * @return 0 on success
 */
uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
        Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
        Notify(PSTR("-----------------\r\n"), 0x80);
        SetCurLUN(lun);
        uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
        if (bAddress) {
                CommandBlockWrapper cbw;

                cbw.dCBWSignature = MASS_CBW_SIGNATURE;
                cbw.dCBWTag = ++dCBWTag;
                cbw.dCBWDataTransferLength = 0;
                cbw.bmCBWFlags = MASS_CMD_DIR_OUT;
                cbw.bmCBWLUN = lun;
                cbw.bmCBWCBLength = 6;

                for (uint8_t i = 0; i < 16; i++)
                        cbw.CBWCB[i] = 0;

                cbw.CBWCB[0] = SCSI_CMD_START_STOP_UNIT;
                cbw.CBWCB[1] = lun << 5;
                cbw.CBWCB[4] = ctl & 0x03;

                rcode = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
        }
        return rcode;
}
/**
 * For driver use only. Used during Driver Init
 *
 * @param lun Logical Unit Number
 * @param bsize
 * @param buf
 * @return
 */
uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
        Notify(PSTR("\r\nInquiry\r\n"), 0x80);
        Notify(PSTR("---------\r\n"), 0x80);

        CommandBlockWrapper cbw;
        SetCurLUN(lun);
        cbw.dCBWSignature = MASS_CBW_SIGNATURE;
        cbw.dCBWTag = ++dCBWTag;
        cbw.dCBWDataTransferLength = bsize;
        cbw.bmCBWFlags = MASS_CMD_DIR_IN;
        cbw.bmCBWLUN = lun;
        cbw.bmCBWCBLength = 6;

        for (uint8_t i = 0; i < 16; i++)
                cbw.CBWCB[i] = 0;

        cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
        cbw.CBWCB[1] = lun << 5;
        cbw.CBWCB[4] = bsize;

        uint8_t rc = HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
#if 0
        if (!rc) {
                printf("LUN %i `", lun);
                for (int i = 8; i < 36; i++) printf("%c", buf[i]);
                printf("'\r\nQualifier %1.1X ", (buf[0]&0xE0) >> 5);
                printf("Device type %2.2X ", buf[0]&0x1f);
                printf("RMB %1.1X ", buf[1]&0x80 >> 7);
                printf("SSCS% 1.1X ", buf[5]&0x80 >> 7);
                uint8_t sv = buf[2];
                printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
                switch (sv) {
                        case 0:
                                printf("No specific");
                                break;
                                /*
                                case 1:
                                        printf("");
                                        break;
                                 */
                        case 2:
                                printf("ANSI 2");
                                break;
                        case 3:
                                printf("ANSI INCITS 301-1997 (SPC)");
                                break;
                        case 4:
                                printf("ANSI INCITS 351-2001 (SPC-2)");
                                break;
                        case 5:
                                printf("ANSI INCITS 408-2005 (SPC-4)");
                                break;
                        case 6:
                                printf("T10/1731-D (SPC-4)");
                                break;
                        default:
                                printf("unknown");
                }
                printf(" standards.\r\n");
        }
/**
 * Write data to media
 *
 * @param lun Logical Unit Number
 * @param addr LBA address on media to write
 * @param bsize size of a block (we should probably use the cached size)
 * @param blocks how many blocks to write
 * @param buf memory that contains the data to write
 * @return 0 on success
 */
uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
        if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
        if (!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
        Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
        D_PrintHex<uint8_t > (lun, 0x90);
        //printf("LUN=%i LBA=%8.8X BLOCKS=%i SIZE=%i\r\n", lun, addr, blocks, bsize);
        Notify(PSTR("\r\nLBA:\t\t"), 0x90);
        D_PrintHex<uint32_t > (addr, 0x90);
        Notify(PSTR("\r\nblocks:\t\t"), 0x90);
        D_PrintHex<uint8_t > (blocks, 0x90);
        Notify(PSTR("\r\nblock size:\t"), 0x90);
        D_PrintHex<uint16_t > (bsize, 0x90);
        Notify(PSTR("\r\n---------\r\n"), 0x80);
        //MediaCTL(lun, 0x01);
        CommandBlockWrapper cbw;

again:
        cbw.dCBWSignature = MASS_CBW_SIGNATURE;
        cbw.dCBWTag = ++dCBWTag;
        cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
        cbw.bmCBWFlags = MASS_CMD_DIR_OUT;
        cbw.bmCBWLUN = lun;
        cbw.bmCBWCBLength = 10;

        for (uint8_t i = 0; i < 16; i++)
                cbw.CBWCB[i] = 0;

        cbw.CBWCB[0] = SCSI_CMD_WRITE_10;
        cbw.CBWCB[1] = lun << 5;
        cbw.CBWCB[2] = ((addr >> 24) & 0xff);
        cbw.CBWCB[3] = ((addr >> 16) & 0xff);
        cbw.CBWCB[4] = ((addr >> 8) & 0xff);
        cbw.CBWCB[5] = (addr & 0xff);
        cbw.CBWCB[8] = 1;

        SetCurLUN(lun);
        uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0));
        if (er == MASS_ERR_WRITE_STALL) {
                MediaCTL(lun, 1);
                delay(150);
                if (!TestUnitReady(lun)) goto again;
        }
        return er;
}
/**
 * Lock or Unlock the tray or door on device.
 * Caution: Some devices with buggy firmware will lock up.
 *
 * @param lun Logical Unit Number
 * @param lock 1 to lock, 0 to unlock
 * @return
 */
uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
        Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
        Notify(PSTR("---------\r\n"), 0x80);

        CommandBlockWrapper cbw;
        SetCurLUN(lun);
        cbw.dCBWSignature = MASS_CBW_SIGNATURE;
        cbw.dCBWTag = ++dCBWTag;
        cbw.dCBWDataTransferLength = 0;
        cbw.bmCBWFlags = MASS_CMD_DIR_IN;
        cbw.bmCBWLUN = lun;
        cbw.bmCBWCBLength = 6;

        for (uint8_t i = 0; i < 16; i++)
                cbw.CBWCB[i] = 0;

        cbw.CBWCB[0] = SCSI_CMD_PREVENT_REMOVAL;
        cbw.CBWCB[4] = lock;

        return (HandleSCSIError(Transaction(&cbw, 0, NULL, 0)));

}
Exemple #6
0
/**
 * Wrap and execute a SCSI CDB with length of 10
 *
 * @param cdb CDB to execute
 * @param buf_size Size of expected transaction
 * @param buf Buffer
 * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
 * @return
 */
uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
        // promote buf_size to 32bits.
        CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
        //SetCurLUN(cdb->LUN);
        return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
}