Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BaseJpegDecode BaseUsbHost FATFileSystem mbed-rtos mbed
Revision 0:98f918e1d528, committed 2013-02-02
- Comitter:
- va009039
- Date:
- Sat Feb 02 01:25:25 2013 +0000
- Commit message:
- first commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseJpegDecode.lib Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/BaseJpegDecode/#d7ee458cacd1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseUsbHost.lib Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/BaseUsbHost/#d931d24c2f81
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/FATFileSystem/#86638c0f65b0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SimpleJpegDecode/SimpleJpegDecode.cpp Sat Feb 02 01:25:25 2013 +0000
@@ -0,0 +1,161 @@
+#include "SimpleJpegDecode.h"
+
+#define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0);
+#define ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+
+
+#define _1_4020 45
+#define _0_3441 11
+#define _0_7139 23
+#define _1_7718 57
+#define _0_0012 0
+
+int adjust(int r) {
+ if (r >= 0) {
+ if (r <= 255) {
+ return r;
+ } else {
+ return 255;
+ }
+ } else {
+ return 0;
+ }
+}
+
+void convYUVtoRGB(uint8_t rgb[], int y, int u, int v)
+{
+ rgb[0] = adjust((y*32 + v*_1_4020)/32 + 128);
+ rgb[1] = adjust((y*32 - u*_0_3441 - v*_0_7139)/32 + 128);
+ rgb[2] = adjust((y*32 + u*_1_7718 - v*_0_0012)/32 + 128);
+}
+
+SimpleJpegDecode::SimpleJpegDecode(uint8_t output_mode)
+{
+ m_output_mode = output_mode;
+ clearOnResult();
+}
+
+
+void SimpleJpegDecode::output(int mcu, int block, int scan, int value)
+{
+ int sc = (block < yblock) ? 0 : 1;
+ inputBLOCK(mcu, block, scan, value * qt[sc][scan]);
+}
+
+void SimpleJpegDecode::outputDC(int mcu, int block, int value)
+{
+ output(mcu, block, 0, value);
+ DC_count++;
+}
+
+void SimpleJpegDecode::outputAC(int mcu, int block, int scan, int value)
+{
+ output(mcu, block, scan, value);
+ AC_count++;
+}
+
+void SimpleJpegDecode::outputMARK(uint8_t c)
+{
+}
+
+void SimpleJpegDecode::format_YUV(int mcu, int block, int8_t* values)
+{
+ if (block < yblock+1) {
+ memcpy(m_block_data[block], values, 64);
+ return;
+ }
+ int mcu_x_count = (width+15)/16;
+ int mcu_x = mcu % mcu_x_count;
+ int mcu_y = mcu / mcu_x_count;
+ uint8_t yuv[3];
+ if (yblock == 2) {
+ for(int y = 0; y < 8; y++) {
+ for(int x = 0; x < 16; x++) {
+ yuv[0] = m_block_data[x/8][y*8+x%8] + 128;
+ yuv[1] = m_block_data[2][y*8+x/2] + 128;
+ yuv[2] = values[y*8+x/2] + 128;
+ onResult(mcu_x * 16 + x, mcu_y * 8 + y, yuv);
+ }
+ }
+ } else if (yblock == 4) {
+ for(int y = 0; y < 16; y++) {
+ for(int x = 0; x < 16; x++) {
+ yuv[0] = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8] + 128;
+ yuv[1] = m_block_data[4][(y/2)*8+x/2] + 128;
+ yuv[2] = values[(y/2)*8+x/2] + 128;
+ onResult(mcu_x * 16 + x, mcu_y * 16 + y, yuv);
+ }
+ }
+ } else {
+ ASSERT(yblock == 2 || yblock == 4);
+ }
+}
+
+void SimpleJpegDecode::format_RGB24(int mcu, int block, int8_t* values)
+{
+ if (block < yblock+1) {
+ memcpy(m_block_data[block], values, 64);
+ return;
+ }
+ int mcu_x_count = (width+15)/16;
+ int mcu_x = mcu % mcu_x_count;
+ int mcu_y = mcu / mcu_x_count;
+ uint8_t rgb[3];
+ if (yblock == 2) {
+ for(int y = 0; y < 8; y++) {
+ for(int x = 0; x < 16; x++) {
+ int8_t yuv_y = m_block_data[x/8][y*8+x%8];
+ int8_t yuv_u = m_block_data[2][y*8+x/2];
+ int8_t yuv_v = values[y*8+x/2];
+ convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v);
+ onResult(mcu_x * 16 + x, mcu_y * 8 + y, rgb);
+ }
+ }
+ } else if (yblock == 4) {
+ for(int y = 0; y < 16; y++) {
+ for(int x = 0; x < 16; x++) {
+ int8_t yuv_y = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8];
+ int8_t yuv_u = m_block_data[4][(y/2)*8+x/2];
+ int8_t yuv_v = values[(y/2)*8+x/2];
+ convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v);
+ onResult(mcu_x * 16 + x, mcu_y * 16 + y, rgb);
+ }
+ }
+ } else {
+ ASSERT(yblock == 2 || yblock == 4);
+ }
+}
+
+void SimpleJpegDecode::outputBLOCK(int mcu, int block, int8_t* values)
+{
+ BLOCK_count++;
+ if (m_output_mode == YUV) {
+ format_YUV(mcu, block, values);
+ } else if (m_output_mode == RGB24) {
+ format_RGB24(mcu, block, values);
+ } else {
+ ASSERT(m_output_mode == YUV || m_output_mode == RGB24);
+ }
+}
+
+void SimpleJpegDecode::onResult(int x, int y, uint8_t* yuv)
+{
+ if(m_pCbItem && m_pCbMeth)
+ (m_pCbItem->*m_pCbMeth)(x, y, yuv);
+ else if(m_pCb)
+ m_pCb(x, y, yuv);
+}
+
+void SimpleJpegDecode::setOnResult( void (*pMethod)(int, int, uint8_t*) )
+{
+ m_pCb = pMethod;
+ m_pCbItem = NULL;
+ m_pCbMeth = NULL;
+}
+
+void SimpleJpegDecode::clearOnResult()
+{
+ m_pCb = NULL;
+ m_pCbItem = NULL;
+ m_pCbMeth = NULL;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SimpleJpegDecode/SimpleJpegDecode.h Sat Feb 02 01:25:25 2013 +0000
@@ -0,0 +1,56 @@
+#ifndef SIMPLE_JPEG_DECODE_H
+#define SIMPLE_JPEG_DECODE_H
+
+#include "BaseJpegDecode.h"
+#include "inverseDCT.h"
+
+#define YUV 0
+#define RGB24 1
+
+class SimpleJpegDecode : public BaseJpegDecode, public inverseDCT {
+public:
+ SimpleJpegDecode(uint8_t output_mode=RGB24);
+
+ void format_YUV(int mcu, int block, int8_t* values);
+ void format_RGB24(int mcu, int block, int8_t* values);
+
+ void output(int mcu, int block, int scan, int value);
+ virtual void outputDC(int mcu, int block, int value);
+ virtual void outputAC(int mcu, int block, int scan, int value);
+ virtual void outputMARK(uint8_t c);
+ virtual void outputBLOCK(int muc, int block, int8_t* values); // iDCT
+
+ int8_t m_block_data[5][64];
+ int DC_count;
+ int AC_count;
+ int BLOCK_count;
+
+ ///Setups the result callback
+ /**
+ @param pMethod : callback function
+ */
+ void setOnResult( void (*pMethod)(int, int, uint8_t*) );
+
+ ///Setups the result callback
+ /**
+ @param pItem : instance of class on which to execute the callback method
+ @param pMethod : callback method
+ */
+ class CDummy;
+ template<class T>
+ void setOnResult( T* pItem, void (T::*pMethod)(int, int, uint8_t*) )
+ {
+ m_pCb = NULL;
+ m_pCbItem = (CDummy*) pItem;
+ m_pCbMeth = (void (CDummy::*)(int, int, uint8_t*)) pMethod;
+ }
+ void clearOnResult();
+protected:
+ void onResult(int x, int y, uint8_t* yuv);
+ CDummy* m_pCbItem;
+ void (CDummy::*m_pCbMeth)(int, int, uint8_t*);
+ void (*m_pCb)(int, int, uint8_t*);
+ uint8_t m_output_mode;
+};
+
+#endif // SIMPLE_JPEG_DECODE_H
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/UsbFlashDrive/UsbFlashDrive.cpp Sat Feb 02 01:25:25 2013 +0000
@@ -0,0 +1,406 @@
+// UsbFlashDrive.cpp 2013/1/25
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+//#define DEBUG
+#include "BaseUsbHostDebug.h"
+#define TEST
+#include "BaseUsbHostTest.h"
+#include "UsbFlashDrive.h"
+
+//#define WRITE_PROTECT
+
+
+uint32_t BE32(uint8_t* d)
+{
+ return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+}
+
+void BE16(uint32_t n, uint8_t* d)
+{
+ d[0] = (uint8_t)(n >> 8);
+ d[1] = (uint8_t)n;
+}
+
+void BE32(uint32_t n, uint8_t* d)
+{
+ d[0] = (uint8_t)(n >> 24);
+ d[1] = (uint8_t)(n >> 16);
+ d[2] = (uint8_t)(n >> 8);
+ d[3] = (uint8_t)n;
+}
+
+UsbFlashDrive::UsbFlashDrive(const char* name, ControlEp* ctlEp): FATFileSystem(name)
+{
+ m_name = name;
+
+ if (ctlEp == NULL) { // root hub
+ DBG_OHCI(LPC_USB->HcRhPortStatus1);
+ TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200);
+ ctlEp = new ControlEp();
+ TEST_ASSERT_TRUE(ctlEp);
+ }
+
+ CTASSERT(sizeof(CBW) == 31);
+ CTASSERT(sizeof(CSW) == 13);
+ TEST_ASSERT(sizeof(CBW) == 31);
+ TEST_ASSERT(sizeof(CSW) == 13);
+
+ m_numBlocks = 0;
+ m_BlockSize = 0;
+ m_lun = 0;
+ m_interface = 0;
+ m_pEpBulkIn = NULL;
+ m_pEpBulkOut = NULL;
+
+ ParseConfiguration(ctlEp);
+ int rc = ctlEp->SetConfiguration(1);
+ TEST_ASSERT_EQUAL(rc, USB_OK);
+ GetMaxLUN(ctlEp);
+ setup(ctlEp);
+}
+
+bool UsbFlashDrive::check(ControlEp* ctlEp)
+{
+ if (ctlEp == NULL) {
+ return false;
+ }
+ CTASSERT(sizeof(StandardDeviceDescriptor) == 18);
+ CTASSERT(sizeof(StandardConfigurationDescriptor) == 9);
+ CTASSERT(sizeof(StandardInterfaceDescriptor) == 9);
+ TEST_ASSERT(sizeof(StandardDeviceDescriptor) == 18);
+ TEST_ASSERT(sizeof(StandardConfigurationDescriptor) == 9);
+ TEST_ASSERT(sizeof(StandardInterfaceDescriptor) == 9);
+
+ StandardDeviceDescriptor desc;
+ int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_DEVICE, 0, reinterpret_cast<uint8_t*>(&desc), sizeof(StandardDeviceDescriptor));
+ if (rc != USB_OK) {
+ return false;
+ }
+ if (desc.bDeviceClass == 8) {
+ return true;
+ } else if (desc.bDeviceClass != 0x00) {
+ return false;
+ }
+ uint8_t temp[4];
+ rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp));
+ if (rc != USB_OK) {
+ return false;
+ }
+ StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp);
+ uint8_t* buf = new uint8_t[cfg->wTotalLength];
+
+ rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength);
+ if (rc != USB_OK) {
+ return false;
+ }
+ DBG_HEX(buf, cfg->wTotalLength);
+ bool ret = false;
+ for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) {
+ StandardInterfaceDescriptor* desc = reinterpret_cast<StandardInterfaceDescriptor*>(buf+pos);
+ if (desc->bDescriptorType == 4) { // interface ?
+ if (desc->bInterfaceClass == 8 && desc->bInterfaceSubClass == 6 && desc->bInterfaceProtocol == 0x50) {
+ ret = true;
+ }
+ break;
+ }
+ }
+ delete[] buf;
+ return ret;
+}
+
+int UsbFlashDrive::disk_initialize()
+{
+ //DBG("m_BlockSize=%d\n", m_BlockSize);
+ if (m_BlockSize != 512) {
+ return 1;
+ }
+ return 0;
+}
+
+int UsbFlashDrive::disk_write(const uint8_t* buffer, uint64_t sector)
+{
+ m_report_disk_write++;
+ //DBG("buffer=%p block_number=%d\n", buffer, sector);
+ int ret = MS_BulkSend(sector, 1, buffer);
+ if (ret >= 0) {
+ return 0;
+ }
+ return 1;
+}
+
+int UsbFlashDrive::disk_read(uint8_t* buffer, uint64_t sector)
+{
+ m_report_disk_read++;
+ //DBG("buffer=%p block_number=%d\n", buffer, sector);
+ int ret = MS_BulkRecv(sector, 1, buffer);
+ if (ret >= 0) {
+ return 0;
+ }
+ return 1;
+}
+
+int UsbFlashDrive::disk_status()
+{
+ m_report_disk_status++;
+ return 0;
+}
+
+int UsbFlashDrive::disk_sync()
+{
+ m_report_disk_sync++;
+ return 0;
+}
+
+uint64_t UsbFlashDrive::disk_sectors()
+{
+ DBG("m_numBlocks=%d\n", m_numBlocks);
+ return m_numBlocks;
+}
+
+int UsbFlashDrive::setup(ControlEp* ctlEp, int timeout)
+{
+
+ int retry = 0;
+ Timer t;
+ t.start();
+ t.reset();
+ while(t.read_ms() < timeout) {
+ DBG("retry=%d t=%d\n", retry, t.read_ms());
+ if (retry > 80) {
+ return -1;
+ }
+ int rc = TestUnitReady();
+ DBG("TestUnitReady(): %d\n", rc);
+ if (rc == USB_OK) {
+ DBG("m_CSW.bCSWStatus: %02X\n", m_CSW.bCSWStatus);
+ if (m_CSW.bCSWStatus == 0x00) {
+ break;
+ }
+ }
+ GetSenseInfo();
+ retry++;
+ wait_ms(50);
+ }
+ if (t.read_ms() >= timeout) {
+ return -1;
+ }
+ ReadCapacity();
+ Inquire();
+ return 0;
+}
+
+int UsbFlashDrive::ParseConfiguration(ControlEp* ctlEp)
+{
+ TEST_ASSERT(ctlEp);
+ TEST_ASSERT(sizeof(StandardEndpointDescriptor) == 7);
+ uint8_t temp[4];
+ int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp));
+ if (rc != USB_OK) {
+ return rc;
+ }
+ StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp);
+ uint8_t* buf = new uint8_t[cfg->wTotalLength];
+ rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength);
+ if (rc != USB_OK) {
+ return rc;
+ }
+ DBG_HEX(buf, cfg->wTotalLength);
+ for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) {
+ StandardEndpointDescriptor* desc = reinterpret_cast<StandardEndpointDescriptor*>(buf+pos);
+ if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT) {
+ if (desc->bmAttributes == 2) { // bulk
+ BulkEp* pEp = new BulkEp(ctlEp->GetAddr(), desc->bEndpointAddress, desc->wMaxPacketSize);
+ if (desc->bEndpointAddress & 0x80) {
+ m_pEpBulkIn = pEp;
+ } else {
+ m_pEpBulkOut = pEp;
+ }
+ }
+ }
+ }
+ delete[] buf;
+ if (m_pEpBulkIn && m_pEpBulkOut) {
+ return USB_OK;
+ }
+ return USB_ERROR;
+}
+
+int UsbFlashDrive::BulkOnlyMassStorageReset(ControlEp* ctlEp)
+{
+ TEST_ASSERT(ctlEp);
+ int rc = ctlEp->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0);
+ TEST_ASSERT(rc == USB_OK);
+ return rc;
+}
+
+int UsbFlashDrive::GetMaxLUN(ControlEp* ctlEp)
+{
+ TEST_ASSERT(ctlEp);
+ TEST_ASSERT(m_interface == 0);
+ uint8_t temp[1];
+ int rc = ctlEp->controlReceive(0xa1, 0xfe, 0x0000, m_interface, temp, sizeof(temp));
+ TEST_ASSERT(rc == USB_OK);
+ DBG_BYTES("GetMaxLUN", temp, sizeof(temp));
+ m_MaxLUN = temp[0];
+ TEST_ASSERT(m_MaxLUN <= 15);
+ return rc;
+}
+
+
+int UsbFlashDrive::TestUnitReady()
+{
+ const uint8_t cdb[6] = {SCSI_CMD_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00};
+ m_CBW.dCBWDataTraansferLength = 0;
+ m_CBW.bmCBWFlags = 0x00;
+ CommandTransport(cdb, sizeof(cdb));
+ StatusTransport();
+ return 0;
+}
+
+int UsbFlashDrive::GetSenseInfo()
+{
+ const uint8_t cdb[6] = {SCSI_CMD_REQUEST_SENSE, 0x00, 0x00, 0x00, 18, 0x00};
+ m_CBW.dCBWDataTraansferLength = 18;
+ m_CBW.bmCBWFlags = 0x80; // data In
+ CommandTransport(cdb, sizeof(cdb));
+
+ uint8_t buf[18];
+ _bulkRecv(buf, sizeof(buf));
+ DBG_HEX(buf, sizeof(buf));
+
+ StatusTransport();
+ TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
+ return 0;
+}
+
+int UsbFlashDrive::ReadCapacity()
+{
+ const uint8_t cdb[10] = {SCSI_CMD_READ_CAPACITY, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00};
+ m_CBW.dCBWDataTraansferLength = 8;
+ m_CBW.bmCBWFlags = 0x80; // data In
+ CommandTransport(cdb, sizeof(cdb));
+
+ uint8_t buf[8];
+ int rc = _bulkRecv(buf, sizeof(buf));
+ TEST_ASSERT(rc >= 0);
+ DBG_HEX(buf, sizeof(buf));
+
+ StatusTransport();
+ TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
+
+ m_numBlocks = BE32(buf);
+ m_BlockSize = BE32(buf+4);
+ DBG("m_numBlocks=%d m_BlockSize=%d\n", m_numBlocks, m_BlockSize);
+ TEST_ASSERT(m_BlockSize == 512);
+ TEST_ASSERT(m_numBlocks > 0);
+ return 0;
+}
+
+int UsbFlashDrive::Inquire()
+{
+ const uint8_t cdb[6] = {SCSI_CMD_INQUIRY, 0x00, 0x00, 0x00, 36, 0x00};
+ m_CBW.dCBWDataTraansferLength = 36;
+ m_CBW.bmCBWFlags = 0x80; // data In
+ CommandTransport(cdb, sizeof(cdb));
+
+ uint8_t buf[36];
+ int rc = _bulkRecv(buf, sizeof(buf));
+ TEST_ASSERT(rc >= 0);
+ DBG_HEX(buf, sizeof(buf));
+
+ StatusTransport();
+ return 0;
+}
+
+int UsbFlashDrive::MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer)
+{
+ TEST_ASSERT(m_BlockSize == 512);
+ TEST_ASSERT(num_blocks == 1);
+ TEST_ASSERT(user_buffer);
+ uint8_t cdb[10] = {SCSI_CMD_READ_10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00};
+ BE32(block_number, cdb+2);
+ BE16(num_blocks, cdb+7);
+ uint32_t len = m_BlockSize * num_blocks;
+ TEST_ASSERT(len <= 512);
+ m_CBW.dCBWDataTraansferLength = len;
+ m_CBW.bmCBWFlags = 0x80; // data In
+ CommandTransport(cdb, sizeof(cdb));
+
+ int ret = _bulkRecv(user_buffer, len);
+ //DBG_HEX(user_buffer, len);
+
+ StatusTransport();
+ TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
+ return ret;
+}
+
+int UsbFlashDrive::MS_BulkSend(uint32_t block_number, int num_blocks, const uint8_t* user_buffer)
+{
+#ifdef WRITE_PROTECT
+ return 0;
+#else
+ TEST_ASSERT(num_blocks == 1);
+ TEST_ASSERT(user_buffer);
+ uint8_t cdb[10] = {SCSI_CMD_WRITE_10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00};
+ BE32(block_number, cdb+2);
+ BE16(num_blocks, cdb+7);
+ uint32_t len = m_BlockSize * num_blocks;
+ TEST_ASSERT(len <= 512);
+ m_CBW.dCBWDataTraansferLength = len;
+ m_CBW.bmCBWFlags = 0x00; // data Out
+ CommandTransport(cdb, sizeof(cdb));
+
+ int ret = _bulkSend(user_buffer, len);
+ //DBG_HEX(user_buffer, len);
+
+ StatusTransport();
+ TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
+ return ret;
+#endif //WRITE_PROTECT
+}
+
+int UsbFlashDrive::CommandTransport(const uint8_t* cdb, int size)
+{
+ TEST_ASSERT(cdb);
+ TEST_ASSERT(size >= 6);
+ TEST_ASSERT(size <= 16);
+ m_CBW.bCBWLUN = m_lun;
+ m_CBW.bCBWCBLength = size;
+ memcpy(m_CBW.CBWCB, cdb, size);
+
+ m_CBW.dCBWSignature = 0x43425355;
+ m_CBW.dCBWTag = m_tag++;
+ m_CBW.bCBWLUN = 0;
+ //DBG_HEX((uint8_t*)&m_CBW, sizeof(CBW));
+ int rc = _bulkSend((uint8_t*)&m_CBW, sizeof(CBW));
+ return rc;
+}
+
+int UsbFlashDrive::StatusTransport()
+{
+ TEST_ASSERT(sizeof(CSW) == 13);
+ int rc = _bulkRecv((uint8_t*)&m_CSW, sizeof(CSW));
+ //DBG_HEX((uint8_t*)&m_CSW, sizeof(CSW));
+ TEST_ASSERT(m_CSW.dCSWSignature == 0x53425355);
+ TEST_ASSERT(m_CSW.dCSWTag == m_CBW.dCBWTag);
+ TEST_ASSERT(m_CSW.dCSWDataResidue == 0);
+ return rc;
+}
+
+int UsbFlashDrive::_bulkRecv(uint8_t* buf, int size)
+{
+ TEST_ASSERT(m_pEpBulkIn);
+ int ret = m_pEpBulkIn->bulkReceive(buf, size);
+ return ret;
+}
+
+int UsbFlashDrive::_bulkSend(const uint8_t* buf, int size)
+{
+ TEST_ASSERT(m_pEpBulkOut);
+ int ret = m_pEpBulkOut->bulkSend(buf, size);
+ return ret;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/UsbFlashDrive/UsbFlashDrive.h Sat Feb 02 01:25:25 2013 +0000
@@ -0,0 +1,75 @@
+// usbFlashDrive.h 2013/1/8
+#pragma once
+
+#include "FATFileSystem.h"
+
+#define SCSI_CMD_REQUEST_SENSE 0x03
+#define SCSI_CMD_TEST_UNIT_READY 0x00
+#define SCSI_CMD_INQUIRY 0x12
+#define SCSI_CMD_READ_10 0x28
+#define SCSI_CMD_READ_CAPACITY 0x25
+#define SCSI_CMD_WRITE_10 0x2A
+
+#pragma pack(push,1)
+struct CBW {
+ uint32_t dCBWSignature;
+ uint32_t dCBWTag;
+ uint32_t dCBWDataTraansferLength;
+ uint8_t bmCBWFlags;
+ uint8_t bCBWLUN;
+ uint8_t bCBWCBLength;
+ uint8_t CBWCB[16];
+};
+
+struct CSW {
+ uint32_t dCSWSignature;
+ uint32_t dCSWTag;
+ uint32_t dCSWDataResidue;
+ uint8_t bCSWStatus;
+};
+#pragma pack(pop)
+
+class UsbFlashDrive : public FATFileSystem {
+public:
+ UsbFlashDrive(const char* name, ControlEp* ctlEp = NULL);
+ static bool check(ControlEp* ctlEp);
+ virtual int disk_initialize();
+ virtual int disk_write(const uint8_t* buffer, uint64_t sector);
+ virtual int disk_read(uint8_t* buffer, uint64_t sector);
+ virtual int disk_status();
+ virtual int disk_sync();
+ virtual uint64_t disk_sectors();
+private:
+ int setup(ControlEp* ctlEp, int timeout = 9000);
+ int ParseConfiguration(ControlEp* ctlEp);
+ int BulkOnlyMassStorageReset(ControlEp* ctlEp);
+ int GetMaxLUN(ControlEp* ctlEp);
+ int ReadCapacity();
+ int GetSenseInfo();
+ int TestUnitReady();
+ int Inquire();
+ int MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer);
+ int MS_BulkSend(uint32_t block_number, int num_blocks, const uint8_t* user_buffer);
+ int CommandTransport(const uint8_t* cdb, int size);
+ int StatusTransport();
+ int _bulkRecv(uint8_t* buf, int size);
+ int _bulkSend(const uint8_t* buf, int size);
+ const char* m_name;
+ int m_drive;
+ uint32_t m_numBlocks;
+ int m_BlockSize;
+ int m_lun;
+ int m_MaxLUN;
+ int m_interface;
+ uint32_t m_tag;
+ CBW m_CBW;
+ CSW m_CSW;
+ // endpoint
+ BulkEp* m_pEpBulkIn;
+ BulkEp* m_pEpBulkOut;
+ // report
+ uint32_t m_report_disk_write;
+ uint32_t m_report_disk_read;
+ uint32_t m_report_disk_status;
+ uint32_t m_report_disk_sync;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bmp24.h Sat Feb 02 01:25:25 2013 +0000
@@ -0,0 +1,66 @@
+#ifndef BMP24_H
+#define BMP24_H
+
+#define BMP24_WIDTH (16*4)
+#define BMP24_HEIGHT (16*3)
+
+class bmp24 {
+ uint8_t m_bitmap[BMP24_WIDTH*BMP24_HEIGHT*3];
+public:
+ int width;
+ int height;
+
+ bmp24() {
+ width = BMP24_WIDTH;
+ height = BMP24_HEIGHT;
+ }
+
+ void clear() {
+ memset(m_bitmap, 0, sizeof(m_bitmap));
+ }
+
+ void point(int x, int y, uint8_t* rgb) {
+ if (x >= 0 && x < width && y >= 0 && y < height) {
+ int pos = y*width*3+x*3;
+ m_bitmap[pos++] = rgb[0];
+ m_bitmap[pos++] = rgb[1];
+ m_bitmap[pos] = rgb[2];
+ }
+ }
+
+ void LE32write(uint8_t* buf, int value) {
+ *buf++ = value & 0xff;
+ *buf++ = (value>>8) & 0xff;
+ *buf++ = (value>>16) & 0xff;
+ *buf = (value>>24) & 0xff;
+ }
+
+ bool writeFile(const char *path) {
+ FILE *fp = fopen(path, "wb");
+ if (fp == NULL) {
+ return false;
+ }
+ uint8_t header[] = {
+0x42,0x4d,0x36,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
+0x00,0x00,0xa0,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00};
+ int file_size = sizeof(header) + sizeof(m_bitmap);
+ LE32write(header+2, file_size);
+ LE32write(header+18, width);
+ LE32write(header+22, height);
+
+ fwrite(header, 1, sizeof(header), fp);
+ for(int y = height-1; y >=0; y--) {
+ for(int x = 0; x < width; x++) {
+ fputc(m_bitmap[y*width*3+x*3+2], fp);
+ fputc(m_bitmap[y*width*3+x*3+1], fp);
+ fputc(m_bitmap[y*width*3+x*3+0], fp);
+ }
+ }
+ fclose(fp);
+ return true;
+ }
+};
+
+#endif // BMP24_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Sat Feb 02 01:25:25 2013 +0000
@@ -0,0 +1,57 @@
+// SimpleJpegDecode_example/main.cpp 2013/2/2
+// convert jpeg to bmp
+//
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#include "SimpleJpegDecode.h"
+#include "UsbFlashDrive.h"
+#include "bmp24.h"
+
+#define INPUT_FILE "/usb/input.jpg"
+#define OUTPUT_FILE "/usb/output.bmp"
+
+Serial pc(USBTX, USBRX);
+
+SimpleJpegDecode decode;
+bmp24 bmp;
+
+void callbackRGB(int x, int y, uint8_t* rgb)
+{
+ bmp.point(x, y, rgb);
+}
+
+int main() {
+ pc.baud(921600);
+ printf("%s\n", __FILE__);
+
+ BaseUsbHost* usbHost = new BaseUsbHost();
+ ControlEp* ctlEp = new ControlEp; // root hub
+ if (UsbHub::check(ctlEp)) {
+ UsbHub* hub = new UsbHub(ctlEp);
+ ctlEp = hub->search<UsbFlashDrive>();
+ }
+ if (!UsbFlashDrive::check(ctlEp)) {
+ error("USB flash drive is not connected.\n");
+ }
+ UsbFlashDrive* drive = new UsbFlashDrive("usb", ctlEp);
+
+ bmp.clear();
+ decode.setOnResult(callbackRGB);
+ decode.clear();
+ printf("input: %s\n", INPUT_FILE);
+ FILE* fp = fopen(INPUT_FILE, "rb");
+ if (fp == NULL) {
+ error("open error\n");
+ }
+ while(!feof(fp)) {
+ int c = fgetc(fp);
+ decode.input(c);
+ }
+ fclose(fp);
+ printf("output: %s\n", OUTPUT_FILE);
+ if (!bmp.writeFile(OUTPUT_FILE)) {
+ error("write error\n");
+ }
+ exit(1);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#53e6cccd8782
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/0954ebd79f59 \ No newline at end of file