123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716 |
- /*----------------------------------------------------------------------------
- * U S B - K e r n e l
- *----------------------------------------------------------------------------
- * Name: MSCUSER.C
- * Purpose: Mass Storage Class Custom User Module
- * Version: V1.10
- *----------------------------------------------------------------------------
- * This software is supplied "AS IS" without any warranties, express,
- * implied or statutory, including but not limited to the implied
- * warranties of fitness for purpose, satisfactory quality and
- * noninfringement. Keil extends you a royalty-free right to reproduce
- * and distribute executable files created using this software for use
- * on NXP Semiconductors LPC family microcontroller devices only. Nothing
- * else gives you the right to use this software.
- *
- * Copyright (c) 2005-2009 Keil Software.
- *---------------------------------------------------------------------------*/
-
- extern "C" {
- #include "LPC17xx.h"
- #include "lpc_types.h"
- }
- #include "usb.h"
- #include "msc.h"
- #include "usbcfg.h"
- #include "usbhw.h"
- #include "usbcore.h"
- #include "mscuser.h"
-
- #include "../chanfs/diskio.h"
- #include <debug_frmwrk.h>
-
- DWORD MSC_BlockCount = 0;
-
- uint32_t MemOK; /* Memory OK */
-
- DWORD lba; /* start block */
- DWORD transfer_count; /* blocks to transfer */
- DWORD length;
- uint32_t block_offset; /* current block offset*/
-
- uint8_t BulkStage; /* Bulk Stage */
-
- uint8_t BulkBuf[MSC_MAX_PACKET]; /* Bulk In/Out Buffer */
- uint8_t block_cache[MSC_BLOCK_SIZE];
- uint8_t BulkLen; /* Bulk In/Out Length */
-
- MSC_CBW CBW; /* Command Block Wrapper */
- MSC_CSW CSW; /* Command Status Wrapper */
- uint8_t media_lock = 0;
-
- uint32_t MSC_SD_Lock() {
- media_lock = CBW.CB[4]; //0x1 - lock, 0x0 - unlock
- // logical_unit = CBW.CB[1] & 0xE0;
- CSW.bStatus = CSW_CMD_PASSED;
- MSC_SetCSW();
- return 0;
- }
-
- uint32_t MSC_SD_Release(uint8_t pdrv) {
- MSC_BlockCount = 0;
- return 0;
- }
-
- uint32_t MSC_SD_Init(uint8_t pdrv) {
- DSTATUS ret = disk_initialize(pdrv);
- if(ret) return ret;
- if(disk_ioctl (pdrv, GET_SECTOR_COUNT, (void *)(&MSC_BlockCount))) return 1;
- return 0;
- }
-
- #define STARTSTOP_STOPMOTOR 0x0
- #define STARTSTOP_STARTMOTOR 0x1
- #define STARTSTOP_EJECT 0x2
- #define STARTSTOP_LOAD 0x3
-
- void MSC_StartStopUnit() {
- switch (CBW.CB[4] & 0x03) {
- case STARTSTOP_EJECT:
- MSC_SD_Release(0);
- break;
- case STARTSTOP_LOAD:
- if(MSC_BlockCount == 0) {
- if(MSC_SD_Init(0) != 0) {
- CSW.bStatus = CSW_CMD_FAILED;
- MSC_SetCSW();
- return;
- }
- }
- break;
- default:
- _DBG("MSC_StartStopUnit unknown startstopunit sub command\n");
- }
- CSW.bStatus = CSW_CMD_PASSED;
- MSC_SetCSW();
- }
-
- /*
- * MSC Mass Storage Reset Request Callback
- * Called automatically on Mass Storage Reset Request
- * Parameters: None (global SetupPacket and EP0Buf)
- * Return Value: TRUE - Success, FALSE - Error
- */
-
- uint32_t MSC_Reset (void) {
- BulkStage = MSC_BS_CBW;
- return (TRUE);
- }
-
-
- /*
- * MSC Get Max LUN Request Callback
- * Called automatically on Get Max LUN Request
- * Parameters: None (global SetupPacket and EP0Buf)
- * Return Value: TRUE - Success, FALSE - Error
- */
-
- uint32_t MSC_GetMaxLUN (void) {
-
- EP0Buf[0] = 0; /* No LUN associated with this device */
- return (TRUE);
- }
-
-
- /*
- * MSC Memory Read Callback
- * Called automatically on Memory Read Event
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_MemoryRead (void) {
- uint32_t n = (length > MSC_MAX_PACKET) ? MSC_MAX_PACKET : length;
-
- if (lba > MSC_BlockCount) {
- n = (MSC_BlockCount - lba) * MSC_BLOCK_SIZE + block_offset;
- BulkStage = MSC_BS_ERROR;
- }
-
- if(block_offset == 0) {
- disk_read (0, block_cache, lba, 1);
- }
-
- USB_WriteEP(MSC_EP_IN, &block_cache[block_offset], n);
-
- block_offset += n;
- length -= n;
- CSW.dDataResidue -= n;
-
- if(block_offset >= MSC_BLOCK_SIZE) {
- block_offset = 0;
- ++lba;
- }
-
- if (length == 0) {
- BulkStage = MSC_BS_DATA_IN_LAST;
- }
-
- if (BulkStage != MSC_BS_DATA_IN) {
- CSW.bStatus = CSW_CMD_PASSED;
- }
- }
-
-
- /*
- * MSC Memory Write Callback
- * Called automatically on Memory Write Event
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_MemoryWrite (void) {
-
- for (uint32_t n = 0; n < BulkLen; n++) {
- block_cache[block_offset + n] = BulkBuf[n];
- }
-
- if(block_offset + BulkLen >= MSC_BLOCK_SIZE) {
- if(!(disk_status(0) & STA_PROTECT)){
- disk_write(0, block_cache, lba, 1);
- }
- }
-
- block_offset += BulkLen;
- length -= BulkLen;
- CSW.dDataResidue -= BulkLen;
-
- if(block_offset >= MSC_BLOCK_SIZE) {
- block_offset = 0;
- ++lba;
- }
-
- if ((length == 0) || (BulkStage == MSC_BS_CSW)) {
- CSW.bStatus = CSW_CMD_PASSED;
- MSC_SetCSW();
- }
- }
-
-
- /*
- * MSC Memory Verify Callback
- * Called automatically on Memory Verify Event
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_MemoryVerify (void) {
-
- if(!block_offset) {
- disk_read(0, block_cache, lba, 1);
- }
-
- for (uint32_t n = 0; n < BulkLen; n++) {
- if (block_cache[block_offset + n] != BulkBuf[n]) {
- MemOK = FALSE;
- break;
- }
- }
-
- block_offset += BulkLen;
- length -= BulkLen;
- CSW.dDataResidue -= BulkLen;
-
- if ((length == 0) || (BulkStage == MSC_BS_CSW)) {
- CSW.bStatus = (MemOK) ? CSW_CMD_PASSED : CSW_CMD_FAILED;
- MSC_SetCSW();
- }
- }
-
-
- /*
- * MSC SCSI Read/Write Setup Callback
- * Parameters: None (global variables)
- * Return Value: TRUE - Success, FALSE - Error
- */
-
- uint32_t MSC_RWSetup (void) {
- uint32_t n;
-
- /* Logical Block Address of First Block */
- lba = (CBW.CB[2] << 24) |
- (CBW.CB[3] << 16) |
- (CBW.CB[4] << 8) |
- (CBW.CB[5] << 0);
-
- /* Number of Blocks to transfer */
- transfer_count = (CBW.CB[7] << 8) |
- (CBW.CB[8] << 0);
-
- block_offset = 0;
- length = transfer_count * MSC_BLOCK_SIZE;
-
- if (CBW.dDataLength != (transfer_count * MSC_BLOCK_SIZE)) {
- USB_SetStallEP(MSC_EP_IN);
- USB_SetStallEP(MSC_EP_OUT);
- CSW.bStatus = CSW_PHASE_ERROR;
- MSC_SetCSW();
- return (FALSE);
- }
-
- return (TRUE);
- }
-
-
- /*
- * Check Data IN Format
- * Parameters: None (global variables)
- * Return Value: TRUE - Success, FALSE - Error
- */
-
- uint32_t DataInFormat (void) {
-
- if (CBW.dDataLength == 0) {
- CSW.bStatus = CSW_PHASE_ERROR;
- MSC_SetCSW();
- return (FALSE);
- }
- if ((CBW.bmFlags & 0x80) == 0) {
- USB_SetStallEP(MSC_EP_OUT);
- CSW.bStatus = CSW_PHASE_ERROR;
- MSC_SetCSW();
- return (FALSE);
- }
- return (TRUE);
- }
-
-
- /*
- * Perform Data IN Transfer
- * Parameters: None (global variables)
- * Return Value: TRUE - Success, FALSE - Error
- */
-
- void DataInTransfer (void) {
-
- if (BulkLen > CBW.dDataLength) {
- BulkLen = CBW.dDataLength;
- }
-
- USB_WriteEP(MSC_EP_IN, BulkBuf, BulkLen);
- BulkStage = MSC_BS_DATA_IN_LAST;
-
- CSW.dDataResidue -= BulkLen;
- CSW.bStatus = CSW_CMD_PASSED;
- }
-
-
- /*
- * MSC SCSI Test Unit Ready Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_TestUnitReady (void) {
-
- if (CBW.dDataLength != 0) {
- if ((CBW.bmFlags & 0x80) != 0) {
- USB_SetStallEP(MSC_EP_IN);
- } else {
- USB_SetStallEP(MSC_EP_OUT);
- }
- }
-
- if(MSC_BlockCount > 0) {
- CSW.bStatus = CSW_CMD_PASSED;
- } else {
- CSW.bStatus = CSW_CMD_FAILED;
- }
-
- MSC_SetCSW();
- }
-
-
- /*
- * MSC SCSI Request Sense Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_RequestSense (void) {
-
- if (!DataInFormat()) return;
-
- BulkBuf[ 0] = 0x70; /* Response Code */
- BulkBuf[ 1] = 0x00;
- BulkBuf[ 2] = static_cast<uint8_t>(Sense_KEY::ILLEGAL_REQUEST);
- BulkBuf[ 3] = 0x00;
- BulkBuf[ 4] = 0x00;
- BulkBuf[ 5] = 0x00;
- BulkBuf[ 6] = 0x00;
- BulkBuf[ 7] = 0x0A; /* Additional Length */
-
- BulkBuf[ 8] = 0x00;
- BulkBuf[ 9] = 0x00;
- BulkBuf[10] = 0x00;
- BulkBuf[11] = 0x00;
- BulkBuf[12] = static_cast<uint8_t>(Sense_ASC::CANNOT_READ_MEDIUM);
- BulkBuf[13] = static_cast<uint8_t>(Sense_ASCQ::UNKNOWN_FORMAT);
- BulkBuf[14] = 0x00;
- BulkBuf[15] = 0x00;
- BulkBuf[16] = 0x00;
- BulkBuf[17] = 0x00;
-
- if (MSC_BlockCount == 0) {
- BulkBuf[ 2] = static_cast<uint8_t>(Sense_KEY::NOT_READY);
- BulkBuf[12] = static_cast<uint8_t>(Sense_ASC::MEDIUM_NOT_PRESENT);
- BulkBuf[13] = static_cast<uint8_t>(Sense_ASCQ::LOADABLE);
- }
-
- BulkLen = 18;
- DataInTransfer();
- }
-
-
- /*
- * MSC SCSI Inquiry Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_Inquiry (void) {
-
- if (!DataInFormat()) return;
-
- BulkBuf[ 0] = 0x00; /* Direct Access Device */
- BulkBuf[ 1] = 0x80; /* RMB = 1: Removable Medium */
- BulkBuf[ 2] = 0x00; /* Version: No conformance claim to standard */
- BulkBuf[ 3] = 0x01;
-
- BulkBuf[ 4] = 36-4; /* Additional Length */
- BulkBuf[ 5] = 0x80; /* SCCS = 1: Storage Controller Component */
- BulkBuf[ 6] = 0x00;
- BulkBuf[ 7] = 0x00;
-
- BulkBuf[ 8] = 'M'; /* Vendor Identification */
- BulkBuf[ 9] = 'a';
- BulkBuf[10] = 'r';
- BulkBuf[11] = 'l';
- BulkBuf[12] = 'i';
- BulkBuf[13] = 'n';
- BulkBuf[14] = ' ';
- BulkBuf[15] = ' ';
-
- BulkBuf[16] = 'R'; /* Product Identification */
- BulkBuf[17] = 'e';
- BulkBuf[18] = '-';
- BulkBuf[19] = 'A';
- BulkBuf[20] = 'R';
- BulkBuf[21] = 'M';
- BulkBuf[22] = ' ';
- BulkBuf[23] = 'S';
- BulkBuf[24] = 'D';
- BulkBuf[25] = 'C';
- BulkBuf[26] = 'a';
- BulkBuf[27] = 'r';
- BulkBuf[28] = 'd';
- BulkBuf[29] = ' ';
- BulkBuf[30] = '0';
- BulkBuf[31] = '1';
-
- BulkBuf[32] = '1'; /* Product Revision Level */
- BulkBuf[33] = '.';
- BulkBuf[34] = '0';
- BulkBuf[35] = ' ';
-
- if(MSC_BlockCount == 0) {
- BulkBuf[0] = 0x20; // Direct Access Device usually available but not currently
- }
-
- BulkLen = 36;
- DataInTransfer();
- }
-
-
- /*
- * MSC SCSI Mode Sense (6-Byte) Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_ModeSense6 (void) {
-
- if (!DataInFormat()) return;
-
- BulkBuf[ 0] = 0x03;
- BulkBuf[ 1] = 0x00;
- BulkBuf[ 2] = 0x00;
- BulkBuf[ 3] = 0x00;
-
- BulkLen = 4;
- DataInTransfer();
- }
-
-
- /*
- * MSC SCSI Mode Sense (10-Byte) Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_ModeSense10 (void) {
-
- if (!DataInFormat()) return;
-
- BulkBuf[ 0] = 0x00;
- BulkBuf[ 1] = 0x06;
- BulkBuf[ 2] = 0x00;
- BulkBuf[ 3] = 0x00;
- BulkBuf[ 4] = 0x00;
- BulkBuf[ 5] = 0x00;
- BulkBuf[ 6] = 0x00;
- BulkBuf[ 7] = 0x00;
-
- BulkLen = 8;
- DataInTransfer();
- }
-
-
- /*
- * MSC SCSI Read Capacity Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_ReadCapacity (void) {
-
- if (!DataInFormat()) return;
-
- /* Last Logical Block */
- BulkBuf[ 0] = ((MSC_BlockCount - 1) >> 24) & 0xFF;
- BulkBuf[ 1] = ((MSC_BlockCount - 1) >> 16) & 0xFF;
- BulkBuf[ 2] = ((MSC_BlockCount - 1) >> 8) & 0xFF;
- BulkBuf[ 3] = ((MSC_BlockCount - 1) >> 0) & 0xFF;
-
- /* Block Length */
- BulkBuf[ 4] = (MSC_BLOCK_SIZE >> 24) & 0xFF;
- BulkBuf[ 5] = (MSC_BLOCK_SIZE >> 16) & 0xFF;
- BulkBuf[ 6] = (MSC_BLOCK_SIZE >> 8) & 0xFF;
- BulkBuf[ 7] = (MSC_BLOCK_SIZE >> 0) & 0xFF;
-
- BulkLen = 8;
- DataInTransfer();
- }
-
-
- /*
- * MSC SCSI Read Format Capacity Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_ReadFormatCapacity (void) {
-
- if (!DataInFormat()) return;
-
- BulkBuf[ 0] = 0x00;
- BulkBuf[ 1] = 0x00;
- BulkBuf[ 2] = 0x00;
- BulkBuf[ 3] = 0x08; /* Capacity List Length */
-
- /* Block Count */
- BulkBuf[ 4] = (MSC_BlockCount >> 24) & 0xFF;
- BulkBuf[ 5] = (MSC_BlockCount >> 16) & 0xFF;
- BulkBuf[ 6] = (MSC_BlockCount >> 8) & 0xFF;
- BulkBuf[ 7] = (MSC_BlockCount >> 0) & 0xFF;
-
- /* Block Length */
- BulkBuf[ 8] = 0x02; /* Descriptor Code: Formatted Media */
- BulkBuf[ 9] = (MSC_BLOCK_SIZE >> 16) & 0xFF;
- BulkBuf[10] = (MSC_BLOCK_SIZE >> 8) & 0xFF;
- BulkBuf[11] = (MSC_BLOCK_SIZE >> 0) & 0xFF;
-
- BulkLen = 12;
- DataInTransfer();
- }
-
-
- /*
- * MSC Get Command Block Wrapper Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_GetCBW (void) {
- uint32_t n;
-
- for (n = 0; n < BulkLen; n++) {
- *((uint8_t *)&CBW + n) = BulkBuf[n];
- }
- if ((BulkLen == sizeof(CBW)) && (CBW.dSignature == MSC_CBW_Signature)) {
- /* Valid CBW */
- CSW.dTag = CBW.dTag;
- CSW.dDataResidue = CBW.dDataLength;
- if ((CBW.bLUN != 0) || (CBW.bCBLength < 1) || CBW.bCBLength > 16) {
- fail: CSW.bStatus = CSW_CMD_FAILED;
- MSC_SetCSW();
- _DBG("Failed SCSI OP code ");
- _DBH(CBW.CB[0]);
- _DBG("\n");
- } else {
- switch (CBW.CB[0]) {
- case SCSI_TEST_UNIT_READY:
- MSC_TestUnitReady();
- break;
- case SCSI_REQUEST_SENSE:
- MSC_RequestSense();
- break;
- case SCSI_FORMAT_UNIT:
- goto fail;
- case SCSI_INQUIRY:
- MSC_Inquiry();
- break;
- case SCSI_START_STOP_UNIT:
- MSC_StartStopUnit();
- break;
- case SCSI_MEDIA_REMOVAL:
- MSC_SD_Lock();
- break;
- case SCSI_MODE_SELECT6:
- goto fail;
- case SCSI_MODE_SENSE6:
- MSC_ModeSense6();
- break;
- case SCSI_MODE_SELECT10:
- goto fail;
- case SCSI_MODE_SENSE10:
- MSC_ModeSense10();
- break;
- case SCSI_READ_FORMAT_CAPACITIES:
- MSC_ReadFormatCapacity();
- break;
- case SCSI_READ_CAPACITY:
- MSC_ReadCapacity();
- break;
- case SCSI_READ10:
- if (MSC_RWSetup()) {
- if ((CBW.bmFlags & 0x80) != 0) {
- BulkStage = MSC_BS_DATA_IN;
- MSC_MemoryRead();
- } else {
- USB_SetStallEP(MSC_EP_OUT);
- CSW.bStatus = CSW_PHASE_ERROR;
- MSC_SetCSW();
- }
- }
- break;
- case SCSI_WRITE10:
- if (MSC_RWSetup()) {
- if ((CBW.bmFlags & 0x80) == 0) {
- BulkStage = MSC_BS_DATA_OUT;
- } else {
- USB_SetStallEP(MSC_EP_IN);
- CSW.bStatus = CSW_PHASE_ERROR;
- MSC_SetCSW();
- }
- }
- break;
- case SCSI_VERIFY10:
- if (MSC_RWSetup()) {
- if ((CBW.bmFlags & 0x80) == 0) {
- BulkStage = MSC_BS_DATA_OUT;
- MemOK = TRUE;
- } else {
- USB_SetStallEP(MSC_EP_IN);
- CSW.bStatus = CSW_PHASE_ERROR;
- MSC_SetCSW();
- }
- }
- break;
- default:
- goto fail;
- }
- }
- } else {
- /* Invalid CBW */
- USB_SetStallEP(MSC_EP_IN);
- USB_SetStallEP(MSC_EP_OUT);
- BulkStage = MSC_BS_ERROR;
- }
- }
-
-
- /*
- * MSC Set Command Status Wrapper Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_SetCSW (void) {
-
- CSW.dSignature = MSC_CSW_Signature;
- USB_WriteEP(MSC_EP_IN, (uint8_t *)&CSW, sizeof(CSW));
- BulkStage = MSC_BS_CSW;
- }
-
-
- /*
- * MSC Bulk In Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_BulkIn (void) {
-
- switch (BulkStage) {
- case MSC_BS_DATA_IN:
- switch (CBW.CB[0]) {
- case SCSI_READ10:
- MSC_MemoryRead();
- break;
- }
- break;
- case MSC_BS_DATA_IN_LAST:
- MSC_SetCSW();
- break;
- case MSC_BS_DATA_IN_LAST_STALL:
- USB_SetStallEP(MSC_EP_IN);
- MSC_SetCSW();
- break;
- case MSC_BS_CSW:
- BulkStage = MSC_BS_CBW;
- break;
- }
- }
-
-
- /*
- * MSC Bulk Out Callback
- * Parameters: None (global variables)
- * Return Value: None
- */
-
- void MSC_BulkOut (void) {
-
- BulkLen = (uint8_t)USB_ReadEP(MSC_EP_OUT, BulkBuf);
- switch (BulkStage) {
- case MSC_BS_CBW:
- MSC_GetCBW();
- break;
- case MSC_BS_DATA_OUT:
- switch (CBW.CB[0]) {
- case SCSI_WRITE10:
- MSC_MemoryWrite();
- break;
- case SCSI_VERIFY10:
- MSC_MemoryVerify();
- break;
- }
- break;
- default:
- USB_SetStallEP(MSC_EP_OUT);
- CSW.bStatus = CSW_PHASE_ERROR;
- MSC_SetCSW();
- break;
- }
- }
|