Library to use Arduino USB host shield on mbed

Dependents:   USBHOST_PS5

ArduinoのUSB Host Shield 2.0をmbedで使えるようにしたライブラリです。
大体のコードがArduinoからそのまま移植可能です。

Arduino UNOやMega用のホストシールド以外にもミニサイズのホストシールドでも使用可能です https://os.mbed.com/media/uploads/kotakku/dffgfddswa.png

シールドについて

3.3VのI/O用にシールドの改造が必要になりますがネット上に記事がたくさんあるのでそちらを参考にしてください

接続例

https://os.mbed.com/media/uploads/kotakku/esgsvfvhjrekldkcjxvb.png

使い方

Arduinoのコードと違うのはUSBのインスタンスの宣言部分のみです。
ピンを自分で指定できるようにしたので使いやすくなりました。

仕様

  • Arduinoのmillis関数、micros関数の移植のために内部でTimerクラスを使用しています。

main.cpp

#include "mbed.h"
#include <PS3BT.h>
#include <usbhub.h>

Serial pc(USBTX, USBRX, 115200);

//Nucleo f303k8用
USB Usb(A6, A5, A4, A3, A2); // mosi, miso, sclk, ssel, intr
BTD Btd(&Usb);
PS3BT PS3(&Btd);

int main()
{
    bool printAngle = false;

    if (Usb.Init() == -1)
    {
        pc.printf("\r\nOSC did not start");
        while (1); // Halt
    }
    pc.printf("\r\nPS3 USB Library Started");

    while (1)
    {
        Usb.Task();
        
        if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
            if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117)
            {
                pc.printf("\r\nLeftHatX: %d", PS3.getAnalogHat(LeftHatX));
                pc.printf("\tLeftHatY: %d", PS3.getAnalogHat(LeftHatY));
                if (PS3.PS3Connected)
                { // The Navigation controller only have one joystick
                    pc.printf("\tRightHatX: %d", PS3.getAnalogHat(RightHatX));
                    pc.printf("\tRightHatY: %d", PS3.getAnalogHat(RightHatY));
                }
            }
            // Analog button values can be read from almost all buttons
            if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2))
            {
                pc.printf("\r\nL2: %d", PS3.getAnalogButton(L2));
                if (!PS3.PS3NavigationConnected)
                {
                    pc.printf("\tR2: %d", PS3.getAnalogButton(R2));
                }
            }
            if (PS3.getButtonClick(PS))
            {
                PS3.disconnect();
                pc.printf("\r\nPS");
            }
    
            if (PS3.getButtonClick(TRIANGLE))
                pc.printf("\r\nTriangle");
            if (PS3.getButtonClick(CIRCLE))
                pc.printf("\r\nCircle");
            if (PS3.getButtonClick(CROSS))
                pc.printf("\r\nCross");
            if (PS3.getButtonClick(SQUARE))
                pc.printf("\r\nSquare");
    
            if (PS3.getButtonClick(UP))
            {
                pc.printf("\r\nUp");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED4);
            }
            if (PS3.getButtonClick(RIGHT))
            {
                pc.printf("\r\nRight");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED1);
            }
            if (PS3.getButtonClick(DOWN))
            {
                pc.printf("\r\nDown");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED2);
            }
            if (PS3.getButtonClick(LEFT))
            {
                pc.printf("\r\nLeft");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED3);
            }
    
            if (PS3.getButtonClick(L1))
                pc.printf("\r\nL1");
            if (PS3.getButtonClick(L3))
                pc.printf("\r\nL3");
            if (PS3.getButtonClick(R1))
                pc.printf("\r\nR1");
            if (PS3.getButtonClick(R3))
                pc.printf("\r\nR3");
    
            if (PS3.getButtonClick(SELECT))
            {
                pc.printf("\r\nSelect - ");
                PS3.printStatusString();
            }
            if (PS3.getButtonClick(START))
            {
                pc.printf("\r\nStart");
                printAngle = !printAngle;
            }
            if (printAngle)
            {
                pc.printf("\r\nPitch: %.3lf", PS3.getAngle(Pitch));
                pc.printf("\tRoll: %.3lf", PS3.getAngle(Roll));
            }
        }
        else
        {
            pc.printf("not connect\n");
        }
    }
}
Committer:
robo_ichinoseki_a
Date:
Sat May 02 05:56:48 2020 +0000
Revision:
1:da31140f2a1c
Parent:
0:b1ce54272580
update

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kotakku 0:b1ce54272580 1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
kotakku 0:b1ce54272580 2
kotakku 0:b1ce54272580 3 This program is free software; you can redistribute it and/or modify
kotakku 0:b1ce54272580 4 it under the terms of the GNU General Public License as published by
kotakku 0:b1ce54272580 5 the Free Software Foundation; either version 2 of the License, or
kotakku 0:b1ce54272580 6 (at your option) any later version.
kotakku 0:b1ce54272580 7
kotakku 0:b1ce54272580 8 This program is distributed in the hope that it will be useful,
kotakku 0:b1ce54272580 9 but WITHOUT ANY WARRANTY; without even the implied warranty of
kotakku 0:b1ce54272580 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kotakku 0:b1ce54272580 11 GNU General Public License for more details.
kotakku 0:b1ce54272580 12
kotakku 0:b1ce54272580 13 You should have received a copy of the GNU General Public License
kotakku 0:b1ce54272580 14 along with this program; if not, write to the Free Software
kotakku 0:b1ce54272580 15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kotakku 0:b1ce54272580 16
kotakku 0:b1ce54272580 17 Contact information
kotakku 0:b1ce54272580 18 -------------------
kotakku 0:b1ce54272580 19
kotakku 0:b1ce54272580 20 Circuits At Home, LTD
kotakku 0:b1ce54272580 21 Web : http://www.circuitsathome.com
kotakku 0:b1ce54272580 22 e-mail : support@circuitsathome.com
kotakku 0:b1ce54272580 23 */
kotakku 0:b1ce54272580 24
kotakku 0:b1ce54272580 25 #include "masstorage.h"
kotakku 0:b1ce54272580 26
kotakku 0:b1ce54272580 27 const uint8_t BulkOnly::epDataInIndex = 1;
kotakku 0:b1ce54272580 28 const uint8_t BulkOnly::epDataOutIndex = 2;
kotakku 0:b1ce54272580 29 const uint8_t BulkOnly::epInterruptInIndex = 3;
kotakku 0:b1ce54272580 30
kotakku 0:b1ce54272580 31 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 32
kotakku 0:b1ce54272580 33 // Interface code
kotakku 0:b1ce54272580 34
kotakku 0:b1ce54272580 35 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 36
kotakku 0:b1ce54272580 37 /**
kotakku 0:b1ce54272580 38 * Get the capacity of the media
kotakku 0:b1ce54272580 39 *
kotakku 0:b1ce54272580 40 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 41 * @return media capacity
kotakku 0:b1ce54272580 42 */
kotakku 0:b1ce54272580 43 uint32_t BulkOnly::GetCapacity(uint8_t lun) {
kotakku 0:b1ce54272580 44 if(LUNOk[lun])
kotakku 0:b1ce54272580 45 return CurrentCapacity[lun];
kotakku 0:b1ce54272580 46 return 0LU;
kotakku 0:b1ce54272580 47 }
kotakku 0:b1ce54272580 48
kotakku 0:b1ce54272580 49 /**
kotakku 0:b1ce54272580 50 * Get the sector (block) size used on the media
kotakku 0:b1ce54272580 51 *
kotakku 0:b1ce54272580 52 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 53 * @return media sector size
kotakku 0:b1ce54272580 54 */
kotakku 0:b1ce54272580 55 uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
kotakku 0:b1ce54272580 56 if(LUNOk[lun])
kotakku 0:b1ce54272580 57 return CurrentSectorSize[lun];
kotakku 0:b1ce54272580 58 return 0U;
kotakku 0:b1ce54272580 59 }
kotakku 0:b1ce54272580 60
kotakku 0:b1ce54272580 61 /**
kotakku 0:b1ce54272580 62 * Test if LUN is ready for use
kotakku 0:b1ce54272580 63 *
kotakku 0:b1ce54272580 64 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 65 * @return true if LUN is ready for use
kotakku 0:b1ce54272580 66 */
kotakku 0:b1ce54272580 67 bool BulkOnly::LUNIsGood(uint8_t lun) {
kotakku 0:b1ce54272580 68 return LUNOk[lun];
kotakku 0:b1ce54272580 69 }
kotakku 0:b1ce54272580 70
kotakku 0:b1ce54272580 71 /**
kotakku 0:b1ce54272580 72 * Test if LUN is write protected
kotakku 0:b1ce54272580 73 *
kotakku 0:b1ce54272580 74 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 75 * @return cached status of write protect switch
kotakku 0:b1ce54272580 76 */
kotakku 0:b1ce54272580 77 bool BulkOnly::WriteProtected(uint8_t lun) {
kotakku 0:b1ce54272580 78 return WriteOk[lun];
kotakku 0:b1ce54272580 79 }
kotakku 0:b1ce54272580 80
kotakku 0:b1ce54272580 81 /**
kotakku 0:b1ce54272580 82 * Wrap and execute a SCSI CDB with length of 6
kotakku 0:b1ce54272580 83 *
kotakku 0:b1ce54272580 84 * @param cdb CDB to execute
kotakku 0:b1ce54272580 85 * @param buf_size Size of expected transaction
kotakku 0:b1ce54272580 86 * @param buf Buffer
kotakku 0:b1ce54272580 87 * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
kotakku 0:b1ce54272580 88 * @return
kotakku 0:b1ce54272580 89 */
kotakku 0:b1ce54272580 90 uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
kotakku 0:b1ce54272580 91 // promote buf_size to 32bits.
kotakku 0:b1ce54272580 92 CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
kotakku 0:b1ce54272580 93 //SetCurLUN(cdb->LUN);
kotakku 0:b1ce54272580 94 return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
kotakku 0:b1ce54272580 95 }
kotakku 0:b1ce54272580 96
kotakku 0:b1ce54272580 97 /**
kotakku 0:b1ce54272580 98 * Wrap and execute a SCSI CDB with length of 10
kotakku 0:b1ce54272580 99 *
kotakku 0:b1ce54272580 100 * @param cdb CDB to execute
kotakku 0:b1ce54272580 101 * @param buf_size Size of expected transaction
kotakku 0:b1ce54272580 102 * @param buf Buffer
kotakku 0:b1ce54272580 103 * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
kotakku 0:b1ce54272580 104 * @return
kotakku 0:b1ce54272580 105 */
kotakku 0:b1ce54272580 106 uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
kotakku 0:b1ce54272580 107 // promote buf_size to 32bits.
kotakku 0:b1ce54272580 108 CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
kotakku 0:b1ce54272580 109 //SetCurLUN(cdb->LUN);
kotakku 0:b1ce54272580 110 return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
kotakku 0:b1ce54272580 111 }
kotakku 0:b1ce54272580 112
kotakku 0:b1ce54272580 113 /**
kotakku 0:b1ce54272580 114 * Lock or Unlock the tray or door on device.
kotakku 0:b1ce54272580 115 * Caution: Some devices with buggy firmware will lock up.
kotakku 0:b1ce54272580 116 *
kotakku 0:b1ce54272580 117 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 118 * @param lock 1 to lock, 0 to unlock
kotakku 0:b1ce54272580 119 * @return
kotakku 0:b1ce54272580 120 */
kotakku 0:b1ce54272580 121 uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
kotakku 0:b1ce54272580 122 Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
kotakku 0:b1ce54272580 123 Notify(PSTR("---------\r\n"), 0x80);
kotakku 0:b1ce54272580 124
kotakku 0:b1ce54272580 125 CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock);
kotakku 0:b1ce54272580 126 return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN);
kotakku 0:b1ce54272580 127 }
kotakku 0:b1ce54272580 128
kotakku 0:b1ce54272580 129 /**
kotakku 0:b1ce54272580 130 * Media control, for spindle motor and media tray or door.
kotakku 0:b1ce54272580 131 * This includes CDROM, TAPE and anything with a media loader.
kotakku 0:b1ce54272580 132 *
kotakku 0:b1ce54272580 133 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 134 * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media
kotakku 0:b1ce54272580 135 * @return 0 on success
kotakku 0:b1ce54272580 136 */
kotakku 0:b1ce54272580 137 uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
kotakku 0:b1ce54272580 138 Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
kotakku 0:b1ce54272580 139 Notify(PSTR("-----------------\r\n"), 0x80);
kotakku 0:b1ce54272580 140
kotakku 0:b1ce54272580 141 uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
kotakku 0:b1ce54272580 142 if(bAddress) {
kotakku 0:b1ce54272580 143 CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
kotakku 0:b1ce54272580 144 rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);
kotakku 0:b1ce54272580 145 } else {
kotakku 0:b1ce54272580 146 SetCurLUN(lun);
kotakku 0:b1ce54272580 147 }
kotakku 0:b1ce54272580 148 return rcode;
kotakku 0:b1ce54272580 149 }
kotakku 0:b1ce54272580 150
kotakku 0:b1ce54272580 151 /**
kotakku 0:b1ce54272580 152 * Read data from media
kotakku 0:b1ce54272580 153 *
kotakku 0:b1ce54272580 154 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 155 * @param addr LBA address on media to read
kotakku 0:b1ce54272580 156 * @param bsize size of a block (we should probably use the cached size)
kotakku 0:b1ce54272580 157 * @param blocks how many blocks to read
kotakku 0:b1ce54272580 158 * @param buf memory that is able to hold the requested data
kotakku 0:b1ce54272580 159 * @return 0 on success
kotakku 0:b1ce54272580 160 */
kotakku 0:b1ce54272580 161 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
kotakku 0:b1ce54272580 162 if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
kotakku 0:b1ce54272580 163 Notify(PSTR("\r\nRead LUN:\t"), 0x80);
kotakku 0:b1ce54272580 164 D_PrintHex<uint8_t > (lun, 0x90);
kotakku 0:b1ce54272580 165 Notify(PSTR("\r\nLBA:\t\t"), 0x90);
kotakku 0:b1ce54272580 166 D_PrintHex<uint32_t > (addr, 0x90);
kotakku 0:b1ce54272580 167 Notify(PSTR("\r\nblocks:\t\t"), 0x90);
kotakku 0:b1ce54272580 168 D_PrintHex<uint8_t > (blocks, 0x90);
kotakku 0:b1ce54272580 169 Notify(PSTR("\r\nblock size:\t"), 0x90);
kotakku 0:b1ce54272580 170 D_PrintHex<uint16_t > (bsize, 0x90);
kotakku 0:b1ce54272580 171 Notify(PSTR("\r\n---------\r\n"), 0x80);
kotakku 0:b1ce54272580 172 CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr);
kotakku 0:b1ce54272580 173
kotakku 0:b1ce54272580 174 again:
kotakku 0:b1ce54272580 175 uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN);
kotakku 0:b1ce54272580 176
kotakku 0:b1ce54272580 177 if(er == MASS_ERR_STALL) {
kotakku 0:b1ce54272580 178 MediaCTL(lun, 1);
kotakku 0:b1ce54272580 179 delay(150);
kotakku 0:b1ce54272580 180 if(!TestUnitReady(lun)) goto again;
kotakku 0:b1ce54272580 181 }
kotakku 0:b1ce54272580 182 return er;
kotakku 0:b1ce54272580 183 }
kotakku 0:b1ce54272580 184
kotakku 0:b1ce54272580 185 /**
kotakku 0:b1ce54272580 186 * Write data to media
kotakku 0:b1ce54272580 187 *
kotakku 0:b1ce54272580 188 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 189 * @param addr LBA address on media to write
kotakku 0:b1ce54272580 190 * @param bsize size of a block (we should probably use the cached size)
kotakku 0:b1ce54272580 191 * @param blocks how many blocks to write
kotakku 0:b1ce54272580 192 * @param buf memory that contains the data to write
kotakku 0:b1ce54272580 193 * @return 0 on success
kotakku 0:b1ce54272580 194 */
kotakku 0:b1ce54272580 195 uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
kotakku 0:b1ce54272580 196 if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
kotakku 0:b1ce54272580 197 if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
kotakku 0:b1ce54272580 198 Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
kotakku 0:b1ce54272580 199 D_PrintHex<uint8_t > (lun, 0x90);
kotakku 0:b1ce54272580 200 Notify(PSTR("\r\nLBA:\t\t"), 0x90);
kotakku 0:b1ce54272580 201 D_PrintHex<uint32_t > (addr, 0x90);
kotakku 0:b1ce54272580 202 Notify(PSTR("\r\nblocks:\t\t"), 0x90);
kotakku 0:b1ce54272580 203 D_PrintHex<uint8_t > (blocks, 0x90);
kotakku 0:b1ce54272580 204 Notify(PSTR("\r\nblock size:\t"), 0x90);
kotakku 0:b1ce54272580 205 D_PrintHex<uint16_t > (bsize, 0x90);
kotakku 0:b1ce54272580 206 Notify(PSTR("\r\n---------\r\n"), 0x80);
kotakku 0:b1ce54272580 207 CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr);
kotakku 0:b1ce54272580 208
kotakku 0:b1ce54272580 209 again:
kotakku 0:b1ce54272580 210 uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT);
kotakku 0:b1ce54272580 211
kotakku 0:b1ce54272580 212 if(er == MASS_ERR_WRITE_STALL) {
kotakku 0:b1ce54272580 213 MediaCTL(lun, 1);
kotakku 0:b1ce54272580 214 delay(150);
kotakku 0:b1ce54272580 215 if(!TestUnitReady(lun)) goto again;
kotakku 0:b1ce54272580 216 }
kotakku 0:b1ce54272580 217 return er;
kotakku 0:b1ce54272580 218 }
kotakku 0:b1ce54272580 219
kotakku 0:b1ce54272580 220 // End of user functions, the remaining code below is driver internals.
kotakku 0:b1ce54272580 221 // Only developer serviceable parts below!
kotakku 0:b1ce54272580 222
kotakku 0:b1ce54272580 223 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 224
kotakku 0:b1ce54272580 225 // Main driver code
kotakku 0:b1ce54272580 226
kotakku 0:b1ce54272580 227 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 228
kotakku 0:b1ce54272580 229 BulkOnly::BulkOnly(USB *p) :
kotakku 0:b1ce54272580 230 pUsb(p),
kotakku 0:b1ce54272580 231 bAddress(0),
kotakku 0:b1ce54272580 232 bIface(0),
kotakku 0:b1ce54272580 233 bNumEP(1),
kotakku 0:b1ce54272580 234 qNextPollTime(0),
kotakku 0:b1ce54272580 235 bPollEnable(false),
kotakku 0:b1ce54272580 236 //dCBWTag(0),
kotakku 0:b1ce54272580 237 bLastUsbError(0) {
kotakku 0:b1ce54272580 238 ClearAllEP();
kotakku 0:b1ce54272580 239 dCBWTag = 0;
kotakku 0:b1ce54272580 240 if(pUsb)
kotakku 0:b1ce54272580 241 pUsb->RegisterDeviceClass(this);
kotakku 0:b1ce54272580 242 }
kotakku 0:b1ce54272580 243
kotakku 0:b1ce54272580 244 /**
kotakku 0:b1ce54272580 245 * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success
kotakku 0:b1ce54272580 246 * We need to standardize either the rcode, or change the API to return values
kotakku 0:b1ce54272580 247 * so a signal that additional actions are required can be produced.
kotakku 0:b1ce54272580 248 * Some of these codes do exist already.
kotakku 0:b1ce54272580 249 *
kotakku 0:b1ce54272580 250 * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance.
kotakku 0:b1ce54272580 251 * Doing so would save some program memory when using multiple drivers.
kotakku 0:b1ce54272580 252 *
kotakku 0:b1ce54272580 253 * @param parent USB address of parent
kotakku 0:b1ce54272580 254 * @param port address of port on parent
kotakku 0:b1ce54272580 255 * @param lowspeed true if device is low speed
kotakku 0:b1ce54272580 256 * @return
kotakku 0:b1ce54272580 257 */
kotakku 0:b1ce54272580 258 uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
kotakku 0:b1ce54272580 259
kotakku 0:b1ce54272580 260 const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
kotakku 0:b1ce54272580 261
kotakku 0:b1ce54272580 262 uint8_t buf[constBufSize];
kotakku 0:b1ce54272580 263 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
kotakku 0:b1ce54272580 264 uint8_t rcode;
kotakku 0:b1ce54272580 265 UsbDevice *p = NULL;
kotakku 0:b1ce54272580 266 EpInfo *oldep_ptr = NULL;
kotakku 0:b1ce54272580 267 USBTRACE("MS ConfigureDevice\r\n");
kotakku 0:b1ce54272580 268 ClearAllEP();
kotakku 0:b1ce54272580 269 AddressPool &addrPool = pUsb->GetAddressPool();
kotakku 0:b1ce54272580 270
kotakku 0:b1ce54272580 271
kotakku 0:b1ce54272580 272 if(bAddress)
kotakku 0:b1ce54272580 273 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
kotakku 0:b1ce54272580 274
kotakku 0:b1ce54272580 275 // <TECHNICAL>
kotakku 0:b1ce54272580 276 // Get pointer to pseudo device with address 0 assigned
kotakku 0:b1ce54272580 277 p = addrPool.GetUsbDevicePtr(0);
kotakku 0:b1ce54272580 278 if(!p) {
kotakku 0:b1ce54272580 279 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 280 }
kotakku 0:b1ce54272580 281
kotakku 0:b1ce54272580 282 if(!p->epinfo) {
kotakku 0:b1ce54272580 283 USBTRACE("epinfo\r\n");
kotakku 0:b1ce54272580 284 return USB_ERROR_EPINFO_IS_NULL;
kotakku 0:b1ce54272580 285 }
kotakku 0:b1ce54272580 286
kotakku 0:b1ce54272580 287 // Save old pointer to EP_RECORD of address 0
kotakku 0:b1ce54272580 288 oldep_ptr = p->epinfo;
kotakku 0:b1ce54272580 289
kotakku 0:b1ce54272580 290 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
kotakku 0:b1ce54272580 291 p->epinfo = epInfo;
kotakku 0:b1ce54272580 292
kotakku 0:b1ce54272580 293 p->lowspeed = lowspeed;
kotakku 0:b1ce54272580 294 // Get device descriptor
kotakku 0:b1ce54272580 295 rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
kotakku 0:b1ce54272580 296
kotakku 0:b1ce54272580 297 // Restore p->epinfo
kotakku 0:b1ce54272580 298 p->epinfo = oldep_ptr;
kotakku 0:b1ce54272580 299
kotakku 0:b1ce54272580 300 if(rcode) {
kotakku 0:b1ce54272580 301 goto FailGetDevDescr;
kotakku 0:b1ce54272580 302 }
kotakku 0:b1ce54272580 303 // Allocate new address according to device class
kotakku 0:b1ce54272580 304 bAddress = addrPool.AllocAddress(parent, false, port);
kotakku 0:b1ce54272580 305
kotakku 0:b1ce54272580 306 if(!bAddress)
kotakku 0:b1ce54272580 307 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
kotakku 0:b1ce54272580 308
kotakku 0:b1ce54272580 309 // Extract Max Packet Size from the device descriptor
kotakku 0:b1ce54272580 310 epInfo[0].maxPktSize = udd->bMaxPacketSize0;
kotakku 0:b1ce54272580 311 // Steal and abuse from epInfo structure to save on memory.
kotakku 0:b1ce54272580 312 epInfo[1].epAddr = udd->bNumConfigurations;
kotakku 0:b1ce54272580 313 // </TECHNICAL>
kotakku 0:b1ce54272580 314 return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
kotakku 0:b1ce54272580 315
kotakku 0:b1ce54272580 316 FailGetDevDescr:
kotakku 0:b1ce54272580 317 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 318 NotifyFailGetDevDescr(rcode);
kotakku 0:b1ce54272580 319 #endif
kotakku 0:b1ce54272580 320 rcode = USB_ERROR_FailGetDevDescr;
kotakku 0:b1ce54272580 321
kotakku 0:b1ce54272580 322 Release();
kotakku 0:b1ce54272580 323 return rcode;
kotakku 0:b1ce54272580 324 };
kotakku 0:b1ce54272580 325
kotakku 0:b1ce54272580 326 /**
kotakku 0:b1ce54272580 327 *
kotakku 0:b1ce54272580 328 * @param parent (not used)
kotakku 0:b1ce54272580 329 * @param port (not used)
kotakku 0:b1ce54272580 330 * @param lowspeed true if device is low speed
kotakku 0:b1ce54272580 331 * @return 0 for success
kotakku 0:b1ce54272580 332 */
kotakku 0:b1ce54272580 333 uint8_t BulkOnly::Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed) {
kotakku 0:b1ce54272580 334 uint8_t rcode;
kotakku 0:b1ce54272580 335 uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
kotakku 0:b1ce54272580 336 epInfo[1].epAddr = 0;
kotakku 0:b1ce54272580 337 USBTRACE("MS Init\r\n");
kotakku 0:b1ce54272580 338
kotakku 0:b1ce54272580 339 AddressPool &addrPool = pUsb->GetAddressPool();
kotakku 0:b1ce54272580 340 UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
kotakku 0:b1ce54272580 341
kotakku 0:b1ce54272580 342 if(!p)
kotakku 0:b1ce54272580 343 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 344
kotakku 0:b1ce54272580 345 // Assign new address to the device
kotakku 0:b1ce54272580 346 delay(2000);
kotakku 0:b1ce54272580 347 rcode = pUsb->setAddr(0, 0, bAddress);
kotakku 0:b1ce54272580 348
kotakku 0:b1ce54272580 349 if(rcode) {
kotakku 0:b1ce54272580 350 p->lowspeed = false;
kotakku 0:b1ce54272580 351 addrPool.FreeAddress(bAddress);
kotakku 0:b1ce54272580 352 bAddress = 0;
kotakku 0:b1ce54272580 353 USBTRACE2("setAddr:", rcode);
kotakku 0:b1ce54272580 354 return rcode;
kotakku 0:b1ce54272580 355 }
kotakku 0:b1ce54272580 356
kotakku 0:b1ce54272580 357 USBTRACE2("Addr:", bAddress);
kotakku 0:b1ce54272580 358
kotakku 0:b1ce54272580 359 p->lowspeed = false;
kotakku 0:b1ce54272580 360
kotakku 0:b1ce54272580 361 p = addrPool.GetUsbDevicePtr(bAddress);
kotakku 0:b1ce54272580 362
kotakku 0:b1ce54272580 363 if(!p)
kotakku 0:b1ce54272580 364 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 365
kotakku 0:b1ce54272580 366 p->lowspeed = lowspeed;
kotakku 0:b1ce54272580 367
kotakku 0:b1ce54272580 368 // Assign epInfo to epinfo pointer
kotakku 0:b1ce54272580 369 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
kotakku 0:b1ce54272580 370
kotakku 0:b1ce54272580 371 if(rcode)
kotakku 0:b1ce54272580 372 goto FailSetDevTblEntry;
kotakku 0:b1ce54272580 373
kotakku 0:b1ce54272580 374 USBTRACE2("NC:", num_of_conf);
kotakku 0:b1ce54272580 375
kotakku 0:b1ce54272580 376 for(uint8_t i = 0; i < num_of_conf; i++) {
kotakku 0:b1ce54272580 377 ConfigDescParser< USB_CLASS_MASS_STORAGE,
kotakku 0:b1ce54272580 378 MASS_SUBCLASS_SCSI,
kotakku 0:b1ce54272580 379 MASS_PROTO_BBB,
kotakku 0:b1ce54272580 380 CP_MASK_COMPARE_CLASS |
kotakku 0:b1ce54272580 381 CP_MASK_COMPARE_SUBCLASS |
kotakku 0:b1ce54272580 382 CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);
kotakku 0:b1ce54272580 383
kotakku 0:b1ce54272580 384 rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
kotakku 0:b1ce54272580 385
kotakku 0:b1ce54272580 386 if(rcode)
kotakku 0:b1ce54272580 387 goto FailGetConfDescr;
kotakku 0:b1ce54272580 388
kotakku 0:b1ce54272580 389 if(bNumEP > 1)
kotakku 0:b1ce54272580 390 break;
kotakku 0:b1ce54272580 391 }
kotakku 0:b1ce54272580 392
kotakku 0:b1ce54272580 393 if(bNumEP < 3)
kotakku 0:b1ce54272580 394 return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
kotakku 0:b1ce54272580 395
kotakku 0:b1ce54272580 396 // Assign epInfo to epinfo pointer
kotakku 0:b1ce54272580 397 pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
kotakku 0:b1ce54272580 398
kotakku 0:b1ce54272580 399 USBTRACE2("Conf:", bConfNum);
kotakku 0:b1ce54272580 400
kotakku 0:b1ce54272580 401 // Set Configuration Value
kotakku 0:b1ce54272580 402 rcode = pUsb->setConf(bAddress, 0, bConfNum);
kotakku 0:b1ce54272580 403
kotakku 0:b1ce54272580 404 if(rcode)
kotakku 0:b1ce54272580 405 goto FailSetConfDescr;
kotakku 0:b1ce54272580 406
kotakku 0:b1ce54272580 407 //Linux does a 1sec delay after this.
kotakku 0:b1ce54272580 408 delay(1000);
kotakku 0:b1ce54272580 409
kotakku 0:b1ce54272580 410 rcode = GetMaxLUN(&bMaxLUN);
kotakku 0:b1ce54272580 411 if(rcode)
kotakku 0:b1ce54272580 412 goto FailGetMaxLUN;
kotakku 0:b1ce54272580 413
kotakku 0:b1ce54272580 414 if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
kotakku 0:b1ce54272580 415 ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
kotakku 0:b1ce54272580 416
kotakku 0:b1ce54272580 417 delay(1000); // Delay a bit for slow firmware.
kotakku 0:b1ce54272580 418
kotakku 0:b1ce54272580 419 for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
kotakku 0:b1ce54272580 420 InquiryResponse response;
kotakku 0:b1ce54272580 421 rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
kotakku 0:b1ce54272580 422 if(rcode) {
kotakku 0:b1ce54272580 423 ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
kotakku 0:b1ce54272580 424 } else {
kotakku 0:b1ce54272580 425 #if 0
kotakku 0:b1ce54272580 426 printf("LUN %i `", lun);
kotakku 0:b1ce54272580 427 uint8_t *buf = response.VendorID;
kotakku 0:b1ce54272580 428 for(int i = 0; i < 28; i++) printf("%c", buf[i]);
kotakku 0:b1ce54272580 429 printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
kotakku 0:b1ce54272580 430 printf("Device type %2.2X ", response.DeviceType);
kotakku 0:b1ce54272580 431 printf("RMB %1.1X ", response.Removable);
kotakku 0:b1ce54272580 432 printf("SSCS %1.1X ", response.SCCS);
kotakku 0:b1ce54272580 433 uint8_t sv = response.Version;
kotakku 0:b1ce54272580 434 printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
kotakku 0:b1ce54272580 435 switch(sv) {
kotakku 0:b1ce54272580 436 case 0:
kotakku 0:b1ce54272580 437 printf("No specific");
kotakku 0:b1ce54272580 438 break;
kotakku 0:b1ce54272580 439 case 1:
kotakku 0:b1ce54272580 440 printf("ANSI X3.131-1986 (ANSI 1)");
kotakku 0:b1ce54272580 441 break;
kotakku 0:b1ce54272580 442 case 2:
kotakku 0:b1ce54272580 443 printf("ANSI X3.131-1994 (ANSI 2)");
kotakku 0:b1ce54272580 444 break;
kotakku 0:b1ce54272580 445 case 3:
kotakku 0:b1ce54272580 446 printf("ANSI INCITS 301-1997 (SPC)");
kotakku 0:b1ce54272580 447 break;
kotakku 0:b1ce54272580 448 case 4:
kotakku 0:b1ce54272580 449 printf("ANSI INCITS 351-2001 (SPC-2)");
kotakku 0:b1ce54272580 450 break;
kotakku 0:b1ce54272580 451 case 5:
kotakku 0:b1ce54272580 452 printf("ANSI INCITS 408-2005 (SPC-4)");
kotakku 0:b1ce54272580 453 break;
kotakku 0:b1ce54272580 454 case 6:
kotakku 0:b1ce54272580 455 printf("T10/1731-D (SPC-4)");
kotakku 0:b1ce54272580 456 break;
kotakku 0:b1ce54272580 457 default:
kotakku 0:b1ce54272580 458 printf("unknown");
kotakku 0:b1ce54272580 459 }
kotakku 0:b1ce54272580 460 printf(" standards.\r\n");
kotakku 0:b1ce54272580 461 #endif
kotakku 0:b1ce54272580 462 uint8_t tries = 0xf0;
kotakku 0:b1ce54272580 463 while((rcode = TestUnitReady(lun))) {
kotakku 0:b1ce54272580 464 if(rcode == 0x08) break; // break on no media, this is OK to do.
kotakku 0:b1ce54272580 465 // try to lock media and spin up
kotakku 0:b1ce54272580 466 if(tries < 14) {
kotakku 0:b1ce54272580 467 LockMedia(lun, 1);
kotakku 0:b1ce54272580 468 MediaCTL(lun, 1); // I actually have a USB stick that needs this!
kotakku 0:b1ce54272580 469 } else delay(2 * (tries + 1));
kotakku 0:b1ce54272580 470 tries++;
kotakku 0:b1ce54272580 471 if(!tries) break;
kotakku 0:b1ce54272580 472 }
kotakku 0:b1ce54272580 473 if(!rcode) {
kotakku 0:b1ce54272580 474 delay(1000);
kotakku 0:b1ce54272580 475 LUNOk[lun] = CheckLUN(lun);
kotakku 0:b1ce54272580 476 if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
kotakku 0:b1ce54272580 477 }
kotakku 0:b1ce54272580 478 }
kotakku 0:b1ce54272580 479 }
kotakku 0:b1ce54272580 480
kotakku 0:b1ce54272580 481
kotakku 0:b1ce54272580 482 CheckMedia();
kotakku 0:b1ce54272580 483
kotakku 0:b1ce54272580 484 rcode = OnInit();
kotakku 0:b1ce54272580 485
kotakku 0:b1ce54272580 486 if(rcode)
kotakku 0:b1ce54272580 487 goto FailOnInit;
kotakku 0:b1ce54272580 488
kotakku 0:b1ce54272580 489 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 490 USBTRACE("MS configured\r\n\r\n");
kotakku 0:b1ce54272580 491 #endif
kotakku 0:b1ce54272580 492
kotakku 0:b1ce54272580 493 bPollEnable = true;
kotakku 0:b1ce54272580 494
kotakku 0:b1ce54272580 495 //USBTRACE("Poll enabled\r\n");
kotakku 0:b1ce54272580 496 return 0;
kotakku 0:b1ce54272580 497
kotakku 0:b1ce54272580 498 FailSetConfDescr:
kotakku 0:b1ce54272580 499 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 500 NotifyFailSetConfDescr();
kotakku 0:b1ce54272580 501 goto Fail;
kotakku 0:b1ce54272580 502 #endif
kotakku 0:b1ce54272580 503
kotakku 0:b1ce54272580 504 FailOnInit:
kotakku 0:b1ce54272580 505 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 506 USBTRACE("OnInit:");
kotakku 0:b1ce54272580 507 goto Fail;
kotakku 0:b1ce54272580 508 #endif
kotakku 0:b1ce54272580 509
kotakku 0:b1ce54272580 510 FailGetMaxLUN:
kotakku 0:b1ce54272580 511 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 512 USBTRACE("GetMaxLUN:");
kotakku 0:b1ce54272580 513 goto Fail;
kotakku 0:b1ce54272580 514 #endif
kotakku 0:b1ce54272580 515
kotakku 0:b1ce54272580 516 //#ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 517 //FailInvalidSectorSize:
kotakku 0:b1ce54272580 518 // USBTRACE("Sector Size is NOT VALID: ");
kotakku 0:b1ce54272580 519 // goto Fail;
kotakku 0:b1ce54272580 520 //#endif
kotakku 0:b1ce54272580 521
kotakku 0:b1ce54272580 522 FailSetDevTblEntry:
kotakku 0:b1ce54272580 523 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 524 NotifyFailSetDevTblEntry();
kotakku 0:b1ce54272580 525 goto Fail;
kotakku 0:b1ce54272580 526 #endif
kotakku 0:b1ce54272580 527
kotakku 0:b1ce54272580 528 FailGetConfDescr:
kotakku 0:b1ce54272580 529 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 530 NotifyFailGetConfDescr();
kotakku 0:b1ce54272580 531 #endif
kotakku 0:b1ce54272580 532
kotakku 0:b1ce54272580 533 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 534 Fail:
kotakku 0:b1ce54272580 535 NotifyFail(rcode);
kotakku 0:b1ce54272580 536 #endif
kotakku 0:b1ce54272580 537 Release();
kotakku 0:b1ce54272580 538 return rcode;
kotakku 0:b1ce54272580 539 }
kotakku 0:b1ce54272580 540
kotakku 0:b1ce54272580 541 /**
kotakku 0:b1ce54272580 542 * For driver use only.
kotakku 0:b1ce54272580 543 *
kotakku 0:b1ce54272580 544 * @param conf
kotakku 0:b1ce54272580 545 * @param iface
kotakku 0:b1ce54272580 546 * @param alt
kotakku 0:b1ce54272580 547 * @param proto
kotakku 0:b1ce54272580 548 * @param pep
kotakku 0:b1ce54272580 549 */
kotakku 0:b1ce54272580 550 void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR * pep) {
kotakku 0:b1ce54272580 551 ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
kotakku 0:b1ce54272580 552 ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
kotakku 0:b1ce54272580 553 ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
kotakku 0:b1ce54272580 554
kotakku 0:b1ce54272580 555 bConfNum = conf;
kotakku 0:b1ce54272580 556
kotakku 0:b1ce54272580 557 uint8_t index;
kotakku 0:b1ce54272580 558
kotakku 0:b1ce54272580 559 #if 1
kotakku 0:b1ce54272580 560 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) {
kotakku 0:b1ce54272580 561 index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
kotakku 0:b1ce54272580 562 // Fill in the endpoint info structure
kotakku 0:b1ce54272580 563 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
kotakku 0:b1ce54272580 564 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
kotakku 0:b1ce54272580 565 epInfo[index].bmSndToggle = 0;
kotakku 0:b1ce54272580 566 epInfo[index].bmRcvToggle = 0;
kotakku 0:b1ce54272580 567
kotakku 0:b1ce54272580 568 bNumEP++;
kotakku 0:b1ce54272580 569
kotakku 0:b1ce54272580 570 PrintEndpointDescriptor(pep);
kotakku 0:b1ce54272580 571
kotakku 0:b1ce54272580 572 }
kotakku 0:b1ce54272580 573 #else
kotakku 0:b1ce54272580 574 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80)
kotakku 0:b1ce54272580 575 index = epInterruptInIndex;
kotakku 0:b1ce54272580 576 else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK)
kotakku 0:b1ce54272580 577 index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
kotakku 0:b1ce54272580 578 else
kotakku 0:b1ce54272580 579 return;
kotakku 0:b1ce54272580 580
kotakku 0:b1ce54272580 581 // Fill in the endpoint info structure
kotakku 0:b1ce54272580 582 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
kotakku 0:b1ce54272580 583 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
kotakku 0:b1ce54272580 584 epInfo[index].bmSndToggle = 0;
kotakku 0:b1ce54272580 585 epInfo[index].bmRcvToggle = 0;
kotakku 0:b1ce54272580 586
kotakku 0:b1ce54272580 587 bNumEP++;
kotakku 0:b1ce54272580 588
kotakku 0:b1ce54272580 589 PrintEndpointDescriptor(pep);
kotakku 0:b1ce54272580 590 #endif
kotakku 0:b1ce54272580 591 }
kotakku 0:b1ce54272580 592
kotakku 0:b1ce54272580 593 /**
kotakku 0:b1ce54272580 594 * For driver use only.
kotakku 0:b1ce54272580 595 *
kotakku 0:b1ce54272580 596 * @return
kotakku 0:b1ce54272580 597 */
kotakku 0:b1ce54272580 598 uint8_t BulkOnly::Release() {
kotakku 0:b1ce54272580 599 ClearAllEP();
kotakku 0:b1ce54272580 600 pUsb->GetAddressPool().FreeAddress(bAddress);
kotakku 0:b1ce54272580 601 return 0;
kotakku 0:b1ce54272580 602 }
kotakku 0:b1ce54272580 603
kotakku 0:b1ce54272580 604 /**
kotakku 0:b1ce54272580 605 * For driver use only.
kotakku 0:b1ce54272580 606 *
kotakku 0:b1ce54272580 607 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 608 * @return true if LUN is ready for use.
kotakku 0:b1ce54272580 609 */
kotakku 0:b1ce54272580 610 bool BulkOnly::CheckLUN(uint8_t lun) {
kotakku 0:b1ce54272580 611 uint8_t rcode;
kotakku 0:b1ce54272580 612 Capacity capacity;
kotakku 0:b1ce54272580 613 for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
kotakku 0:b1ce54272580 614
kotakku 0:b1ce54272580 615 rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
kotakku 0:b1ce54272580 616 if(rcode) {
kotakku 0:b1ce54272580 617 //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
kotakku 0:b1ce54272580 618 return false;
kotakku 0:b1ce54272580 619 }
kotakku 0:b1ce54272580 620 ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
kotakku 0:b1ce54272580 621 for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
kotakku 0:b1ce54272580 622 D_PrintHex<uint8_t > (capacity.data[i], 0x80);
kotakku 0:b1ce54272580 623 Notify(PSTR("\r\n\r\n"), 0x80);
kotakku 0:b1ce54272580 624 // Only 512/1024/2048/4096 are valid values!
kotakku 0:b1ce54272580 625 uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
kotakku 0:b1ce54272580 626 if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
kotakku 0:b1ce54272580 627 return false;
kotakku 0:b1ce54272580 628 }
kotakku 0:b1ce54272580 629 // Store capacity information.
kotakku 0:b1ce54272580 630 CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
kotakku 0:b1ce54272580 631
kotakku 0:b1ce54272580 632 CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
kotakku 0:b1ce54272580 633 if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) {
kotakku 0:b1ce54272580 634 // Buggy firmware will report 0xffffffff or 0 for no media
kotakku 0:b1ce54272580 635 if(CurrentCapacity[lun])
kotakku 0:b1ce54272580 636 ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
kotakku 0:b1ce54272580 637 return false;
kotakku 0:b1ce54272580 638 }
kotakku 0:b1ce54272580 639 delay(20);
kotakku 0:b1ce54272580 640 Page3F(lun);
kotakku 0:b1ce54272580 641 if(!TestUnitReady(lun)) return true;
kotakku 0:b1ce54272580 642 return false;
kotakku 0:b1ce54272580 643 }
kotakku 0:b1ce54272580 644
kotakku 0:b1ce54272580 645 /**
kotakku 0:b1ce54272580 646 * For driver use only.
kotakku 0:b1ce54272580 647 *
kotakku 0:b1ce54272580 648 * Scan for media change on all LUNs
kotakku 0:b1ce54272580 649 */
kotakku 0:b1ce54272580 650 void BulkOnly::CheckMedia() {
kotakku 0:b1ce54272580 651 for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
kotakku 0:b1ce54272580 652 if(TestUnitReady(lun)) {
kotakku 0:b1ce54272580 653 LUNOk[lun] = false;
kotakku 0:b1ce54272580 654 continue;
kotakku 0:b1ce54272580 655 }
kotakku 0:b1ce54272580 656 if(!LUNOk[lun])
kotakku 0:b1ce54272580 657 LUNOk[lun] = CheckLUN(lun);
kotakku 0:b1ce54272580 658 }
kotakku 0:b1ce54272580 659 #if 0
kotakku 0:b1ce54272580 660 printf("}}}}}}}}}}}}}}}}STATUS ");
kotakku 0:b1ce54272580 661 for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
kotakku 0:b1ce54272580 662 if(LUNOk[lun])
kotakku 0:b1ce54272580 663 printf("#");
kotakku 0:b1ce54272580 664 else printf(".");
kotakku 0:b1ce54272580 665 }
kotakku 0:b1ce54272580 666 printf("\r\n");
kotakku 0:b1ce54272580 667 #endif
kotakku 0:b1ce54272580 668 qNextPollTime = (uint32_t)millis() + 2000;
kotakku 0:b1ce54272580 669 }
kotakku 0:b1ce54272580 670
kotakku 0:b1ce54272580 671 /**
kotakku 0:b1ce54272580 672 * For driver use only.
kotakku 0:b1ce54272580 673 *
kotakku 0:b1ce54272580 674 * @return
kotakku 0:b1ce54272580 675 */
kotakku 0:b1ce54272580 676 uint8_t BulkOnly::Poll() {
kotakku 0:b1ce54272580 677 //uint8_t rcode = 0;
kotakku 0:b1ce54272580 678
kotakku 0:b1ce54272580 679 if(!bPollEnable)
kotakku 0:b1ce54272580 680 return 0;
kotakku 0:b1ce54272580 681
kotakku 0:b1ce54272580 682 if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) {
kotakku 0:b1ce54272580 683 CheckMedia();
kotakku 0:b1ce54272580 684 }
kotakku 0:b1ce54272580 685 //rcode = 0;
kotakku 0:b1ce54272580 686
kotakku 0:b1ce54272580 687 return 0;
kotakku 0:b1ce54272580 688 }
kotakku 0:b1ce54272580 689
kotakku 0:b1ce54272580 690 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 691
kotakku 0:b1ce54272580 692
kotakku 0:b1ce54272580 693 // SCSI code
kotakku 0:b1ce54272580 694
kotakku 0:b1ce54272580 695
kotakku 0:b1ce54272580 696 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 697
kotakku 0:b1ce54272580 698 /**
kotakku 0:b1ce54272580 699 * For driver use only.
kotakku 0:b1ce54272580 700 *
kotakku 0:b1ce54272580 701 * @param plun
kotakku 0:b1ce54272580 702 * @return
kotakku 0:b1ce54272580 703 */
kotakku 0:b1ce54272580 704 uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
kotakku 0:b1ce54272580 705 uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
kotakku 0:b1ce54272580 706
kotakku 0:b1ce54272580 707 if(ret == hrSTALL)
kotakku 0:b1ce54272580 708 *plun = 0;
kotakku 0:b1ce54272580 709
kotakku 0:b1ce54272580 710 return 0;
kotakku 0:b1ce54272580 711 }
kotakku 0:b1ce54272580 712
kotakku 0:b1ce54272580 713 /**
kotakku 0:b1ce54272580 714 * For driver use only. Used during Driver Init
kotakku 0:b1ce54272580 715 *
kotakku 0:b1ce54272580 716 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 717 * @param bsize
kotakku 0:b1ce54272580 718 * @param buf
kotakku 0:b1ce54272580 719 * @return
kotakku 0:b1ce54272580 720 */
kotakku 0:b1ce54272580 721 uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
kotakku 0:b1ce54272580 722 Notify(PSTR("\r\nInquiry\r\n"), 0x80);
kotakku 0:b1ce54272580 723 Notify(PSTR("---------\r\n"), 0x80);
kotakku 0:b1ce54272580 724
kotakku 0:b1ce54272580 725 CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0);
kotakku 0:b1ce54272580 726 uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
kotakku 0:b1ce54272580 727
kotakku 0:b1ce54272580 728 return rc;
kotakku 0:b1ce54272580 729 }
kotakku 0:b1ce54272580 730
kotakku 0:b1ce54272580 731 /**
kotakku 0:b1ce54272580 732 * For driver use only.
kotakku 0:b1ce54272580 733 *
kotakku 0:b1ce54272580 734 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 735 * @return
kotakku 0:b1ce54272580 736 */
kotakku 0:b1ce54272580 737 uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
kotakku 0:b1ce54272580 738 //SetCurLUN(lun);
kotakku 0:b1ce54272580 739 if(!bAddress)
kotakku 0:b1ce54272580 740 return MASS_ERR_UNIT_NOT_READY;
kotakku 0:b1ce54272580 741
kotakku 0:b1ce54272580 742 Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
kotakku 0:b1ce54272580 743 Notify(PSTR("-----------------\r\n"), 0x80);
kotakku 0:b1ce54272580 744
kotakku 0:b1ce54272580 745 CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);
kotakku 0:b1ce54272580 746 return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN);
kotakku 0:b1ce54272580 747
kotakku 0:b1ce54272580 748 }
kotakku 0:b1ce54272580 749
kotakku 0:b1ce54272580 750 /**
kotakku 0:b1ce54272580 751 * For driver use only.
kotakku 0:b1ce54272580 752 *
kotakku 0:b1ce54272580 753 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 754 * @param pc
kotakku 0:b1ce54272580 755 * @param page
kotakku 0:b1ce54272580 756 * @param subpage
kotakku 0:b1ce54272580 757 * @param len
kotakku 0:b1ce54272580 758 * @param pbuf
kotakku 0:b1ce54272580 759 * @return
kotakku 0:b1ce54272580 760 */
kotakku 0:b1ce54272580 761 uint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
kotakku 0:b1ce54272580 762 Notify(PSTR("\r\rModeSense\r\n"), 0x80);
kotakku 0:b1ce54272580 763 Notify(PSTR("------------\r\n"), 0x80);
kotakku 0:b1ce54272580 764
kotakku 0:b1ce54272580 765 CDB6_t cdb = CDB6_t(SCSI_CMD_MODE_SENSE_6, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0);
kotakku 0:b1ce54272580 766 return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN);
kotakku 0:b1ce54272580 767 }
kotakku 0:b1ce54272580 768
kotakku 0:b1ce54272580 769 /**
kotakku 0:b1ce54272580 770 * For driver use only.
kotakku 0:b1ce54272580 771 *
kotakku 0:b1ce54272580 772 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 773 * @param bsize
kotakku 0:b1ce54272580 774 * @param buf
kotakku 0:b1ce54272580 775 * @return
kotakku 0:b1ce54272580 776 */
kotakku 0:b1ce54272580 777 uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
kotakku 0:b1ce54272580 778 Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
kotakku 0:b1ce54272580 779 Notify(PSTR("---------------\r\n"), 0x80);
kotakku 0:b1ce54272580 780
kotakku 0:b1ce54272580 781 CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun);
kotakku 0:b1ce54272580 782 return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN);
kotakku 0:b1ce54272580 783 }
kotakku 0:b1ce54272580 784
kotakku 0:b1ce54272580 785 /**
kotakku 0:b1ce54272580 786 * For driver use only.
kotakku 0:b1ce54272580 787 *
kotakku 0:b1ce54272580 788 * Page 3F contains write protect status.
kotakku 0:b1ce54272580 789 *
kotakku 0:b1ce54272580 790 * @param lun Logical Unit Number to test.
kotakku 0:b1ce54272580 791 * @return Write protect switch status.
kotakku 0:b1ce54272580 792 */
kotakku 0:b1ce54272580 793 uint8_t BulkOnly::Page3F(uint8_t lun) {
kotakku 0:b1ce54272580 794 uint8_t buf[192];
kotakku 0:b1ce54272580 795 for(int i = 0; i < 192; i++) {
kotakku 0:b1ce54272580 796 buf[i] = 0x00;
kotakku 0:b1ce54272580 797 }
kotakku 0:b1ce54272580 798 WriteOk[lun] = true;
kotakku 0:b1ce54272580 799 uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
kotakku 0:b1ce54272580 800 if(!rc) {
kotakku 0:b1ce54272580 801 WriteOk[lun] = ((buf[2] & 0x80) == 0);
kotakku 0:b1ce54272580 802 Notify(PSTR("Mode Sense: "), 0x80);
kotakku 0:b1ce54272580 803 for(int i = 0; i < 4; i++) {
kotakku 0:b1ce54272580 804 D_PrintHex<uint8_t > (buf[i], 0x80);
kotakku 0:b1ce54272580 805 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 806 }
kotakku 0:b1ce54272580 807 Notify(PSTR("\r\n"), 0x80);
kotakku 0:b1ce54272580 808 }
kotakku 0:b1ce54272580 809 return rc;
kotakku 0:b1ce54272580 810 }
kotakku 0:b1ce54272580 811
kotakku 0:b1ce54272580 812 /**
kotakku 0:b1ce54272580 813 * For driver use only.
kotakku 0:b1ce54272580 814 *
kotakku 0:b1ce54272580 815 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 816 * @param size
kotakku 0:b1ce54272580 817 * @param buf
kotakku 0:b1ce54272580 818 * @return
kotakku 0:b1ce54272580 819 */
kotakku 0:b1ce54272580 820 uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
kotakku 0:b1ce54272580 821 Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
kotakku 0:b1ce54272580 822 Notify(PSTR("----------------\r\n"), 0x80);
kotakku 0:b1ce54272580 823
kotakku 0:b1ce54272580 824 CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0);
kotakku 0:b1ce54272580 825 CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
kotakku 0:b1ce54272580 826 //SetCurLUN(lun);
kotakku 0:b1ce54272580 827 return Transaction(&cbw, size, buf);
kotakku 0:b1ce54272580 828 }
kotakku 0:b1ce54272580 829
kotakku 0:b1ce54272580 830
kotakku 0:b1ce54272580 831 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 832
kotakku 0:b1ce54272580 833
kotakku 0:b1ce54272580 834 // USB code
kotakku 0:b1ce54272580 835
kotakku 0:b1ce54272580 836
kotakku 0:b1ce54272580 837 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 838
kotakku 0:b1ce54272580 839 /**
kotakku 0:b1ce54272580 840 * For driver use only.
kotakku 0:b1ce54272580 841 *
kotakku 0:b1ce54272580 842 * @param index
kotakku 0:b1ce54272580 843 * @return
kotakku 0:b1ce54272580 844 */
kotakku 0:b1ce54272580 845 uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
kotakku 0:b1ce54272580 846 if(index == 0)
kotakku 0:b1ce54272580 847 return 0;
kotakku 0:b1ce54272580 848
kotakku 0:b1ce54272580 849 uint8_t ret = 0;
kotakku 0:b1ce54272580 850
kotakku 0:b1ce54272580 851 while((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01))
kotakku 0:b1ce54272580 852 delay(6);
kotakku 0:b1ce54272580 853
kotakku 0:b1ce54272580 854 if(ret) {
kotakku 0:b1ce54272580 855 ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
kotakku 0:b1ce54272580 856 ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
kotakku 0:b1ce54272580 857 return ret;
kotakku 0:b1ce54272580 858 }
kotakku 0:b1ce54272580 859 epInfo[index].bmSndToggle = 0;
kotakku 0:b1ce54272580 860 epInfo[index].bmRcvToggle = 0;
kotakku 0:b1ce54272580 861 return 0;
kotakku 0:b1ce54272580 862 }
kotakku 0:b1ce54272580 863
kotakku 0:b1ce54272580 864 /**
kotakku 0:b1ce54272580 865 * For driver use only.
kotakku 0:b1ce54272580 866 *
kotakku 0:b1ce54272580 867 */
kotakku 0:b1ce54272580 868 void BulkOnly::Reset() {
kotakku 0:b1ce54272580 869 while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
kotakku 0:b1ce54272580 870 }
kotakku 0:b1ce54272580 871
kotakku 0:b1ce54272580 872 /**
kotakku 0:b1ce54272580 873 * For driver use only.
kotakku 0:b1ce54272580 874 *
kotakku 0:b1ce54272580 875 * @return 0 if successful
kotakku 0:b1ce54272580 876 */
kotakku 0:b1ce54272580 877 uint8_t BulkOnly::ResetRecovery() {
kotakku 0:b1ce54272580 878 Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
kotakku 0:b1ce54272580 879 Notify(PSTR("-----------------\r\n"), 0x80);
kotakku 0:b1ce54272580 880
kotakku 0:b1ce54272580 881 delay(6);
kotakku 0:b1ce54272580 882 Reset();
kotakku 0:b1ce54272580 883 delay(6);
kotakku 0:b1ce54272580 884 ClearEpHalt(epDataInIndex);
kotakku 0:b1ce54272580 885 delay(6);
kotakku 0:b1ce54272580 886 bLastUsbError = ClearEpHalt(epDataOutIndex);
kotakku 0:b1ce54272580 887 delay(6);
kotakku 0:b1ce54272580 888 return bLastUsbError;
kotakku 0:b1ce54272580 889 }
kotakku 0:b1ce54272580 890
kotakku 0:b1ce54272580 891 /**
kotakku 0:b1ce54272580 892 * For driver use only.
kotakku 0:b1ce54272580 893 *
kotakku 0:b1ce54272580 894 * Clear all EP data and clear all LUN status
kotakku 0:b1ce54272580 895 */
kotakku 0:b1ce54272580 896 void BulkOnly::ClearAllEP() {
kotakku 0:b1ce54272580 897 for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
kotakku 0:b1ce54272580 898 epInfo[i].epAddr = 0;
kotakku 0:b1ce54272580 899 epInfo[i].maxPktSize = (i) ? 0 : 8;
kotakku 0:b1ce54272580 900 epInfo[i].bmSndToggle = 0;
kotakku 0:b1ce54272580 901 epInfo[i].bmRcvToggle = 0;
kotakku 0:b1ce54272580 902 epInfo[i].bmNakPower = USB_NAK_DEFAULT;
kotakku 0:b1ce54272580 903 }
kotakku 0:b1ce54272580 904
kotakku 0:b1ce54272580 905 for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
kotakku 0:b1ce54272580 906 LUNOk[i] = false;
kotakku 0:b1ce54272580 907 WriteOk[i] = false;
kotakku 0:b1ce54272580 908 CurrentCapacity[i] = 0lu;
kotakku 0:b1ce54272580 909 CurrentSectorSize[i] = 0;
kotakku 0:b1ce54272580 910 }
kotakku 0:b1ce54272580 911
kotakku 0:b1ce54272580 912 bIface = 0;
kotakku 0:b1ce54272580 913 bNumEP = 1;
kotakku 0:b1ce54272580 914 bAddress = 0;
kotakku 0:b1ce54272580 915 qNextPollTime = 0;
kotakku 0:b1ce54272580 916 bPollEnable = false;
kotakku 0:b1ce54272580 917 bLastUsbError = 0;
kotakku 0:b1ce54272580 918 bMaxLUN = 0;
kotakku 0:b1ce54272580 919 bTheLUN = 0;
kotakku 0:b1ce54272580 920 }
kotakku 0:b1ce54272580 921
kotakku 0:b1ce54272580 922 /**
kotakku 0:b1ce54272580 923 * For driver use only.
kotakku 0:b1ce54272580 924 *
kotakku 0:b1ce54272580 925 * @param pcsw
kotakku 0:b1ce54272580 926 * @param pcbw
kotakku 0:b1ce54272580 927 * @return
kotakku 0:b1ce54272580 928 */
kotakku 0:b1ce54272580 929 bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
kotakku 0:b1ce54272580 930 if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
kotakku 0:b1ce54272580 931 Notify(PSTR("CSW:Sig error\r\n"), 0x80);
kotakku 0:b1ce54272580 932 return false;
kotakku 0:b1ce54272580 933 }
kotakku 0:b1ce54272580 934 if(pcsw->dCSWTag != pcbw->dCBWTag) {
kotakku 0:b1ce54272580 935 Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
kotakku 0:b1ce54272580 936 return false;
kotakku 0:b1ce54272580 937 }
kotakku 0:b1ce54272580 938 return true;
kotakku 0:b1ce54272580 939 }
kotakku 0:b1ce54272580 940
kotakku 0:b1ce54272580 941 /**
kotakku 0:b1ce54272580 942 * For driver use only.
kotakku 0:b1ce54272580 943 *
kotakku 0:b1ce54272580 944 * @param error
kotakku 0:b1ce54272580 945 * @param index
kotakku 0:b1ce54272580 946 * @return
kotakku 0:b1ce54272580 947 */
kotakku 0:b1ce54272580 948 uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
kotakku 0:b1ce54272580 949 uint8_t count = 3;
kotakku 0:b1ce54272580 950
kotakku 0:b1ce54272580 951 bLastUsbError = error;
kotakku 0:b1ce54272580 952 //if (error)
kotakku 0:b1ce54272580 953 //ClearEpHalt(index);
kotakku 0:b1ce54272580 954 while(error && count) {
kotakku 0:b1ce54272580 955 if(error != hrSUCCESS) {
kotakku 0:b1ce54272580 956 ErrorMessage<uint8_t > (PSTR("USB Error"), error);
kotakku 0:b1ce54272580 957 ErrorMessage<uint8_t > (PSTR("Index"), index);
kotakku 0:b1ce54272580 958 }
kotakku 0:b1ce54272580 959 switch(error) {
kotakku 0:b1ce54272580 960 // case hrWRONGPID:
kotakku 0:b1ce54272580 961 case hrSUCCESS:
kotakku 0:b1ce54272580 962 return MASS_ERR_SUCCESS;
kotakku 0:b1ce54272580 963 case hrBUSY:
kotakku 0:b1ce54272580 964 // SIE is busy, just hang out and try again.
kotakku 0:b1ce54272580 965 return MASS_ERR_UNIT_BUSY;
kotakku 0:b1ce54272580 966 case hrTIMEOUT:
kotakku 0:b1ce54272580 967 case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED;
kotakku 0:b1ce54272580 968 case hrSTALL:
kotakku 0:b1ce54272580 969 if(index == 0)
kotakku 0:b1ce54272580 970 return MASS_ERR_STALL;
kotakku 0:b1ce54272580 971 ClearEpHalt(index);
kotakku 0:b1ce54272580 972 if(index != epDataInIndex)
kotakku 0:b1ce54272580 973 return MASS_ERR_WRITE_STALL;
kotakku 0:b1ce54272580 974 return MASS_ERR_STALL;
kotakku 0:b1ce54272580 975
kotakku 0:b1ce54272580 976 case hrNAK:
kotakku 0:b1ce54272580 977 if(index == 0)
kotakku 0:b1ce54272580 978 return MASS_ERR_UNIT_BUSY;
kotakku 0:b1ce54272580 979 return MASS_ERR_UNIT_BUSY;
kotakku 0:b1ce54272580 980
kotakku 0:b1ce54272580 981 case hrTOGERR:
kotakku 0:b1ce54272580 982 // Handle a very super rare corner case, where toggles become de-synched.
kotakku 0:b1ce54272580 983 // I have only ran into one device that has this firmware bug, and this is
kotakku 0:b1ce54272580 984 // the only clean way to get back into sync with the buggy device firmware.
kotakku 0:b1ce54272580 985 // --AJK
kotakku 0:b1ce54272580 986 if(bAddress && bConfNum) {
kotakku 0:b1ce54272580 987 error = pUsb->setConf(bAddress, 0, bConfNum);
kotakku 0:b1ce54272580 988
kotakku 0:b1ce54272580 989 if(error)
kotakku 0:b1ce54272580 990 break;
kotakku 0:b1ce54272580 991 }
kotakku 0:b1ce54272580 992 return MASS_ERR_SUCCESS;
kotakku 0:b1ce54272580 993 default:
kotakku 0:b1ce54272580 994 ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
kotakku 0:b1ce54272580 995 return MASS_ERR_GENERAL_USB_ERROR;
kotakku 0:b1ce54272580 996 }
kotakku 0:b1ce54272580 997 count--;
kotakku 0:b1ce54272580 998 } // while
kotakku 0:b1ce54272580 999
kotakku 0:b1ce54272580 1000 return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
kotakku 0:b1ce54272580 1001 }
kotakku 0:b1ce54272580 1002
kotakku 0:b1ce54272580 1003 #if MS_WANT_PARSER
kotakku 0:b1ce54272580 1004
kotakku 0:b1ce54272580 1005 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
kotakku 0:b1ce54272580 1006 return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
kotakku 0:b1ce54272580 1007 }
kotakku 0:b1ce54272580 1008 #endif
kotakku 0:b1ce54272580 1009
kotakku 0:b1ce54272580 1010 /**
kotakku 0:b1ce54272580 1011 * For driver use only.
kotakku 0:b1ce54272580 1012 *
kotakku 0:b1ce54272580 1013 * @param pcbw
kotakku 0:b1ce54272580 1014 * @param buf_size
kotakku 0:b1ce54272580 1015 * @param buf
kotakku 0:b1ce54272580 1016 * @param flags
kotakku 0:b1ce54272580 1017 * @return
kotakku 0:b1ce54272580 1018 */
kotakku 0:b1ce54272580 1019 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
kotakku 0:b1ce54272580 1020 #if MS_WANT_PARSER
kotakku 0:b1ce54272580 1021 , uint8_t flags
kotakku 0:b1ce54272580 1022 #endif
kotakku 0:b1ce54272580 1023 ) {
kotakku 0:b1ce54272580 1024
kotakku 0:b1ce54272580 1025 #if MS_WANT_PARSER
kotakku 0:b1ce54272580 1026 uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
kotakku 0:b1ce54272580 1027 printf("Transfersize %i\r\n", bytes);
kotakku 0:b1ce54272580 1028 delay(1000);
kotakku 0:b1ce54272580 1029
kotakku 0:b1ce54272580 1030 bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
kotakku 0:b1ce54272580 1031 #else
kotakku 0:b1ce54272580 1032 uint16_t bytes = buf_size;
kotakku 0:b1ce54272580 1033 #endif
kotakku 0:b1ce54272580 1034 bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
kotakku 0:b1ce54272580 1035 uint8_t ret = 0;
kotakku 0:b1ce54272580 1036 uint8_t usberr;
kotakku 0:b1ce54272580 1037 CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
kotakku 0:b1ce54272580 1038 SetCurLUN(pcbw->bmCBWLUN);
kotakku 0:b1ce54272580 1039 ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
kotakku 0:b1ce54272580 1040
kotakku 0:b1ce54272580 1041 while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
kotakku 0:b1ce54272580 1042
kotakku 0:b1ce54272580 1043 ret = HandleUsbError(usberr, epDataOutIndex);
kotakku 0:b1ce54272580 1044 //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
kotakku 0:b1ce54272580 1045 if(ret) {
kotakku 0:b1ce54272580 1046 ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
kotakku 0:b1ce54272580 1047 } else {
kotakku 0:b1ce54272580 1048 if(bytes) {
kotakku 0:b1ce54272580 1049 if(!write) {
kotakku 0:b1ce54272580 1050 #if MS_WANT_PARSER
kotakku 0:b1ce54272580 1051 if(callback) {
kotakku 0:b1ce54272580 1052 uint8_t rbuf[bytes];
kotakku 0:b1ce54272580 1053 while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
kotakku 0:b1ce54272580 1054 if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
kotakku 0:b1ce54272580 1055 } else {
kotakku 0:b1ce54272580 1056 #endif
kotakku 0:b1ce54272580 1057 while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
kotakku 0:b1ce54272580 1058 #if MS_WANT_PARSER
kotakku 0:b1ce54272580 1059
kotakku 0:b1ce54272580 1060 }
kotakku 0:b1ce54272580 1061 #endif
kotakku 0:b1ce54272580 1062 ret = HandleUsbError(usberr, epDataInIndex);
kotakku 0:b1ce54272580 1063 } else {
kotakku 0:b1ce54272580 1064 while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
kotakku 0:b1ce54272580 1065 ret = HandleUsbError(usberr, epDataOutIndex);
kotakku 0:b1ce54272580 1066 }
kotakku 0:b1ce54272580 1067 if(ret) {
kotakku 0:b1ce54272580 1068 ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
kotakku 0:b1ce54272580 1069 }
kotakku 0:b1ce54272580 1070 }
kotakku 0:b1ce54272580 1071 }
kotakku 0:b1ce54272580 1072
kotakku 0:b1ce54272580 1073 {
kotakku 0:b1ce54272580 1074 bytes = sizeof (CommandStatusWrapper);
kotakku 0:b1ce54272580 1075 int tries = 2;
kotakku 0:b1ce54272580 1076 while(tries--) {
kotakku 0:b1ce54272580 1077 while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
kotakku 0:b1ce54272580 1078 if(!usberr) break;
kotakku 0:b1ce54272580 1079 ClearEpHalt(epDataInIndex);
kotakku 0:b1ce54272580 1080 if(tries) ResetRecovery();
kotakku 0:b1ce54272580 1081 }
kotakku 0:b1ce54272580 1082 if(!ret) {
kotakku 0:b1ce54272580 1083 Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
kotakku 0:b1ce54272580 1084 Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
kotakku 0:b1ce54272580 1085 } else {
kotakku 0:b1ce54272580 1086 // Throw away csw, IT IS NOT OF ANY USE.
kotakku 0:b1ce54272580 1087 ResetRecovery();
kotakku 0:b1ce54272580 1088 return ret;
kotakku 0:b1ce54272580 1089 }
kotakku 0:b1ce54272580 1090 ret = HandleUsbError(usberr, epDataInIndex);
kotakku 0:b1ce54272580 1091 if(ret) {
kotakku 0:b1ce54272580 1092 ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
kotakku 0:b1ce54272580 1093 }
kotakku 0:b1ce54272580 1094 if(usberr == hrSUCCESS) {
kotakku 0:b1ce54272580 1095 if(IsValidCSW(&csw, pcbw)) {
kotakku 0:b1ce54272580 1096 //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
kotakku 0:b1ce54272580 1097 //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
kotakku 0:b1ce54272580 1098 //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
kotakku 0:b1ce54272580 1099 Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
kotakku 0:b1ce54272580 1100 return csw.bCSWStatus;
kotakku 0:b1ce54272580 1101 } else {
kotakku 0:b1ce54272580 1102 // NOTE! Sometimes this is caused by the reported residue being wrong.
kotakku 0:b1ce54272580 1103 // Get a different device. It isn't compliant, and should have never passed Q&A.
kotakku 0:b1ce54272580 1104 // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
kotakku 0:b1ce54272580 1105 // Other devices that exhibit this behavior exist in the wild too.
kotakku 0:b1ce54272580 1106 // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk
kotakku 0:b1ce54272580 1107 Notify(PSTR("Invalid CSW\r\n"), 0x80);
kotakku 0:b1ce54272580 1108 ResetRecovery();
kotakku 0:b1ce54272580 1109 //return MASS_ERR_SUCCESS;
kotakku 0:b1ce54272580 1110 return MASS_ERR_INVALID_CSW;
kotakku 0:b1ce54272580 1111 }
kotakku 0:b1ce54272580 1112 }
kotakku 0:b1ce54272580 1113 }
kotakku 0:b1ce54272580 1114 return ret;
kotakku 0:b1ce54272580 1115 }
kotakku 0:b1ce54272580 1116
kotakku 0:b1ce54272580 1117 /**
kotakku 0:b1ce54272580 1118 * For driver use only.
kotakku 0:b1ce54272580 1119 *
kotakku 0:b1ce54272580 1120 * @param lun Logical Unit Number
kotakku 0:b1ce54272580 1121 * @return
kotakku 0:b1ce54272580 1122 */
kotakku 0:b1ce54272580 1123 uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
kotakku 0:b1ce54272580 1124 if(lun > bMaxLUN)
kotakku 0:b1ce54272580 1125 return MASS_ERR_INVALID_LUN;
kotakku 0:b1ce54272580 1126 bTheLUN = lun;
kotakku 0:b1ce54272580 1127 return MASS_ERR_SUCCESS;
kotakku 0:b1ce54272580 1128 };
kotakku 0:b1ce54272580 1129
kotakku 0:b1ce54272580 1130 /**
kotakku 0:b1ce54272580 1131 * For driver use only.
kotakku 0:b1ce54272580 1132 *
kotakku 0:b1ce54272580 1133 * @param status
kotakku 0:b1ce54272580 1134 * @return
kotakku 0:b1ce54272580 1135 */
kotakku 0:b1ce54272580 1136 uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
kotakku 0:b1ce54272580 1137 uint8_t ret = 0;
kotakku 0:b1ce54272580 1138
kotakku 0:b1ce54272580 1139 switch(status) {
kotakku 0:b1ce54272580 1140 case 0: return MASS_ERR_SUCCESS;
kotakku 0:b1ce54272580 1141
kotakku 0:b1ce54272580 1142 case 2:
kotakku 0:b1ce54272580 1143 ErrorMessage<uint8_t > (PSTR("Phase Error"), status);
kotakku 0:b1ce54272580 1144 ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
kotakku 0:b1ce54272580 1145 ResetRecovery();
kotakku 0:b1ce54272580 1146 return MASS_ERR_GENERAL_SCSI_ERROR;
kotakku 0:b1ce54272580 1147
kotakku 0:b1ce54272580 1148 case 1:
kotakku 0:b1ce54272580 1149 ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
kotakku 0:b1ce54272580 1150 ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
kotakku 0:b1ce54272580 1151 RequestSenseResponce rsp;
kotakku 0:b1ce54272580 1152
kotakku 0:b1ce54272580 1153 ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
kotakku 0:b1ce54272580 1154
kotakku 0:b1ce54272580 1155 if(ret) {
kotakku 0:b1ce54272580 1156 return MASS_ERR_GENERAL_SCSI_ERROR;
kotakku 0:b1ce54272580 1157 }
kotakku 0:b1ce54272580 1158 ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
kotakku 0:b1ce54272580 1159 if(rsp.bResponseCode & 0x80) {
kotakku 0:b1ce54272580 1160 Notify(PSTR("Information field: "), 0x80);
kotakku 0:b1ce54272580 1161 for(int i = 0; i < 4; i++) {
kotakku 0:b1ce54272580 1162 D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
kotakku 0:b1ce54272580 1163 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 1164 }
kotakku 0:b1ce54272580 1165 Notify(PSTR("\r\n"), 0x80);
kotakku 0:b1ce54272580 1166 }
kotakku 0:b1ce54272580 1167 ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
kotakku 0:b1ce54272580 1168 ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
kotakku 0:b1ce54272580 1169 ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
kotakku 0:b1ce54272580 1170 // warning, this is not testing ASQ, only SK and ASC.
kotakku 0:b1ce54272580 1171 switch(rsp.bmSenseKey) {
kotakku 0:b1ce54272580 1172 case SCSI_S_UNIT_ATTENTION:
kotakku 0:b1ce54272580 1173 switch(rsp.bAdditionalSenseCode) {
kotakku 0:b1ce54272580 1174 case SCSI_ASC_MEDIA_CHANGED:
kotakku 0:b1ce54272580 1175 return MASS_ERR_MEDIA_CHANGED;
kotakku 0:b1ce54272580 1176 default:
kotakku 0:b1ce54272580 1177 return MASS_ERR_UNIT_NOT_READY;
kotakku 0:b1ce54272580 1178 }
kotakku 0:b1ce54272580 1179 case SCSI_S_NOT_READY:
kotakku 0:b1ce54272580 1180 switch(rsp.bAdditionalSenseCode) {
kotakku 0:b1ce54272580 1181 case SCSI_ASC_MEDIUM_NOT_PRESENT:
kotakku 0:b1ce54272580 1182 return MASS_ERR_NO_MEDIA;
kotakku 0:b1ce54272580 1183 default:
kotakku 0:b1ce54272580 1184 return MASS_ERR_UNIT_NOT_READY;
kotakku 0:b1ce54272580 1185 }
kotakku 0:b1ce54272580 1186 case SCSI_S_ILLEGAL_REQUEST:
kotakku 0:b1ce54272580 1187 switch(rsp.bAdditionalSenseCode) {
kotakku 0:b1ce54272580 1188 case SCSI_ASC_LBA_OUT_OF_RANGE:
kotakku 0:b1ce54272580 1189 return MASS_ERR_BAD_LBA;
kotakku 0:b1ce54272580 1190 default:
kotakku 0:b1ce54272580 1191 return MASS_ERR_CMD_NOT_SUPPORTED;
kotakku 0:b1ce54272580 1192 }
kotakku 0:b1ce54272580 1193 default:
kotakku 0:b1ce54272580 1194 return MASS_ERR_GENERAL_SCSI_ERROR;
kotakku 0:b1ce54272580 1195 }
kotakku 0:b1ce54272580 1196
kotakku 0:b1ce54272580 1197 // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
kotakku 0:b1ce54272580 1198 // case 0x05/0x14: we stalled out
kotakku 0:b1ce54272580 1199 // case 0x15/0x16: we naked out.
kotakku 0:b1ce54272580 1200 default:
kotakku 0:b1ce54272580 1201 ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
kotakku 0:b1ce54272580 1202 ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
kotakku 0:b1ce54272580 1203 return status;
kotakku 0:b1ce54272580 1204 } // switch
kotakku 0:b1ce54272580 1205 }
kotakku 0:b1ce54272580 1206
kotakku 0:b1ce54272580 1207
kotakku 0:b1ce54272580 1208 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 1209
kotakku 0:b1ce54272580 1210
kotakku 0:b1ce54272580 1211 // Debugging code
kotakku 0:b1ce54272580 1212
kotakku 0:b1ce54272580 1213
kotakku 0:b1ce54272580 1214 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 1215
kotakku 0:b1ce54272580 1216 /**
kotakku 0:b1ce54272580 1217 *
kotakku 0:b1ce54272580 1218 * @param ep_ptr
kotakku 0:b1ce54272580 1219 */
kotakku 0:b1ce54272580 1220 void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
kotakku 0:b1ce54272580 1221 Notify(PSTR("Endpoint descriptor:"), 0x80);
kotakku 0:b1ce54272580 1222 Notify(PSTR("\r\nLength:\t\t"), 0x80);
kotakku 0:b1ce54272580 1223 D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
kotakku 0:b1ce54272580 1224 Notify(PSTR("\r\nType:\t\t"), 0x80);
kotakku 0:b1ce54272580 1225 D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
kotakku 0:b1ce54272580 1226 Notify(PSTR("\r\nAddress:\t"), 0x80);
kotakku 0:b1ce54272580 1227 D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
kotakku 0:b1ce54272580 1228 Notify(PSTR("\r\nAttributes:\t"), 0x80);
kotakku 0:b1ce54272580 1229 D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
kotakku 0:b1ce54272580 1230 Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
kotakku 0:b1ce54272580 1231 D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
kotakku 0:b1ce54272580 1232 Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
kotakku 0:b1ce54272580 1233 D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
kotakku 0:b1ce54272580 1234 Notify(PSTR("\r\n"), 0x80);
kotakku 0:b1ce54272580 1235 }
kotakku 0:b1ce54272580 1236
kotakku 0:b1ce54272580 1237
kotakku 0:b1ce54272580 1238 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 1239
kotakku 0:b1ce54272580 1240
kotakku 0:b1ce54272580 1241 // misc/to kill/to-do
kotakku 0:b1ce54272580 1242
kotakku 0:b1ce54272580 1243
kotakku 0:b1ce54272580 1244 ////////////////////////////////////////////////////////////////////////////////
kotakku 0:b1ce54272580 1245
kotakku 0:b1ce54272580 1246 /* We won't be needing this... */
kotakku 0:b1ce54272580 1247 uint8_t BulkOnly::Read(uint8_t lun __attribute__((unused)), uint32_t addr __attribute__((unused)), uint16_t bsize __attribute__((unused)), uint8_t blocks __attribute__((unused)), USBReadParser * prs __attribute__((unused))) {
kotakku 0:b1ce54272580 1248 #if MS_WANT_PARSER
kotakku 0:b1ce54272580 1249 if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
kotakku 0:b1ce54272580 1250 Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
kotakku 0:b1ce54272580 1251 Notify(PSTR("---------\r\n"), 0x80);
kotakku 0:b1ce54272580 1252
kotakku 0:b1ce54272580 1253 CommandBlockWrapper cbw = CommandBlockWrapper();
kotakku 0:b1ce54272580 1254
kotakku 0:b1ce54272580 1255 cbw.dCBWSignature = MASS_CBW_SIGNATURE;
kotakku 0:b1ce54272580 1256 cbw.dCBWTag = ++dCBWTag;
kotakku 0:b1ce54272580 1257 cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
kotakku 0:b1ce54272580 1258 cbw.bmCBWFlags = MASS_CMD_DIR_IN,
kotakku 0:b1ce54272580 1259 cbw.bmCBWLUN = lun;
kotakku 0:b1ce54272580 1260 cbw.bmCBWCBLength = 10;
kotakku 0:b1ce54272580 1261
kotakku 0:b1ce54272580 1262 cbw.CBWCB[0] = SCSI_CMD_READ_10;
kotakku 0:b1ce54272580 1263 cbw.CBWCB[8] = blocks;
kotakku 0:b1ce54272580 1264 cbw.CBWCB[2] = ((addr >> 24) & 0xff);
kotakku 0:b1ce54272580 1265 cbw.CBWCB[3] = ((addr >> 16) & 0xff);
kotakku 0:b1ce54272580 1266 cbw.CBWCB[4] = ((addr >> 8) & 0xff);
kotakku 0:b1ce54272580 1267 cbw.CBWCB[5] = (addr & 0xff);
kotakku 0:b1ce54272580 1268
kotakku 0:b1ce54272580 1269 return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
kotakku 0:b1ce54272580 1270 #else
kotakku 0:b1ce54272580 1271 return MASS_ERR_NOT_IMPLEMENTED;
kotakku 0:b1ce54272580 1272 #endif
kotakku 0:b1ce54272580 1273 }
kotakku 0:b1ce54272580 1274