git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2812 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2011-03-09 16:38:56 +00:00
parent 0df60fe0a4
commit f27e4f46fe
2 changed files with 71 additions and 23 deletions

View File

@ -64,18 +64,19 @@ static uint32_t cbw_tag;
static uint32_t csw_sent; static uint32_t csw_sent;
/** /**
* @brief Status . * @brief Status.
*/ */
static uint8_t csw_status; static uint8_t csw_status;
/** /**
* @brief Multi purpose I/O buffer. * @brief Received CBW.
*/ */
static union { static msccbw_t CBW;
uint8_t buf[512];
msccbw_t CBW; /**
msccsw_t CSW; * @brief CSW to be transmitted.
} u; */
static msccsw_t CSW;
/*===========================================================================*/ /*===========================================================================*/
/* Driver local functions. */ /* Driver local functions. */
@ -90,10 +91,54 @@ static void msc_reset(USBDriver *usbp) {
msc_state = MSC_IDLE; msc_state = MSC_IDLE;
chSysLockFromIsr(); chSysLockFromIsr();
usbStartReceiveI(usbp, MSC_DATA_OUT_EP, u.buf, sizeof(u.buf)); usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
chSysUnlockFromIsr(); chSysUnlockFromIsr();
} }
static void msc_transmit(USBDriver *usbp, const uint8_t *p, size_t n) {
if (n > CBW.dCBWDataTransferLength)
n = CBW.dCBWDataTransferLength;
CSW.dCSWDataResidue = CBW.dCBWDataTransferLength - (uint32_t)n;
chSysLockFromIsr();
usbStartTransmitI(usbp, MSC_DATA_IN_EP, scsi_inquiry_data, n);
chSysUnlockFromIsr();
}
static bool_t msc_decode_in(USBDriver *usbp) {
uint32_t nblocks, secsize;
size_t n;
switch (u.CBW.CBWCB[0]) {
case SCSI_INQUIRY:
msc_transmit(usbp, &scsi_inquiry_data, sizeof scsi_inquiry_data);
CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
break;
case SCSI_READ_FORMAT_CAPACITIES:
buf[8] = scsi_read_format_capacities(&nblocks, &secsize);
buf[0] = u.buf[1] = u.buf[2] = 0;
buf[3] = 8;
buf[4] = (tU8)(nblocks >> 24);
buf[5] = (tU8)(nblocks >> 16);
buf[6] = (tU8)(nblocks >> 8);
buf[7] = (tU8)(nblocks >> 0);
buf[9] = (tU8)(secsize >> 16);
buf[10] = (tU8)(secsize >> 8);
buf[11] = (tU8)(secsize >> 0);
msc_transmit(usbp, buf, 12);
CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
break;
default:
return TRUE;
}
return FALSE;
}
static bool_t msc_decode_out(USBDriver *usbp) {
return FALSE;
}
/*===========================================================================*/ /*===========================================================================*/
/* Driver exported functions. */ /* Driver exported functions. */
/*===========================================================================*/ /*===========================================================================*/
@ -143,18 +188,16 @@ void mscDataTransmitted(USBDriver *usbp, usbep_t ep) {
switch (msc_state) { switch (msc_state) {
case MSC_DATA_IN: case MSC_DATA_IN:
u.CSW.dCSWSignature = MSC_CSW_SIGNATURE; CSW.dCSWSignature = MSC_CSW_SIGNATURE;
u.CSW.dCSWTag = cbw_tag; CSW.dCSWTag = CBW.dCBWTag;
u.CSW.dCSWDataResidue = cbw_length - csw_sent;
u.CSW.bCSWStatus = csw_status;
chSysLockFromIsr(); chSysLockFromIsr();
usbStartTransmitI(usbp, ep, (uint8_t *)&u.CSW, sizeof(u.CSW)); usbStartTransmitI(usbp, ep, (uint8_t *)&CSW, sizeof CSW);
chSysUnlockFromIsr(); chSysUnlockFromIsr();
msc_state = MSC_SENDING_CSW; msc_state = MSC_SENDING_CSW;
break; break;
case MSC_SENDING_CSW: case MSC_SENDING_CSW:
chSysLockFromIsr(); chSysLockFromIsr();
usbStartReceiveI(usbp, MSC_DATA_OUT_EP, u.buf, sizeof(u.buf)); usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
chSysUnlockFromIsr(); chSysUnlockFromIsr();
msc_state = MSC_IDLE; msc_state = MSC_IDLE;
break; break;
@ -177,31 +220,32 @@ void mscDataReceived(USBDriver *usbp, usbep_t ep) {
n = usbGetReceiveTransactionSizeI(usbp, ep); n = usbGetReceiveTransactionSizeI(usbp, ep);
switch (msc_state) { switch (msc_state) {
case MSC_IDLE: case MSC_IDLE:
if ((n != sizeof(msccbw_t)) || if ((n != sizeof(msccbw_t)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE))
(u.CBW.dCBWSignature != MSC_CBW_SIGNATURE))
goto stallout; /* 6.6.1 */ goto stallout; /* 6.6.1 */
cbw_length = u.CBW.dCBWDataTransferLength; if (CBW.bmCBWFlags & 0x80) {
cbw_tag = u.CBW.dCBWTag;
if (u.CBW.bmCBWFlags & 0x80) {
/* IN, Device to Host.*/ /* IN, Device to Host.*/
/* if (scsi_decode_in(usbp)) if (msc_decode_in(usbp))
goto stallout;*/ goto stallout;
msc_state = MSC_DATA_IN; msc_state = MSC_DATA_IN;
} }
else { else {
/* OUT, Host to Device.*/ /* OUT, Host to Device.*/
/* if (scsi_decode_out(usbp)) if (msc_decode_out(usbp))
goto stallout;*/ goto stallout;
msc_state = MSC_DATA_OUT; msc_state = MSC_DATA_OUT;
} }
break; break;
case MSC_DATA_OUT:
break;
default: default:
; ;
} }
return; return;
stallout: stallout:
msc_state = MSC_ERROR; msc_state = MSC_ERROR;
chSysLockFromIsr();
usbStallReceiveI(usbp, ep); usbStallReceiveI(usbp, ep);
chSysUnlockFromIsr();
return; return;
} }

View File

@ -38,6 +38,10 @@
#define MSC_GET_MAX_LUN_COMMAND 0xFE #define MSC_GET_MAX_LUN_COMMAND 0xFE
#define MSC_MASS_STORAGE_RESET_COMMAND 0xFF #define MSC_MASS_STORAGE_RESET_COMMAND 0xFF
#define MSC_CSW_STATUS_PASSED 0
#define MSC_CSW_STATUS_FAILED 1
#define MSC_CSW_STATUS_PHASE_ERROR 2
/*===========================================================================*/ /*===========================================================================*/
/* Driver pre-compile time settings. */ /* Driver pre-compile time settings. */
/*===========================================================================*/ /*===========================================================================*/