BaseUsbHost example program
Dependencies: BaseUsbHost FATFileSystem mbed mbed-rtos
Revision 0:2a9734a95d55, committed 2012-12-04
- Comitter:
- va009039
- Date:
- Tue Dec 04 13:39:57 2012 +0000
- Child:
- 1:80205a2de336
- Commit message:
- first commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseJpegDecode.lib Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/BaseJpegDecode/#a7547692071d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseUsbHost.lib Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/BaseUsbHost/#b7d6879637a8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetInterface.lib Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/EthernetInterface/#a0ee3ae75cfa
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/FATFileSystem/#b6669c987c8e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LogitechC270/LogitechC270.cpp Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,157 @@ +// LogitechC270.cpp 2012/12/4 +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#define DEBUG +#include "BaseUsbHostDebug.h" +#define TEST +#include "BaseUsbHostTest.h" +#include "LogitechC270.h" + +LogitechC270::LogitechC270(int frame, uint32_t interval, ControlEp* ctlEp) +{ + uint8_t buf[26]; + + if (ctlEp == NULL) { // root hub + DBG_OHCI(LPC_USB->HcRhPortStatus1); + TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200); + m_ctlEp = new ControlEp(); + TEST_ASSERT_TRUE(m_ctlEp); + } else { + m_ctlEp = ctlEp; + } + + int r = m_ctlEp->GetDescriptor(1, 0, buf, 18); + TEST_ASSERT(r == USB_OK); + DBG_HEX(buf, 18); + vid = *reinterpret_cast<uint16_t*>(buf+8); + pid = *reinterpret_cast<uint16_t*>(buf+10); + DBG("VID PID: %04X %04X\n", vid, pid); + TEST_ASSERT(vid == 0x046d && pid == 0x0825); + int addr = m_ctlEp->GetAddr(); + DBG("addr: %d\n", addr); + + m_isoEp = new IsochronousEp(addr, 0x81, 192); + TEST_ASSERT_TRUE(m_isoEp); + + int rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, buf, 1); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_INFO Prob", buf, 1); + + rc = Control(GET_DEF, VS_PROBE_CONTROL, 1, buf, 26); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_DEF Probe", buf, 26); + + rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, buf, 26); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_MIN Probe", buf, 26); + + rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, buf, 26); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_MAX Probe", buf, 26); + + rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, buf, 26); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_CUR Probe", buf, 26); + + memset(buf, 0, 26); + buf[2] = C270_MJPEG; + buf[3] = frame; + *reinterpret_cast<uint32_t*>(buf+4) = interval; + + DBG_BYTES("SET_CUR Commit", buf, 26); + rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, 26); + TEST_ASSERT(rc == USB_OK); + + rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, 26); + TEST_ASSERT(rc == USB_OK); + TEST_ASSERT_EQUAL(buf[2], C270_MJPEG); + TEST_ASSERT_EQUAL(buf[3], frame); + TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval); + DBG_BYTES("GET_CUR Commit", buf, 26); + + int cfg; + rc = m_ctlEp->GetConfiguration(&cfg); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("config: %d\n", cfg); + + rc = m_ctlEp->SetConfiguration(1); + TEST_ASSERT_EQUAL(rc, USB_OK); + + rc = m_ctlEp->GetConfiguration(&cfg); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("config: %d\n", cfg); + TEST_ASSERT_EQUAL(cfg, 1); + + int alt; + rc = m_ctlEp->GetInterface(1, &alt); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("alt: %d\n", alt); + + rc = m_ctlEp->SetInterfaceAlternate(1, 1); // alt=1 packet size = 192 + TEST_ASSERT_EQUAL(rc, USB_OK); + + rc = m_ctlEp->GetInterface(1, &alt); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("alt: %d\n", alt); + TEST_ASSERT_EQUAL(alt, 1); + + for(int i = 0; i < 16; i++) { + report_cc_count[i] = 0; + report_ps_cc_count[i] = 0; + } + + LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable + LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable +} + +void LogitechC270::poll() +{ + HCITD* itd = m_isoEp->read(); + if (itd) { + uint8_t cc = itd->Control>>28; + report_cc_count[cc]++; + if (cc == 0) { // ConditionCode + //DBG_ITD(itd); + uint16_t frame = itd->Control & 0xffff; + uint8_t* buf = const_cast<uint8_t*>(itd->buf); + int mps = m_isoEp->m_PacketSize; + for(int i = 0; i < m_isoEp->m_FrameCount; i++) { + uint16_t pswn = itd->OffsetPSW[i]; + cc = pswn>>12; + if (cc == 0 || cc == 9) { + int len = pswn & 0x7ff; + onResult(frame, buf, len); + } + report_ps_cc_count[cc]++; + buf += mps; + frame++; + } + } + m_isoEp->delete_HCTD(reinterpret_cast<HCTD*>(itd)); + } +} + +int LogitechC270::Control(int req, int cs, int index, uint8_t* buf, int size) +{ + TEST_ASSERT(m_ctlEp); + int rc; + if (req == SET_CUR) { + rc = m_ctlEp->controlSend( + USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, + req, cs<<8, index, buf, size); + return rc; + } + rc = m_ctlEp->controlReceive( + USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, + req, cs<<8, index, buf, size); + return rc; +} + +void LogitechC270::onResult(uint16_t frame, uint8_t* buf, int len) +{ + if(m_pCbItem && m_pCbMeth) + (m_pCbItem->*m_pCbMeth)(frame, buf, len); + else if(m_pCb) + m_pCb(frame, buf, len); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LogitechC270/LogitechC270.h Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,77 @@ +#ifndef LOGITECH_C270_H +#define LOGITECH_C270_H + +#define C270_160x120 2 +#define C270_176x144 3 +#define C270_320x176 4 +#define C270_320x240 5 +#define C270_352x288 6 +#define C270_432x240 7 +#define C270_640x480 1 +#define C270_544x288 8 +#define C270_640x360 9 +#define C270_752x416 10 +#define C270_800x448 11 +#define C270_800x600 12 + +#define _30FPS 333333 +#define _25FPS 400000 +#define _20FPS 500000 +#define _15FPS 666666 +#define _10FPS 1000000 +#define _5FPS 2000000 + +#define C270_MJPEG 2 +#define C270_YUV2 1 + +#define SET_CUR 0x01 +#define GET_CUR 0x81 +#define GET_MIN 0x82 +#define GET_MAX 0x83 +#define GET_RES 0x84 +#define GET_LEN 0x85 +#define GET_INFO 0x86 +#define GET_DEF 0x87 + +#define VS_PROBE_CONTROL 0x01 +#define VS_COMMIT_CONTROL 0x02 + +class LogitechC270 { +public: + LogitechC270(int frame = C270_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL); + void poll(); + int Control(int req, int cs, int index, uint8_t* buf, int size); + uint16_t vid; + uint16_t pid; + ControlEp* m_ctlEp; + IsochronousEp* m_isoEp; + uint32_t report_cc_count[16]; // ConditionCode + uint32_t report_ps_cc_count[16]; // Packt Status ConditionCode + // callback + void onResult(uint16_t frame, uint8_t* buf, int len); + void setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) ) + { + m_pCb = pMethod; + m_pCbItem = NULL; + m_pCbMeth = NULL; + } + + class CDummy; + template<class T> + void setOnResult( T* pItem, void (T::*pMethod)(uint16_t, uint8_t*, int) ) + { + m_pCb = NULL; + m_pCbItem = (CDummy*) pItem; + m_pCbMeth = (void (CDummy::*)(uint16_t, uint8_t*, int)) pMethod; + } + void clearOnResult() + { + m_pCb = NULL; + m_pCbItem = NULL; + m_pCbMeth = NULL; + } + CDummy* m_pCbItem; + void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int); + void (*m_pCb)(uint16_t, uint8_t*, int); +}; +#endif //LOGITECH_C270_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Terminal.lib Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/cbayley/code/Terminal/#543e8e498e09
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UsbFlashDrive/UsbFlashDrive.cpp Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,388 @@ +// UsbFlashDrive.cpp 2012/12/4 +#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 + +int LE16(const uint8_t* d) +{ + return d[0] | (d[1] << 8); +} + +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); + m_ctlEp = new ControlEp(); + TEST_ASSERT_TRUE(m_ctlEp); + } else { + m_ctlEp = ctlEp; + } + + 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(); + int rc = m_ctlEp->SetConfiguration(1); + TEST_ASSERT_EQUAL(rc, USB_OK); + GetMaxLUN(); + setup(); +} + +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(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() +{ + int rc; + uint8_t ConfigDesc[9]; + int index = 0; + TEST_ASSERT(m_ctlEp); + rc = m_ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, ConfigDesc, sizeof(ConfigDesc)); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("ConfigDescriptor 9bytes", ConfigDesc, sizeof(ConfigDesc)); + TEST_ASSERT(ConfigDesc[0] == 9); + TEST_ASSERT(ConfigDesc[1] == 0x02); + int wTotalLength = *((uint16_t*)&ConfigDesc[2]); + DBG("TotalLength: %d\n", wTotalLength); + int bConfigValue = ConfigDesc[5]; + TEST_ASSERT(bConfigValue == 1); + DBG("ConfigValue: %d\n", bConfigValue); + DBG("MaxPower: %d mA\n", ConfigDesc[8]*2); + + uint8_t* buf = new uint8_t[wTotalLength]; + TEST_ASSERT(buf); + rc = m_ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength); + TEST_ASSERT(rc == USB_OK); + TEST_ASSERT(ConfigDesc[1] == 0x02); + for (int pos = 0; pos < wTotalLength; pos += buf[pos]) { + DBG_BYTES("CFG", buf+pos, buf[pos]); + int type = buf[pos+1]; + if (USB_DESCRIPTOR_TYPE_INTERFACE == type) { // 0x04 + DBG("InterfaceNumber: %d\n", buf[pos+2]); + DBG("AlternateSetting: %d\n", buf[pos+3]); + DBG("NumEndpoint: %d\n", buf[pos+4]); + DBG("InterfaceClass: %02X\n", buf[pos+5]); + DBG("InterfaceSubClass: %02X\n", buf[pos+6]); + DBG("InterfaceProtocol: %02X\n", buf[pos+7]); + TEST_ASSERT(buf[pos+6] == 0x06); // SCSI + TEST_ASSERT(buf[pos+7] == 0x50); // bulk only + } + if (USB_DESCRIPTOR_TYPE_ENDPOINT == type) { + TEST_ASSERT(buf[pos] == 7); + uint8_t att = buf[pos+3]; + if (att == 2) { // bulk + uint8_t ep = buf[pos+2]; + bool dir = ep & 0x80; // true=IN + uint16_t size = LE16(buf+pos+4); + DBG("EndpointAddress: %02X\n", ep); + DBG("Attribute: %02X\n", att); + DBG("MaxPacketSize: %d\n", size); + BulkEp* pEp = new BulkEp(m_ctlEp->GetAddr(), ep, size); + TEST_ASSERT(pEp); + if (dir) { + m_pEpBulkIn = pEp; + } else { + m_pEpBulkOut = pEp; + } + } + } + } + delete[] buf; + TEST_ASSERT(m_pEpBulkIn); + TEST_ASSERT(m_pEpBulkOut); + return 0; +} + +int UsbFlashDrive::BulkOnlyMassStorageReset() +{ + TEST_ASSERT(m_ctlEp); + int rc = m_ctlEp->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); + TEST_ASSERT(rc == USB_OK); + return rc; +} + +int UsbFlashDrive::GetMaxLUN() +{ + TEST_ASSERT(m_interface == 0); + uint8_t temp[1]; + TEST_ASSERT(m_ctlEp); + int rc = m_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->read(buf, size); + return ret; +} + +int UsbFlashDrive::_bulkSend(const uint8_t* buf, int size) +{ + TEST_ASSERT(m_pEpBulkOut); + int ret = m_pEpBulkOut->write(buf, size); + return ret; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UsbFlashDrive/UsbFlashDrive.h Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,78 @@ +// usbFlashDrive.h 2012/12/4 +#ifndef USB_FLASH_DRIVE_H +#define USB_FLASH_DRIVE_H + +#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) +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTraansferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +} CBW; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +} CSW; +#pragma pack(pop) + +class UsbFlashDrive : public FATFileSystem { +public: + UsbFlashDrive(const char* name, ControlEp* ctlEp = NULL); + 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(); + + int setup(int timeout = 9000); +private: + int ParseConfiguration(); + int BulkOnlyMassStorageReset(); + int GetMaxLUN(); + 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; + ControlEp* m_ctlEp; + 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; +}; + +#endif // USB_FLASH_DRIVE_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UsbMouseHost/UsbMouseHost.cpp Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,42 @@ +// UsbMouseHost.cpp +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +//#define DEBUG +#include "BaseUsbHostDebug.h" +#define TEST +#include "BaseUsbHostTest.h" +#include "UsbMouseHost.h" + +UsbMouseHost::UsbMouseHost(ControlEp* ctlEp) +{ + if (ctlEp == NULL) { // root hub + DBG_OHCI(LPC_USB->HcRhPortStatus1); + int lowSpeed = 0; + if (LPC_USB->HcRhPortStatus1 & 0x200) { + lowSpeed = 1; + } + m_ctlEp = new ControlEp(lowSpeed); + TEST_ASSERT_TRUE(m_ctlEp); + } else { + m_ctlEp = ctlEp; + } + + int rc = m_ctlEp->SetConfiguration(1); + TEST_ASSERT_EQUAL(rc, USB_OK); + + int addr = m_ctlEp->GetAddr(); + int lowSpeed = m_ctlEp->GetLowSpeed(); + m_intEp = new InterruptEp(addr, 0x81, 8, lowSpeed); + TEST_ASSERT_TRUE(m_intEp); +} + +int UsbMouseHost::read(uint32_t* status, int millisec) +{ + int rc = m_intEp->read(reinterpret_cast<uint8_t*>(status), 4, millisec); + if (rc < 0) { // error? + *status = 0x00000000; + return rc; + } + return USB_OK; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UsbMouseHost/UsbMouseHost.h Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,13 @@ +// UsbMouseHost.h +#ifndef USB_MOUSE_HOST_H +#define USB_MOUSE_HOST_H + +class UsbMouseHost { +public: + UsbMouseHost(ControlEp* ctlEp = NULL); + int read(uint32_t* status, int millisec=osWaitForever); + ControlEp* m_ctlEp; + InterruptEp* m_intEp; +}; + +#endif //USB_MOUSE_HOST_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example1_LogitechC270.cpp Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,153 @@ +#if 1 +// +// simple color tracking +// +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#define DEBUG +#include "BaseUsbHostDebug.h" +#define TEST +#include "BaseUsbHostTest.h" +#include "LogitechC270.h" +#include "BaseJpegDecode.h" +#include "Terminal.h" + +// Logitech C270 +#define WIDTH 160 +#define HEIGHT 120 + +#define THRESHOLD 200 + +DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); +Terminal term(USBTX, USBRX); + +class CalcCenter : public BaseJpegDecode { +public: + int y_center, x_center; + int m_x_sum, m_y_sum, m_sum; + uint32_t EOI_count; + int16_t m_buf[WIDTH/16*HEIGHT/8]; + CalcCenter():EOI_count(0) { + memset(m_buf, 0, sizeof(m_buf)); + } + virtual void outputDC(int mcu, int block, int value) { + if (mcu >= (WIDTH/16*HEIGHT/8)) { + return; + } + if (block == 3) { // 0-1:Y 2:Cb 3:Cr + value *= qt[1][0]; + m_buf[mcu] = value; // debug + if (value >= THRESHOLD) { // red + m_x_sum += value*(mcu%(WIDTH/16)); + m_y_sum += value*(mcu/(WIDTH/16)); + m_sum += value; + } + } + } + virtual void outputAC(int mcu, int block, int scan, int value){}; + virtual void outputMARK(uint8_t c){ + if (c == 0xd9) { // EOI + if(m_sum == 0) { + x_center = y_center = -1; // not found + } else { + x_center = m_x_sum / m_sum; + y_center = m_y_sum / m_sum; + } + m_x_sum = m_y_sum = m_sum = 0; // reset + EOI_count++; + led3 = !led3; + } + }; +}; + +CalcCenter* calc = NULL; +void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) +{ + if (calc) { + calc->input(buf+12, len-12); + } + if (buf[1]&1) { // FID + led1 = !led1; + } +} + +BaseUsbHost *UsbHost; +UsbHub* hub; +ControlEp* ctlEp = NULL; +LogitechC270* cam; + +void display_thread(void const *args) { + Timer t; + term.cls(); + int fg, old_fg = 0xffffff; + while(1) { + int y; + for(y = 0; y < HEIGHT/8; y++) { + term.locate(0, y); + for(int x = 0; x < WIDTH/16; x++) { + int value = calc->m_buf[y*WIDTH/16+x]; + if (value >= THRESHOLD) { + fg = 0xff0000; // red + } else { + fg = 0xffffff; // white + } + if (fg != old_fg) { + term.foreground(fg); + old_fg = fg; + } + term.printf("%+4d,", value); + } + } + term.locate(0, y); + term.printf("Cr:(%d,%d)[width=%d height=%d yblock=%d %u %u]\n", + calc->x_center, calc->y_center, calc->width, calc->height, calc->yblock, calc->EOI_count, t.read_ms()/1000); + term.printf("[CC:"); + for(int i = 0; i < 16; i++) { + term.printf(" %u", cam->report_cc_count[i]); + } + term.printf("]\n"); + term.printf("[PS:"); + for(int i = 0; i < 16; i++) { + term.printf(" %u", cam->report_ps_cc_count[i]); + } + term.printf("]\n"); + Thread::wait(200); + //Thread::signal_wait(1, 2000); + led2 = !led2; + } +} + +int main() { + term.baud(921600); + term.printf("%s\n", __FILE__); + + calc = new CalcCenter; + TEST_ASSERT(calc); + + UsbHost = new BaseUsbHost; + TEST_ASSERT_TRUE(UsbHost); + + UsbHub* hub = new UsbHub(); + TEST_ASSERT_TRUE(hub); + + for(int i = 0; i < 4; i++) { + if (hub->PortEp[i]) { + if (hub->PortEp[i]->DeviceClass == 0x02) { + ctlEp = hub->PortEp[i]; + break; + } + } + } + + cam = new LogitechC270(C270_160x120, _15FPS, ctlEp); + TEST_ASSERT_TRUE(cam); + cam->setOnResult(callback_motion_jpeg); + + Thread thread(display_thread, NULL, osPriorityBelowNormal); + + while(1) { + cam->poll(); + } +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example1_UsbFlashDrive.cpp Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,90 @@ +#if 0 +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#define DEBUG +#include "BaseUsbHostDebug.h" +#define TEST +#include "BaseUsbHostTest.h" +#include "UsbFlashDrive.h" + +DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); +Serial pc(USBTX, USBRX); + +BaseUsbHost *UsbHost; +UsbHub* hub; +ControlEp* ctlEp = NULL; +UsbFlashDrive* drive; +int main() { + pc.baud(921600); + printf("%s\n", __FILE__); + + UsbHost = new BaseUsbHost; + TEST_ASSERT_TRUE(UsbHost); + + UsbHub* hub = new UsbHub(); + TEST_ASSERT_TRUE(hub); + + for(int i = 0; i < MAX_HUB_PORT; i++) { + if (hub->PortEp[i]) { + if (hub->PortEp[i]->DeviceClass == 0x01) { + ctlEp = hub->PortEp[i]; + break; + } + } + } + + drive = new UsbFlashDrive("usb", ctlEp); + TEST_ASSERT(drive); + + + const int file_size = 1024*256; + printf("USB FLASH DRIVE read/write file size: %d bytes\n", file_size); + + char path[32]; + int size; + Timer t; + for(int n = 0; n <= 9; n++) { + sprintf(path, "/usb/test%d.txt", n); + FILE* fp = fopen(path, "wb"); + size = 0; + t.reset(); + t.start(); + if (fp) { + for(int i = 0; i < file_size; i++) { + int c = i & 0xff; + fputc(c, fp); + size++; + } + t.stop(); + fclose(fp); + } + printf("write file %d bytes %d ms %s\n", size, t.read_ms(), path); + led1 = !led1; + } + + for(int n = 0; n <=9; n++) { + sprintf(path, "/usb/test%d.txt", n); + FILE* fp = fopen(path, "rb"); + size = 0; + t.reset(); + t.start(); + if (fp) { + while(1) { + int c = fgetc(fp); + if (c == EOF) { + break; + } + size++; + } + t.stop(); + fclose(fp); + } + printf("read file %d bytes %d ms %s\n", size, t.read_ms(), path); + led2 = !led2; + } + + exit(1); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example1_UsbMouseHost.cpp Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,54 @@ +#if 0 +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#define DEBUG +#include "BaseUsbHostDebug.h" +#define TEST +#include "BaseUsbHostTest.h" +#include "UsbMouseHost.h" + +Serial pc(USBTX, USBRX); +DigitalOut led1(LED1); + +BaseUsbHost *UsbHost; +UsbHub* hub; +ControlEp* ctlEp = NULL; +UsbMouseHost* mouse; +int main() { + pc.baud(921600); + printf("%s\n", __FILE__); + + UsbHost = new BaseUsbHost; + TEST_ASSERT_TRUE(UsbHost); + + UsbHub* hub = new UsbHub(); + TEST_ASSERT_TRUE(hub); + + for(int i = 0; i < 4; i++) { + ctlEp = hub->PortEp[i]; + if (ctlEp) { + break; + } + } + + mouse = new UsbMouseHost(ctlEp); + TEST_ASSERT(mouse); + + + while(1) { + uint32_t status; + int r = mouse->read(&status); + if (r == USB_OK) { + printf("%08X\n", status); + if (status & 1) { // left + led1 = !led1; + } else if (status & 2) { // right + break; + } + } + } + exit(1); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#88a1a9c26ae3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue Dec 04 13:39:57 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/b60934f96c0c \ No newline at end of file