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.
Dependents: F401RE-USBHostMIDI_RecieveExample
Fork of F401RE-USBHost by
Revision 3:a3872f7593e2, committed 2014-01-25
- Comitter:
- va009039
- Date:
- Sat Jan 25 12:51:44 2014 +0000
- Parent:
- 2:0cdac6bcc534
- Child:
- 4:21d651ad6987
- Commit message:
- fix max packet size
Changed in this revision
--- a/FATFileSystem.lib Thu Jan 23 08:32:54 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/mbed_official/code/FATFileSystem/#b6669c987c8e
--- a/USBHALHost.cpp Thu Jan 23 08:32:54 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-// Simple USBHost for FRDM-KL46Z
-#include "USBHALHost.h"
-#include <algorithm>
-
-template <bool>struct CtAssert;
-template <>struct CtAssert<true> {};
-#define CTASSERT(A) CtAssert<A>();
-
-
-#ifdef _USB_DBG
-#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
-#define USB_DBG_HEX(A,B) debug_hex(A,B)
-void debug_hex(uint8_t* buf, int size);
-#else
-#define USB_DBG(...) while(0)
-#define USB_DBG_HEX(A,B) while(0)
-#endif
-
-#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
-#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
-
-#define BD_OWN_MASK (1<<7)
-#define BD_DATA01_MASK (1<<6)
-#define BD_KEEP_MASK (1<<5)
-#define BD_NINC_MASK (1<<4)
-#define BD_DTS_MASK (1<<3)
-#define BD_STALL_MASK (1<<2)
-
-#define TX 1
-#define RX 0
-
-#define EP0_BDT_IDX(dir, odd) (((2 * dir) + (1 * odd)))
-
-#define SETUP_TOKEN 0x0D
-#define IN_TOKEN 0x09
-#define OUT_TOKEN 0x01
-
-// for each endpt: 8 bytes
-struct BDT {
- uint8_t info; // BD[0:7]
- uint8_t dummy; // RSVD: BD[8:15]
- uint16_t byte_count; // BD[16:32]
- uint32_t address; // Addr
- void setBuffer(uint8_t* buf, int size) {
- address = (uint32_t)buf;
- byte_count = size;
- }
- uint8_t getStatus() {
- return (info>>2)&0x0f;
- }
-};
-
-__attribute__((__aligned__(512))) BDT bdt[64];
-
-USBHALHost* USBHALHost::instHost;
-
-USBHALHost::USBHALHost() {
- instHost = this;
- memset(rx_data01, DATA1, sizeof(rx_data01));
- memset(tx_data01, DATA1, sizeof(tx_data01));
-}
-
-void USBHALHost::init() {
- // Disable IRQ
- NVIC_DisableIRQ(USB0_IRQn);
-
- // choose usb src as PLL
- SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK);
-
- // enable OTG clock
- SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
-
- // USB Module Configuration
- // Reset USB Module
- USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
- while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
-
- // Clear interrupt flag
- USB0->ISTAT = 0xff;
-
- // Set BDT Base Register
- USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8);
- USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16);
- USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24);
-
- // Set SOF threshold
- USB0->SOFTHLD = USB_SOFTHLD_CNT(1);
-
- // pulldown D+ and D-
- USB0->USBCTRL = USB_USBCTRL_PDE_MASK;
-
- USB0->USBTRC0 |= 0x40;
-
- // Host mode
- USB0->CTL |= USB_CTL_HOSTMODEEN_MASK;
- // Desable SOF packet generation
- USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
-
- NVIC_SetVector(USB0_IRQn, (uint32_t)_usbisr);
- NVIC_EnableIRQ(USB0_IRQn);
-
- wait_attach();
-
- for(int retry = 2; retry > 0; retry--) {
- // Enable RESET
- USB0->CTL |= USB_CTL_RESET_MASK;
- wait_ms(500);
- USB0->CTL &= ~USB_CTL_RESET_MASK;
-
- // Enable SOF
- USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
- wait_ms(100);
-
- // token transfer initialize
- tx_ptr = ODD;
- rx_ptr = ODD;
- USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK;
-
- if (enumeration()) {
- break;
- }
- USB_DBG("retry=%d", retry);
- USB_TEST_ASSERT(retry > 1);
- }
-}
-
-void USBHALHost::wait_attach() {
- attach_done = false;
- USB0->INTEN = USB_INTEN_ATTACHEN_MASK;
- while(!attach_done);
- wait_ms(100);
- USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK);
- lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true;
- if (lowSpeed) { // low speed
- USB0->ENDPOINT[0].ENDPT |= USB_ENDPT_HOSTWOHUB_MASK;
- }
- USB_DBG("lowSpeed=%d", lowSpeed);
-}
-
-void USBHALHost::setAddr(int _addr) {
- USB0->ADDR = (lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(_addr);
-}
-
-void USBHALHost::setEndpoint(bool use_retry) {
- USB0->ENDPOINT[0].ENDPT = (lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00)|
- USB_ENDPT_EPCTLDIS_MASK|
- (use_retry ? 0x00 : USB_ENDPT_RETRYDIS_MASK)|
- USB_ENDPT_EPRXEN_MASK|
- USB_ENDPT_EPTXEN_MASK|
- USB_ENDPT_EPHSHK_MASK;
-}
-
-int USBHALHost::token_setup(SETUP_PACKET* setup, uint16_t wLength) {
- int retry = 0;
- do {
- token_ready();
- USB0->ENDPOINT[0].ENDPT = (lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) |
- USB_ENDPT_RETRYDIS_MASK|
- USB_ENDPT_EPRXEN_MASK|
- USB_ENDPT_EPTXEN_MASK|
- USB_ENDPT_EPHSHK_MASK;
- CTASSERT(sizeof(SETUP_PACKET) == 8);
- setup->wLength = wLength;
- int idx = EP0_BDT_IDX(TX, tx_ptr);
- bdt[idx].setBuffer((uint8_t*)setup, sizeof(SETUP_PACKET));
- bdt[idx].info = BD_OWN_MASK |
- BD_DTS_MASK; // always data0
- token_done = false;
- USB0->TOKEN = USB_TOKEN_TOKENPID(SETUP_TOKEN)|USB_TOKEN_TOKENENDPT(0);
- while(!token_done);
- LastStatus = bdt[idx].getStatus();
- if (LastStatus == ACK) {
- if (retry > 0) {
- USB_DBG("retry=%d %02x", retry, prev_LastStatus);
- }
- return ACK;
- }
- wait_ms(1);
- prev_LastStatus = LastStatus;
- //USB_DBG("retry=%d %02x", retry, prev_LastStatus);
- }while(retry++ < 10);
- return LastStatus;
-}
-
-int USBHALHost::token_in(uint8_t ep, uint8_t* data, int size, int retryLimit) {
- USB_TEST_ASSERT(ep < sizeof(rx_data01));
- for(int retry = 0;; retry++) {
- token_ready();
- int idx = EP0_BDT_IDX(RX, rx_ptr);
- bdt[idx].setBuffer(data, size);
- bdt[idx].info = BD_OWN_MASK|
- BD_DTS_MASK|
- ((rx_data01[ep] == DATA1) ? BD_DATA01_MASK : 0);
- token_done = false;
- USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)|USB_TOKEN_TOKENENDPT(ep);
- while(!token_done);
- LastStatus = bdt[idx].getStatus();
- int len = bdt[idx].byte_count;
- if (LastStatus == DATA0 || LastStatus == DATA1) {
- rx_data01[ep] = LastStatus == DATA0 ? DATA1 : DATA0;
- if (retry > 0) {
- USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus);
- }
- return len;
- }
- if (++retry >= retryLimit) {
- return -1;
- }
- wait_ms(100);
- prev_LastStatus = LastStatus;
- }
-}
-
-int USBHALHost::token_out(uint8_t ep, const uint8_t* data, int size) {
- USB_TEST_ASSERT(ep < sizeof(tx_data01));
- int retry = 0;
- do {
- token_ready();
- int idx = EP0_BDT_IDX(TX, tx_ptr);
- bdt[idx].info = BD_OWN_MASK|
- BD_DTS_MASK|
- ((tx_data01[ep] == DATA1) ? BD_DATA01_MASK : 0);
- bdt[idx].setBuffer((uint8_t*)data, size);
- token_done = false;
- USB0->TOKEN = USB_TOKEN_TOKENPID(OUT_TOKEN)|USB_TOKEN_TOKENENDPT(ep);
- while(!token_done);
- LastStatus = bdt[idx].getStatus();
- if (LastStatus == ACK) {
- tx_data01[ep] = (tx_data01[ep] == DATA0) ? DATA1 : DATA0;
- if (retry > 0) {
- USB_DBG("retry=%d %02x", retry, prev_LastStatus);
- }
- return bdt[idx].byte_count;
- }
- wait_ms(10);
- prev_LastStatus = LastStatus;
- } while(retry++ < 10);
- return -1;
-}
-
-void USBHALHost::token_ready() {
- while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) { // TOKEN_BUSY ?
- wait_ms(1);
- }
- USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF
- while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK));
- USB0->SOFTHLD = 0; // this is needed as without this you can get errors
- USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF
-}
-
-void USBHALHost::_usbisr(void) {
- if (instHost) {
- instHost->UsbIrqhandler();
- }
-}
-
-void USBHALHost::UsbIrqhandler() {
- uint8_t istat = USB0->ISTAT;
- if (istat & USB_ISTAT_TOKDNE_MASK) {
- uint8_t stat = USB0->STAT;
- ODD_EVEN next_ptr = (stat & USB_STAT_ODD_MASK) ? ODD : EVEN;
- if (stat & USB_STAT_TX_MASK) {
- tx_ptr = next_ptr;
- } else {
- rx_ptr = next_ptr;
- }
- token_done = true;
- }
- if (istat & USB_ISTAT_ATTACH_MASK) {
- USB0->INTEN &= ~USB_INTEN_ATTACHEN_MASK;
- attach_done = true;
- }
- USB0->ISTAT = istat; // clear
-}
-
-void debug_hex(uint8_t* buf, int size) {
- for(int i = 0; i < size; i++) {
- fprintf(stderr, "%02x ", buf[i]);
- if (i%16 == 15) {
- fprintf(stderr, "\r\n");
- }
- }
- fprintf(stderr, "\r\n");
-}
-
--- a/USBHALHost.h Thu Jan 23 08:32:54 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-// Simple USBHost for FRDM-KL46Z
-#pragma once
-#include "mbed.h"
-
-struct SETUP_PACKET {
- uint8_t bmRequestType;
- uint8_t bRequest;
- uint16_t wValue;
- uint16_t wIndex;
- uint16_t wLength;
-};
-
-#define SET_ADDRESS 5
-#define GET_DESCRIPTOR 6
-#define GET_CONFIGURATION 8
-#define SET_CONFIGURATION 9
-
-// TOK_PID[5:2]
-#define DATA0 0x03
-#define DATA1 0x0b
-#define ACK 0x02
-#define STALL 0x0e
-#define NAK 0x0a
-#define Bus_Timeout 0x00
-#define Data_Error 0x0f
-
-enum ODD_EVEN {
- ODD = 0,
- EVEN = 1,
-};
-
-class USBHALHost {
-public:
- uint8_t LastStatus;
- uint8_t prev_LastStatus;
-
-protected:
- USBHALHost();
- void init();
- virtual bool enumeration() = 0;
- bool lowSpeed;
-
- uint8_t ep_int_in;
- uint8_t ep_bulk_in;
- uint8_t ep_bulk_out;
- int MaxPacketSize0;
- void setAddr(int addr);
- void setEndpoint(bool use_retry = false);
- int token_setup(SETUP_PACKET* setup, uint16_t wLength = 0);
- int token_in(uint8_t ep, uint8_t* data = NULL, int size = 0, int retryLimit = 10);
- int token_out(uint8_t ep, const uint8_t* data = NULL, int size = 0);
- void token_ready();
- uint8_t tx_data01[16];
- uint8_t rx_data01[16];
-
-private:
- static void _usbisr(void);
- void UsbIrqhandler();
-
- __IO bool attach_done;
- __IO bool token_done;
- void wait_attach();
- ODD_EVEN tx_ptr;
- ODD_EVEN rx_ptr;
- static USBHALHost * instHost;
-};
--- a/USBHost.cpp Thu Jan 23 08:32:54 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-// Simple USBHost for FRDM-KL46Z
-#include "USBHost.h"
-#include <algorithm>
-
-template <bool>struct CtAssert;
-template <>struct CtAssert<true> {};
-#define CTASSERT(A) CtAssert<A>();
-
-
-#ifdef _USB_DBG
-#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
-#define USB_DBG_HEX(A,B) debug_hex(A,B)
-void debug_hex(uint8_t* buf, int size);
-#else
-#define USB_DBG(...) while(0)
-#define USB_DBG_HEX(A,B) while(0)
-#endif
-
-#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
-#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
-
-USBHost* USBHost::inst = NULL;
-
-USBHost* USBHost::getHostInst()
-{
- if (inst == NULL) {
- inst = new USBHost();
- inst->init();
- }
- return inst;
-}
-
-USBHost::USBHost() {
-}
-
-/* virtual */ bool USBHost::enumeration() {
- uint8_t desc[64];
- MaxPacketSize0 = 8;
- dev_addr = 0;
- USB0->ADDR = (lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(dev_addr);
- wait_ms(100);
- SETUP_PACKET setup_get_descriptor = {0x80, GET_DESCRIPTOR, 1<<8, 0, 0};
- int result = ControlRead(&setup_get_descriptor, desc, 8);
- if (result < 8) {
- USB_DBG("result=%d %02x", result, LastStatus);
- return false;
- }
- USB_DBG_HEX(desc, result);
- MaxPacketSize0 = desc[7];
-
- SETUP_PACKET setup_set_address = {0x00, SET_ADDRESS, 1, 0, 0};
- result = ControlWrite(&setup_set_address);
- if (result < 0) {
- USB_DBG("result=%d %02x", result, LastStatus);
- return false;
- }
- wait_ms(100);
- dev_addr = 1;
-
- result = ControlRead(&setup_get_descriptor, desc, sizeof(desc));
- if (result < 8) {
- USB_DBG("result=%d", result);
- return false;
- }
- USB_DBG_HEX(desc, result);
-
- setup_get_descriptor.wValue = 2<<8; // config descriptor
- result = ControlRead(&setup_get_descriptor, desc, 4);
- if (result != 4) {
- USB_DBG("result=%d", result);
- return false;
- }
- USB_DBG_HEX(desc, 4);
-
- int TotalLength = desc[2]|desc[3]<<8;
- uint8_t* buf = new uint8_t[TotalLength];
- result = ControlRead(&setup_get_descriptor, buf, TotalLength);
- if (result != TotalLength) {
- USB_DBG("result=%d TotalLength=%d %02x", result, TotalLength, LastStatus);
- return false;
- }
- USB_DBG_HEX(buf, TotalLength);
-
- for(int i = 0; i < TotalLength; ) {
- int Length = buf[i];
- uint8_t DescriptorType = buf[i+1];
- if (DescriptorType == 0x05) { // endpoint
- uint8_t EndpointAddress = buf[i+2];
- uint8_t Attributes = buf[i+3];
- if (Attributes == 0x03) { // interrupt
- if (EndpointAddress & 0x80) {
- ep_int_in = EndpointAddress;
- }
- } else if (Attributes == 0x02) { // bulk
- if (EndpointAddress & 0x80) {
- ep_bulk_in = EndpointAddress;
- } else {
- ep_bulk_out = EndpointAddress;
- }
- }
- }
- USB_DBG_HEX(buf+i, Length);
- i += Length;
- }
- delete[] buf;
-
- // config = 1
- SETUP_PACKET setup_set_config = {0x00, SET_CONFIGURATION, 1, 0, 0};
- result = ControlWrite(&setup_set_config);
- if (result < 0) {
- USB_DBG("set config: %02x", LastStatus);
- if (lowSpeed && LastStatus == STALL) { // TODO:
- wait_ms(100);
- return true;
- }
- return false;
- }
- wait_ms(100);
- return true;
-}
-
-int USBHost::ControlRead(SETUP_PACKET* setup, uint8_t* data, int size) {
- setAddr(dev_addr);
- token_setup(setup, size); // setup stage
- if (LastStatus != ACK) {
- USB_DBG("setup %02x", LastStatus);
- return -1;
- }
- rx_data01[0] = DATA1;
- int read_len = 0;
- while(read_len < size) {
- int size2 = std::min(size-read_len, MaxPacketSize0);
- int result = token_in(0, data+read_len, size2);
- //USB_DBG("token_in result=%d %02x", result, LastStatus);
- if (result < 0) {
- USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus);
- return result;
- }
- read_len += result;
- if (result < MaxPacketSize0) {
- break;
- }
- }
- tx_data01[0] = rx_data01[0];
- int result = token_out(0); // status stage
- if (result < 0) {
- USB_DBG("status token_out %02x", LastStatus);
- if (LastStatus == STALL) {
- return read_len;
- }
- return result;
- }
- return read_len;
-}
-
-int USBHost::ControlWrite(SETUP_PACKET* setup, uint8_t* data, int size) {
- setAddr(dev_addr);
- token_setup(setup, size); // setup stage
- if (LastStatus != ACK) {
- USB_DBG("setup %02x", LastStatus);
- return -1;
- }
-
- tx_data01[0] = DATA1;
- int write_len = 0;
- if (data != NULL) {
- write_len = token_out(0, data, size);
- if (write_len < 0) {
- return -1;
- }
- }
- rx_data01[0] = tx_data01[0];
- int result = token_in(0); // status stage
- if (result < 0) {
- return result;
- }
- return write_len;
-}
-
-int USBHost::InterruptRead(uint8_t* data, int size) {
- setAddr(dev_addr);
- setEndpoint();
- const int retryLimit = 0;
- return token_in(ep_int_in & 0x7f, data, size, retryLimit);
-}
-
-int USBHost::BulkRead(uint8_t* data, int size) {
- setAddr(dev_addr);
- setEndpoint();
- const int max_packet_size = 64;
- int read_len = 0;
- while(read_len < size) {
- int size2 = std::min(size-read_len, max_packet_size);
- int result = token_in(ep_bulk_in & 0x7f, data+read_len, size2);
- if (result < 0) {
- //USB_DBG("token_in result=%d %02x", result, LastStatus);
- return result;
- }
- read_len += result;
- if (result < max_packet_size) {
- break;
- }
- }
- return read_len;
-}
-
-int USBHost::BulkWrite(const uint8_t* data, int size) {
- setAddr(dev_addr);
- setEndpoint();
- const int max_packet_size = 64;
- int write_len = 0;
- while(write_len < size) {
- int size2 = std::min(size-write_len, max_packet_size);
- int result = token_out(ep_bulk_out, data+write_len, size2);
- if (result < 0) {
- //USB_DBG("token_in result=%d %02x", result, LastStatus);
- return result;
- }
- write_len += result;
- if (result < max_packet_size) {
- break;
- }
- }
- return write_len;
-}
-
--- a/USBHost.h Thu Jan 23 08:32:54 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-// Simple USBHost for FRDM-KL46Z
-#pragma once
-#include "mbed.h"
-#include "USBHALHost.h"
-
-class USBHost : public USBHALHost {
-public:
- static USBHost* getHostInst();
- int InterruptRead(uint8_t* data, int size);
- int ControlRead(SETUP_PACKET* setup, uint8_t* data, int size);
- int ControlWrite(SETUP_PACKET* setup, uint8_t* data = NULL, int size = 0);
- int BulkRead(uint8_t* data, int size);
- int BulkWrite(const uint8_t* data, int size);
-
-private:
- USBHost();
- static USBHost* inst;
- virtual bool enumeration();
- int dev_addr;
-};
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBEndpoint.h Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,15 @@
+#pragma once
+#include "USBHostTypes.h"
+
+class USBEndpoint {
+public:
+ void setState(uint8_t st){}; // dummy
+ void setSize(uint32_t size) { MaxPacketSize = size; }
+ void setAddress(uint8_t addr) { address = addr; }
+ uint8_t getAddress(){ return address; };
+ uint32_t getSize() { return MaxPacketSize; }
+
+private:
+ uint8_t address;
+ int MaxPacketSize;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost.cpp Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,375 @@
+// Simple USBHost for FRDM-KL46Z
+#include "USBHALHost.h"
+#include <algorithm>
+
+template <bool>struct CtAssert;
+template <>struct CtAssert<true> {};
+#define CTASSERT(A) CtAssert<A>();
+
+
+#ifdef _USB_DBG
+#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
+#define USB_DBG_HEX(A,B) debug_hex(A,B)
+void debug_hex(uint8_t* buf, int size);
+#else
+#define USB_DBG(...) while(0)
+#define USB_DBG_HEX(A,B) while(0)
+#endif
+
+#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
+
+#define BD_OWN_MASK (1<<7)
+#define BD_DATA01_MASK (1<<6)
+#define BD_KEEP_MASK (1<<5)
+#define BD_NINC_MASK (1<<4)
+#define BD_DTS_MASK (1<<3)
+#define BD_STALL_MASK (1<<2)
+
+#define TX 1
+#define RX 0
+
+#define EP0_BDT_IDX(dir, odd) (((2 * dir) + (1 * odd)))
+
+#define SETUP_TOKEN 0x0D
+#define IN_TOKEN 0x09
+#define OUT_TOKEN 0x01
+
+// for each endpt: 8 bytes
+struct BDT {
+ uint8_t info; // BD[0:7]
+ uint8_t dummy; // RSVD: BD[8:15]
+ uint16_t byte_count; // BD[16:32]
+ uint32_t address; // Addr
+ void setBuffer(uint8_t* buf, int size) {
+ address = (uint32_t)buf;
+ byte_count = size;
+ }
+ uint8_t getStatus() {
+ return (info>>2)&0x0f;
+ }
+};
+
+__attribute__((__aligned__(512))) BDT bdt[64];
+
+USBHALHost* USBHALHost::instHost;
+
+USBHALHost::USBHALHost() {
+ instHost = this;
+ report.clear();
+}
+
+void USBHALHost::init() {
+ // Disable IRQ
+ NVIC_DisableIRQ(USB0_IRQn);
+
+ // choose usb src as PLL
+ SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK);
+
+ // enable OTG clock
+ SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
+
+ // USB Module Configuration
+ // Reset USB Module
+ USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
+ while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
+
+ // Clear interrupt flag
+ USB0->ISTAT = 0xff;
+
+ // Set BDT Base Register
+ USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8);
+ USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16);
+ USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24);
+
+ // Set SOF threshold
+ USB0->SOFTHLD = USB_SOFTHLD_CNT(1);
+
+ // pulldown D+ and D-
+ USB0->USBCTRL = USB_USBCTRL_PDE_MASK;
+
+ USB0->USBTRC0 |= 0x40;
+
+ // Host mode
+ USB0->CTL |= USB_CTL_HOSTMODEEN_MASK;
+ // Desable SOF packet generation
+ USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
+
+ NVIC_SetVector(USB0_IRQn, (uint32_t)_usbisr);
+ NVIC_EnableIRQ(USB0_IRQn);
+
+ wait_attach();
+
+ for(int retry = 2; retry > 0; retry--) {
+ // Enable RESET
+ USB0->CTL |= USB_CTL_RESET_MASK;
+ wait_ms(500);
+ USB0->CTL &= ~USB_CTL_RESET_MASK;
+
+ // Enable SOF
+ USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
+ wait_ms(100);
+
+ // token transfer initialize
+ token_transfer_init();
+
+ USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK|
+ USB_INTEN_ERROREN_MASK;
+ USB0->ERREN |= USB_ERREN_PIDERREN_MASK|
+ USB_ERREN_CRC5EOFEN_MASK|
+ USB_ERREN_CRC16EN_MASK|
+ USB_ERREN_DFN8EN_MASK|
+ USB_ERREN_BTOERREN_MASK|
+ USB_ERREN_DMAERREN_MASK|
+ USB_ERREN_BTSERREN_MASK;
+
+ if (enumeration()) {
+ break;
+ }
+ USB_DBG("retry=%d", retry);
+ USB_TEST_ASSERT(retry > 1);
+ }
+}
+
+void USBHALHost::wait_attach() {
+ attach_done = false;
+ USB0->INTEN = USB_INTEN_ATTACHEN_MASK;
+ while(!attach_done);
+ wait_ms(100);
+ USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK);
+ lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true;
+ if (lowSpeed) { // low speed
+ USB0->ENDPOINT[0].ENDPT |= USB_ENDPT_HOSTWOHUB_MASK;
+ }
+ USB_DBG("lowSpeed=%d", lowSpeed);
+}
+
+void USBHALHost::setAddr(int _addr) {
+ USB0->ADDR = (lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(_addr);
+}
+
+void USBHALHost::setEndpoint(bool use_retry) {
+ USB0->ENDPOINT[0].ENDPT = (lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00)|
+ USB_ENDPT_EPCTLDIS_MASK|
+ (use_retry ? 0x00 : USB_ENDPT_RETRYDIS_MASK)|
+ USB_ENDPT_EPRXEN_MASK|
+ USB_ENDPT_EPTXEN_MASK|
+ USB_ENDPT_EPHSHK_MASK;
+}
+
+void USBHALHost::token_transfer_init() {
+ tx_ptr = ODD;
+ rx_ptr = ODD;
+ data01.init();
+}
+
+int USBHALHost::token_setup(SETUP_PACKET* setup, uint16_t wLength) {
+ for(int retry = 0;; retry++) {
+ token_ready();
+ USB0->ENDPOINT[0].ENDPT = (lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) |
+ USB_ENDPT_RETRYDIS_MASK|
+ USB_ENDPT_EPRXEN_MASK|
+ USB_ENDPT_EPTXEN_MASK|
+ USB_ENDPT_EPHSHK_MASK;
+ CTASSERT(sizeof(SETUP_PACKET) == 8);
+ setup->wLength = wLength;
+ int idx = EP0_BDT_IDX(TX, tx_ptr);
+ bdt[idx].setBuffer((uint8_t*)setup, sizeof(SETUP_PACKET));
+ bdt[idx].info = BD_OWN_MASK |
+ BD_DTS_MASK; // always data0
+ token_done = false;
+ USB0->TOKEN = USB_TOKEN_TOKENPID(SETUP_TOKEN)|USB_TOKEN_TOKENENDPT(0);
+ while(!token_done);
+ LastStatus = bdt[idx].getStatus();
+ if (LastStatus == ACK) {
+ if (retry > 0) {
+ USB_DBG("retry=%d %02x", retry, prev_LastStatus);
+ }
+ break;
+ }
+ if (retry > 10) {
+ break;
+ }
+ prev_LastStatus = LastStatus;
+ wait_ms(1);
+ }
+ data01.set(TX, 0, DATA1);
+ data01.set(RX, 0, DATA1);
+ return LastStatus;
+}
+
+int USBHALHost::token_in(uint8_t ep, uint8_t* data, int size, int retryLimit) {
+ for(int retry = 0;; retry++) {
+ token_ready();
+ int idx = EP0_BDT_IDX(RX, rx_ptr);
+ bdt[idx].setBuffer(data, size);
+ bdt[idx].info = BD_OWN_MASK|
+ BD_DTS_MASK|
+ (data01.get(RX, ep) == DATA1 ? BD_DATA01_MASK : 0);
+ token_done = false;
+ USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)|USB_TOKEN_TOKENENDPT(ep);
+ while(!token_done);
+ LastStatus = bdt[idx].getStatus();
+ int len = bdt[idx].byte_count;
+ if (LastStatus == DATA0 || LastStatus == DATA1) {
+ data01.set(RX, ep, LastStatus == DATA0 ? DATA1 : DATA0);
+ if (retry > 0) {
+ USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus);
+ }
+ return len;
+ } else if (LastStatus == NAK) {
+ report.nak++;
+ }
+ if (retry >= retryLimit) {
+ return -1;
+ }
+ wait_ms(100);
+ prev_LastStatus = LastStatus;
+ }
+}
+
+int USBHALHost::token_out(uint8_t ep, const uint8_t* data, int size) {
+ for(int retry = 0;; retry++) {
+ token_ready();
+ int idx = EP0_BDT_IDX(TX, tx_ptr);
+ bdt[idx].setBuffer((uint8_t*)data, size);
+ bdt[idx].info = BD_OWN_MASK|
+ BD_DTS_MASK|
+ (data01.get(TX, ep) == DATA1 ? BD_DATA01_MASK : 0);
+ token_done = false;
+ USB0->TOKEN = USB_TOKEN_TOKENPID(OUT_TOKEN)|USB_TOKEN_TOKENENDPT(ep);
+ while(!token_done);
+ LastStatus = bdt[idx].getStatus();
+ int len = bdt[idx].byte_count;
+ //USB_DBG("len=%d %02x", len, LastStatus);
+ if (LastStatus == ACK) {
+ data01.toggle(TX, ep);
+ if (retry > 0) {
+ USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus);
+ }
+ return len;
+ } else if (LastStatus == NAK) {
+ report.nak++;
+ }
+ if (retry > 10) {
+ return -1;
+ }
+ wait_ms(100);
+ prev_LastStatus = LastStatus;
+ }
+}
+
+void USBHALHost::token_ready() {
+ while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) { // TOKEN_BUSY ?
+ wait_ms(1);
+ }
+ USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF
+ while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK));
+ USB0->SOFTHLD = 0; // this is needed as without this you can get errors
+ USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF
+}
+
+void USBHALHost::_usbisr(void) {
+ if (instHost) {
+ instHost->UsbIrqhandler();
+ }
+}
+
+void USBHALHost::UsbIrqhandler() {
+ uint8_t istat = USB0->ISTAT;
+ if (istat & USB_ISTAT_TOKDNE_MASK) {
+ uint8_t stat = USB0->STAT;
+ ODD_EVEN next_ptr = (stat & USB_STAT_ODD_MASK) ? ODD : EVEN;
+ if (stat & USB_STAT_TX_MASK) {
+ tx_ptr = next_ptr;
+ } else {
+ rx_ptr = next_ptr;
+ }
+ token_done = true;
+ }
+ if (istat & USB_ISTAT_ATTACH_MASK) {
+ USB0->INTEN &= ~USB_INTEN_ATTACHEN_MASK;
+ attach_done = true;
+ }
+ if (istat & USB_ISTAT_ERROR_MASK) {
+ uint8_t errstat = USB0->ERRSTAT;
+ if (errstat & USB_ERRSTAT_PIDERR_MASK) {
+ report.errstat_piderr++;
+ }
+ if (errstat & USB_ERRSTAT_CRC5EOF_MASK) {
+ report.errstat_crc5eof++;
+ }
+ if (errstat & USB_ERRSTAT_CRC16_MASK) {
+ report.errstat_crc16++;
+ }
+ if (errstat & USB_ERRSTAT_DFN8_MASK) {
+ report.errstat_dfn8++;
+ }
+ if (errstat & USB_ERRSTAT_BTOERR_MASK) {
+ report.errstat_btoerr++;
+ }
+ if (errstat & USB_ERRSTAT_DMAERR_MASK) {
+ report.errstat_dmaerr++;
+ }
+ if (errstat & USB_ERRSTAT_BTSERR_MASK) {
+ report.errstat_btoerr++;
+ }
+ USB0->ERRSTAT = errstat;
+ }
+ USB0->ISTAT = istat; // clear
+}
+
+void Report::clear() {
+ errstat_piderr = 0;
+ errstat_crc5eof = 0;
+ errstat_crc16 = 0;
+ errstat_dfn8 = 0;
+ errstat_btoerr = 0;
+ errstat_dmaerr = 0;
+ errstat_bsterr = 0;
+ //
+ nak = 0;
+}
+
+void Report::print_errstat() {
+ printf("ERRSTAT PID: %d, CRC5EOF: %d, CRC16: %d, DFN8: %d, BTO: %d, DMA: %d, BST: %d\n",
+ errstat_piderr, errstat_crc5eof,
+ errstat_crc16, errstat_dfn8,
+ errstat_btoerr, errstat_dmaerr, errstat_bsterr);
+}
+
+void Data01::init() {
+ memset(txrx_data01, DATA0, sizeof(txrx_data01));
+}
+
+void Data01::set(int txrx, int ep, uint8_t _data01) {
+ if (ep == 0) {
+ txrx = 0;
+ }
+ txrx_data01[txrx][ep] = _data01;
+}
+
+void Data01::toggle(int txrx, int ep) {
+ if (ep == 0) {
+ txrx = 0;
+ }
+ txrx_data01[txrx][ep] = txrx_data01[txrx][ep] == DATA0 ? DATA1 : DATA0;
+}
+
+uint8_t Data01::get(int txrx, int ep) {
+ if (ep == 0) {
+ txrx = 0;
+ }
+ return txrx_data01[txrx][ep];
+}
+
+void debug_hex(uint8_t* buf, int size) {
+ for(int i = 0; i < size; i++) {
+ fprintf(stderr, "%02x ", buf[i]);
+ if (i%16 == 15) {
+ fprintf(stderr, "\r\n");
+ }
+ }
+ fprintf(stderr, "\r\n");
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost.h Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,86 @@
+// Simple USBHost for FRDM-KL46Z
+#pragma once
+#include "mbed.h"
+#include "USBHostTypes.h"
+#include "USBEndpoint.h"
+
+struct SETUP_PACKET {
+ uint8_t bmRequestType;
+ uint8_t bRequest;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+};
+
+#define GET_CONFIGURATION 8
+
+// TOK_PID[5:2]
+#define DATA0 0x03
+#define DATA1 0x0b
+#define ACK 0x02
+#define STALL 0x0e
+#define NAK 0x0a
+#define Bus_Timeout 0x00
+#define Data_Error 0x0f
+
+enum ODD_EVEN {
+ ODD = 0,
+ EVEN = 1,
+};
+
+class Report {
+public:
+ void clear();
+ void print_errstat();
+ // error count
+ uint32_t errstat_piderr; // USBx_ERRSTAT[PIDERR]
+ uint32_t errstat_crc5eof;// USBx_ERRSTAT[CRC5EOF]
+ uint32_t errstat_crc16; // USBx_ERRSTAT[CRC16]
+ uint32_t errstat_dfn8; // USBx_ERRSTAT[DFN8]
+ uint32_t errstat_btoerr; // USBx_ERRSTAT[BTOERR]
+ uint32_t errstat_dmaerr; // USBx_ERRSTAT[DMAERR]
+ uint32_t errstat_bsterr; // USBx_ERRSTAT[BTSERR]
+ //
+ uint32_t nak;
+};
+
+class Data01 {
+public:
+ void init();
+ void set(int txrx, int ep, uint8_t _data01);
+ void toggle(int txrx, int ep);
+ uint8_t get(int txrx, int ep);
+private:
+ uint8_t txrx_data01[2][16];
+};
+
+class USBHALHost {
+public:
+ uint8_t LastStatus;
+ uint8_t prev_LastStatus;
+ Report report;
+
+protected:
+ USBHALHost();
+ void init();
+ virtual bool enumeration() = 0;
+ bool lowSpeed;
+ int MaxPacketSize0;
+ void setAddr(int addr);
+ void setEndpoint(bool use_retry = false);
+ void token_transfer_init();
+ int token_setup(SETUP_PACKET* setup, uint16_t wLength = 0);
+ int token_in(uint8_t ep, uint8_t* data = NULL, int size = 0, int retryLimit = 10);
+ int token_out(uint8_t ep, const uint8_t* data = NULL, int size = 0);
+ void token_ready();
+private:
+ static void _usbisr(void);
+ void UsbIrqhandler();
+ __IO bool attach_done;
+ __IO bool token_done;
+ void wait_attach();
+ Data01 data01;
+ ODD_EVEN tx_ptr;
+ ODD_EVEN rx_ptr;
+ static USBHALHost * instHost;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.cpp Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,331 @@
+// Simple USBHost for FRDM-KL46Z
+#include "USBHost.h"
+#include <algorithm>
+
+template <bool>struct CtAssert;
+template <>struct CtAssert<true> {};
+#define CTASSERT(A) CtAssert<A>();
+
+
+#ifdef _USB_DBG
+#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
+#define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
+#define USB_DBG_HEX(A,B) debug_hex(A,B)
+#define USB_DBG_ERRSTAT() report.print_errstat();
+void debug_hex(uint8_t* buf, int size);
+#else
+#define USB_DBG(...) while(0)
+#define USB_DBG2(...) while(0)
+#define USB_DBG_HEX(A,B) while(0)
+#define USB_DBG_ERRSTAT() while(0)
+#endif
+
+#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
+
+#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0);
+
+USBHost* USBHost::inst = NULL;
+
+USBHost* USBHost::getHostInst()
+{
+ if (inst == NULL) {
+ inst = new USBHost();
+ inst->init();
+ }
+ return inst;
+}
+
+USBHost::USBHost() {
+}
+
+/* virtual */ bool USBHost::enumeration() {
+ uint8_t desc[64];
+ MaxPacketSize0 = 8;
+ dev_addr = 0;
+ USB0->ADDR = (lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(dev_addr);
+ wait_ms(100);
+ SETUP_PACKET setup_get_descriptor = {0x80, GET_DESCRIPTOR, 1<<8, 0, 0};
+ int result = ControlRead(&setup_get_descriptor, desc, 8);
+ if (result < 8) {
+ USB_DBG("result=%d %02x", result, LastStatus);
+ USB_DBG_ERRSTAT();
+ return false;
+ }
+ USB_DBG_HEX(desc, result);
+ USB_DBG_ERRSTAT();
+ DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
+ MaxPacketSize0 = dev_desc->bMaxPacketSize;
+
+ SETUP_PACKET setup_set_address = {0x00, SET_ADDRESS, 1, 0, 0};
+ result = ControlWrite(&setup_set_address);
+ if (result < 0) {
+ USB_DBG("result=%d %02x", result, LastStatus);
+ USB_DBG_ERRSTAT();
+ return false;
+ }
+ wait_ms(100);
+ dev_addr = 1;
+
+ result = ControlRead(&setup_get_descriptor, desc, sizeof(desc));
+ if (result < 8) {
+ USB_DBG("result=%d", result);
+ USB_DBG_ERRSTAT();
+ return false;
+ }
+ USB_DBG_HEX(desc, result);
+ USB_DBG_ERRSTAT();
+
+ USB_INFO("VID: %04x, PID: %04x\n", dev_desc->idVendor, dev_desc->idProduct);
+ if (dev_desc->bDeviceClass == HUB_CLASS) {
+ USB_INFO("USB hub not supported.\n\n");
+ exit(1);
+ }
+
+ setup_get_descriptor.wValue = 2<<8; // config descriptor
+ result = ControlRead(&setup_get_descriptor, desc, 4);
+ if (result != 4) {
+ USB_DBG("result=%d", result);
+ USB_DBG_ERRSTAT();
+ return false;
+ }
+ USB_DBG_HEX(desc, 4);
+ USB_DBG_ERRSTAT();
+
+ int TotalLength = desc[2]|desc[3]<<8;
+ uint8_t* buf = new uint8_t[TotalLength];
+ result = ControlRead(&setup_get_descriptor, buf, TotalLength);
+ if (result != TotalLength) {
+ USB_DBG("result=%d TotalLength=%d %02x", result, TotalLength, LastStatus);
+ USB_DBG_ERRSTAT();
+ return false;
+ }
+ USB_DBG_HEX(buf, TotalLength);
+ USB_DBG_ERRSTAT();
+
+ for(int i = 0; i < TotalLength; ) {
+ int Length = buf[i];
+ uint8_t DescriptorType = buf[i+1];
+ if (DescriptorType == 0x05) { // endpoint
+ EndpointDescriptor* desc = reinterpret_cast<EndpointDescriptor*>(buf+i);
+ USBEndpoint* ep = NULL;
+ if (desc->bmAttributes == 0x03) { // interrupt
+ if (desc->bEndpointAddress & 0x80) {
+ ep = &ep_int_in;
+ }
+ } else if (desc->bmAttributes == 0x02) { // bulk
+ ep = (desc->bEndpointAddress & 0x80) ? &ep_bulk_in : &ep_bulk_out;
+ }
+ if (ep) {
+ ep->setAddress(desc->bEndpointAddress);
+ ep->setSize(desc->wMaxPacketSize);
+ }
+ }
+ USB_DBG_HEX(buf+i, Length);
+ i += Length;
+ }
+ delete[] buf;
+
+ // config = 1
+ SETUP_PACKET setup_set_config = {0x00, SET_CONFIGURATION, 1, 0, 0};
+ result = ControlWrite(&setup_set_config);
+ if (result < 0) {
+ USB_DBG("set config: %02x", LastStatus);
+ USB_DBG_ERRSTAT();
+ if (lowSpeed && LastStatus == STALL) { // TODO:
+ wait_ms(100);
+ return true;
+ }
+ return false;
+ }
+ wait_ms(100);
+ return true;
+}
+
+USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
+ SETUP_PACKET setup = {requestType, request, value, index};
+ int result = ControlRead(&setup, buf, len);
+ USB_DBG2("result=%d %02x", result, LastStatus);
+ return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR;
+}
+
+USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
+ SETUP_PACKET setup = {requestType, request, value, index};
+ int result = ControlWrite(&setup, buf, len);
+ if (result >= 0) {
+ return USB_TYPE_OK;
+ }
+ USB_DBG("result=%d %02x", result, LastStatus);
+ USB_DBG_ERRSTAT();
+ USB_DBG_HEX(buf, len);
+ return USB_TYPE_ERROR;
+}
+
+USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
+ USB_TEST_ASSERT(blocking);
+ int result = BulkRead(buf, len);
+ if (result >= 0) {
+ return USB_TYPE_OK;
+ }
+ //USB_DBG2("result=%d %02x", result, host->LastStatus);
+ return USB_TYPE_ERROR;
+}
+
+USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
+ USB_TEST_ASSERT(blocking);
+ int result = BulkWrite(buf, len);
+ if (result >= 0) {
+ return USB_TYPE_OK;
+ }
+ USB_DBG2("result=%d %02x", result, LastStatus);
+ return USB_TYPE_ERROR;
+}
+
+USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
+ USB_TEST_ASSERT(blocking);
+ int result = InterruptRead(buf, len);
+ if (result >= 0) {
+ return USB_TYPE_OK;
+ }
+ return USB_TYPE_ERROR;
+}
+
+int USBHost::ControlRead(SETUP_PACKET* setup, uint8_t* data, int size) {
+ setAddr(dev_addr);
+ token_setup(setup, size); // setup stage
+ if (LastStatus != ACK) {
+ USB_DBG("setup %02x", LastStatus);
+ return -1;
+ }
+ int read_len = 0;
+ while(read_len < size) {
+ int size2 = std::min(size-read_len, MaxPacketSize0);
+ int result = token_in(0, data+read_len, size2);
+ //USB_DBG("token_in result=%d %02x", result, LastStatus);
+ if (result < 0) {
+ USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus);
+ return result;
+ }
+ read_len += result;
+ if (result < MaxPacketSize0) {
+ break;
+ }
+ }
+ int result = token_out(0); // status stage
+ if (result < 0) {
+ USB_DBG("status token_out %02x", LastStatus);
+ if (LastStatus == STALL) {
+ return read_len;
+ }
+ return result;
+ }
+ return read_len;
+}
+
+int USBHost::ControlWrite(SETUP_PACKET* setup, uint8_t* data, int size) {
+ setAddr(dev_addr);
+ token_setup(setup, size); // setup stage
+ if (LastStatus != ACK) {
+ USB_DBG("setup %02x", LastStatus);
+ return -1;
+ }
+ int write_len = 0;
+ if (data != NULL) {
+ write_len = token_out(0, data, size);
+ if (write_len < 0) {
+ return -1;
+ }
+ }
+ int result = token_in(0); // status stage
+ if (result < 0) {
+ USB_DBG("result=%d %02x", result, LastStatus);
+ //return result;
+ }
+ return write_len;
+}
+
+int USBHost::InterruptRead(uint8_t* data, int size) {
+ setAddr(dev_addr);
+ setEndpoint();
+ const int retryLimit = 0;
+ int max_packet_size = ep_int_in.getSize();
+ int read_len = 0;
+ for(int n = 0; read_len < size; n++) {
+ int size2 = std::min(size-read_len, max_packet_size);
+ int result = token_in(ep_int_in.getAddress() & 0x7f, data+read_len, size2, retryLimit);
+ if (result < 0) {
+ if (LastStatus == NAK) {
+ if (n == 0) {
+ return -1;
+ }
+ break;
+ }
+ USB_DBG("token_in result=%d %02x", result, LastStatus);
+ return result;
+ }
+ read_len += result;
+ if (result < max_packet_size) {
+ break;
+ }
+ }
+ return read_len;
+}
+
+int USBHost::BulkRead(uint8_t* data, int size, int timeout_ms) {
+ setAddr(dev_addr);
+ setEndpoint();
+ int max_packet_size = ep_bulk_in.getSize();
+ int retryLimit = (timeout_ms == 0) ? 0 : 10;
+ int read_len = 0;
+ Timer t;
+ for(int n = 0; read_len < size; n++) {
+ int size2 = std::min(size-read_len, max_packet_size);
+ int result = token_in(ep_bulk_in.getAddress() & 0x7f, data+read_len, size2, retryLimit);
+ if (result < 0) {
+ if (LastStatus == NAK) {
+ if (n == 0) {
+ return -1;
+ }
+ break;
+ }
+ USB_DBG("token_in result=%d %02x", result, LastStatus);
+ return result;
+ }
+ read_len += result;
+ if (result < max_packet_size) {
+ break;
+ }
+ if (timeout_ms > 0 && t.read_ms() > timeout_ms) {
+ USB_DBG("timeout_ms: %d", timeout_ms);
+ break;
+ }
+ }
+ return read_len;
+}
+
+int USBHost::BulkWrite(const uint8_t* data, int size) {
+ setAddr(dev_addr);
+ setEndpoint();
+ int max_packet_size = ep_bulk_out.getSize();
+ int write_len = 0;
+ for(int n = 0; write_len < size; n++) {
+ int size2 = std::min(size-write_len, max_packet_size);
+ int result = token_out(ep_bulk_out.getAddress(), data+write_len, size2);
+ if (result < 0) {
+ if (LastStatus == NAK) {
+ if (n == 0) {
+ return -1;
+ }
+ break;
+ }
+ //USB_DBG("token_in result=%d %02x", result, LastStatus);
+ return result;
+ }
+ write_len += result;
+ if (result < max_packet_size) {
+ break;
+ }
+ }
+ return write_len;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.h Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,113 @@
+// Simple USBHost for FRDM-KL46Z
+#pragma once
+#include "mbed.h"
+#include "USBHALHost.h"
+#include "USBEndpoint.h"
+
+class USBDeviceConnected {}; //dummy
+class IUSBEnumerator {}; // dummy
+
+class USBHost : public USBHALHost {
+public:
+ /**
+ * Static method to create or retrieve the single USBHost instance
+ */
+ static USBHost* getHostInst();
+
+ /**
+ * Control read: setup stage, data stage and status stage
+ *
+ * @param dev the control read will be done for this device
+ * @param requestType request type
+ * @param request request
+ * @param value value
+ * @param index index
+ * @param buf pointer on a buffer where will be store the data received
+ * @param len length of the transfer
+ *
+ * @returns status of the control read
+ */
+ USB_TYPE controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len);
+
+ /**
+ * Control write: setup stage, data stage and status stage
+ *
+ * @param dev the control write will be done for this device
+ * @param requestType request type
+ * @param request request
+ * @param value value
+ * @param index index
+ * @param buf pointer on a buffer which will be written
+ * @param len length of the transfer
+ *
+ * @returns status of the control write
+ */
+ USB_TYPE controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len);
+ /**
+ * Bulk read
+ *
+ * @param dev the bulk transfer will be done for this device
+ * @param ep USBEndpoint which will be used to read a packet
+ * @param buf pointer on a buffer where will be store the data received
+ * @param len length of the transfer
+ * @param blocking if true, the read is blocking (wait for completion)
+ *
+ * @returns status of the bulk read
+ */
+ USB_TYPE bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true);
+
+ /**
+ * Bulk write
+ *
+ * @param dev the bulk transfer will be done for this device
+ * @param ep USBEndpoint which will be used to write a packet
+ * @param buf pointer on a buffer which will be written
+ * @param len length of the transfer
+ * @param blocking if true, the write is blocking (wait for completion)
+ *
+ * @returns status of the bulk write
+ */
+ USB_TYPE bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true);
+
+ /**
+ * Interrupt read
+ *
+ * @param dev the interrupt transfer will be done for this device
+ * @param ep USBEndpoint which will be used to write a packet
+ * @param buf pointer on a buffer which will be written
+ * @param len length of the transfer
+ * @param blocking if true, the read is blocking (wait for completion)
+ *
+ * @returns status of the interrupt read
+ */
+ USB_TYPE interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true);
+
+ /**
+ * Interrupt write
+ *
+ * @param dev the interrupt transfer will be done for this device
+ * @param ep USBEndpoint which will be used to write a packet
+ * @param buf pointer on a buffer which will be written
+ * @param len length of the transfer
+ * @param blocking if true, the write is blocking (wait for completion)
+ *
+ * @returns status of the interrupt write
+ */
+ USB_TYPE interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true);
+
+ int ControlRead(SETUP_PACKET* setup, uint8_t* data, int size);
+ int ControlWrite(SETUP_PACKET* setup, uint8_t* data = NULL, int size = 0);
+ int BulkRead(uint8_t* data, int size, int timeout_ms = -1);
+ int BulkWrite(const uint8_t* data, int size);
+ int InterruptRead(uint8_t* data, int size);
+
+private:
+ USBHost();
+ static USBHost* inst;
+ virtual bool enumeration();
+ int dev_addr;
+ USBEndpoint ep_int_in;
+ USBEndpoint ep_bulk_in;
+ USBEndpoint ep_bulk_out;
+};
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostConf.h Sat Jan 25 12:51:44 2014 +0000 @@ -0,0 +1,86 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef USBHOST_CONF_H +#define USBHOST_CONF_H + +/* +* Maximum number of devices that can be connected +* to the usb host +*/ +#define MAX_DEVICE_CONNECTED 5 + +/* +* Maximum of Hub connected to the usb host +*/ +#define MAX_HUB_NB 2 + +/* +* Maximum number of ports on a USB hub +*/ +#define MAX_HUB_PORT 4 + +/* +* Enable USBHostMSD +*/ +#define USBHOST_MSD 1 + +/* +* Enable USBHostKeyboard +*/ +#define USBHOST_KEYBOARD 1 + +/* +* Enable USBHostMouse +*/ +#define USBHOST_MOUSE 1 + +/* +* Enable USBHostSerial or USBHostMultiSerial (if set > 1) +*/ +#define USBHOST_SERIAL 1 + +/* +* Enable USB3Gmodule +*/ +#define USBHOST_3GMODULE 1 + +/* +* Maximum number of interfaces of a usb device +*/ +#define MAX_INTF 4 + +/* +* Maximum number of endpoints on each interface +*/ +#define MAX_ENDPOINT_PER_INTERFACE 3 + +/* +* Maximum number of endpoint descriptors that can be allocated +*/ +#define MAX_ENDPOINT (MAX_DEVICE_CONNECTED * MAX_INTF * MAX_ENDPOINT_PER_INTERFACE) + +/* +* Maximum number of transfer descriptors that can be allocated +*/ +#define MAX_TD (MAX_ENDPOINT*2) + +/* +* usb_thread stack size +*/ +#define USB_THREAD_STACK (256*4 + MAX_HUB_NB*256*4) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostTypes.h Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,158 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USB_INC_H
+#define USB_INC_H
+
+#include "mbed.h"
+#include "toolchain.h"
+
+enum USB_TYPE {
+ USB_TYPE_OK = 0,
+
+ // completion code
+ USB_TYPE_CRC_ERROR = 1,
+ USB_TYPE_BIT_STUFFING_ERROR = 2,
+ USB_TYPE_DATA_TOGGLE_MISMATCH_ERROR = 3,
+ USB_TYPE_STALL_ERROR = 4,
+ USB_TYPE_DEVICE_NOT_RESPONDING_ERROR = 5,
+ USB_TYPE_PID_CHECK_FAILURE_ERROR = 6,
+ USB_TYPE_UNEXPECTED_PID_ERROR = 7,
+ USB_TYPE_DATA_OVERRUN_ERROR = 8,
+ USB_TYPE_DATA_UNDERRUN_ERROR = 9,
+ USB_TYPE_RESERVED = 9,
+ USB_TYPE_RESERVED_ = 10,
+ USB_TYPE_BUFFER_OVERRUN_ERROR = 12,
+ USB_TYPE_BUFFER_UNDERRUN_ERROR = 13,
+
+ // general usb state
+ USB_TYPE_DISCONNECTED = 14,
+ USB_TYPE_FREE = 15,
+ USB_TYPE_IDLE = 16,
+ USB_TYPE_PROCESSING = 17,
+
+ USB_TYPE_ERROR = 18,
+};
+
+
+enum ENDPOINT_DIRECTION {
+ OUT = 1,
+ IN
+};
+
+enum ENDPOINT_TYPE {
+ CONTROL_ENDPOINT = 0,
+ ISOCHRONOUS_ENDPOINT,
+ BULK_ENDPOINT,
+ INTERRUPT_ENDPOINT
+};
+
+#define AUDIO_CLASS 0x01
+#define CDC_CLASS 0x02
+#define HID_CLASS 0x03
+#define MSD_CLASS 0x08
+#define HUB_CLASS 0x09
+#define SERIAL_CLASS 0x0A
+
+#define DEVICE_DESCRIPTOR (1)
+#define CONFIGURATION_DESCRIPTOR (2)
+#define INTERFACE_DESCRIPTOR (4)
+#define ENDPOINT_DESCRIPTOR (5)
+#define HID_DESCRIPTOR (33)
+
+// ----------- Control RequestType Fields -----------
+#define USB_DEVICE_TO_HOST 0x80
+#define USB_HOST_TO_DEVICE 0x00
+#define USB_REQUEST_TYPE_CLASS 0x20
+#define USB_REQUEST_TYPE_STANDARD 0x00
+#define USB_RECIPIENT_DEVICE 0x00
+#define USB_RECIPIENT_INTERFACE 0x01
+#define USB_RECIPIENT_ENDPOINT 0x02
+
+// -------------- USB Standard Requests --------------
+#define SET_ADDRESS 0x05
+#define GET_DESCRIPTOR 0x06
+#define SET_CONFIGURATION 0x09
+#define SET_INTERFACE 0x0b
+#define CLEAR_FEATURE 0x01
+
+// -------------- USB Descriptor Length --------------
+#define DEVICE_DESCRIPTOR_LENGTH 0x12
+#define CONFIGURATION_DESCRIPTOR_LENGTH 0x09
+
+#pragma pack(push,1)
+typedef struct {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdUSB;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize;
+ uint16_t idVendor;
+ uint16_t idProduct;
+ uint16_t bcdDevice;
+ uint8_t iManufacturer;
+ uint8_t iProduct;
+ uint8_t iSerialNumber;
+ uint8_t bNumConfigurations;
+} PACKED DeviceDescriptor;
+
+typedef struct {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength;
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t bMaxPower;
+} PACKED ConfigurationDescriptor;
+
+typedef struct {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceClass;
+ uint8_t bInterfaceSubClass;
+ uint8_t bInterfaceProtocol;
+ uint8_t iInterface;
+} InterfaceDescriptor;
+
+typedef struct {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint16_t wMaxPacketSize;
+ uint8_t bInterval;
+} EndpointDescriptor;
+
+typedef struct {
+ uint8_t bDescLength;
+ uint8_t bDescriptorType;
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint8_t DeviceRemovable;
+ uint8_t PortPweCtrlMak;
+} HubDescriptor;
+#pragma pack(pop)
+
+#endif
--- a/USBHostGPS.h Thu Jan 23 08:32:54 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-// Simple USBHost GPS Dongle for FRDM-KL46Z
-#include "USBHost.h"
-
-#define PL2303_SET_LINE_CODING 0x20
-
-class USBHostGPS {
-public:
- USBHostGPS(int baud = 38400) {
- host = USBHost::getHostInst();
- // stop bit = 1, parity = none, 8bit
- uint8_t data[] = {baud&0xff, baud>>8, baud>>16, baud>>24, 0x00, 0x00, 0x08};
- SETUP_PACKET setup = {0x21, PL2303_SET_LINE_CODING, 0, 0, 0};
- host->ControlWrite(&setup, data, sizeof(data));
- }
- int readNMEA(char* data, int size) {
- return host->BulkRead((uint8_t*)data, size);
- }
-
-private:
- USBHost * host;
-};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostGPS/USBHostGPS.h Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,21 @@
+// Simple USBHost GPS Dongle for FRDM-KL46Z
+#include "USBHost.h"
+
+#define PL2303_SET_LINE_CODING 0x20
+
+class USBHostGPS {
+public:
+ USBHostGPS(int baud = 38400) {
+ host = USBHost::getHostInst();
+ // stop bit = 1, parity = none, 8bit
+ uint8_t data[] = {baud&0xff, baud>>8, baud>>16, baud>>24, 0x00, 0x00, 0x08};
+ SETUP_PACKET setup = {0x21, PL2303_SET_LINE_CODING, 0, 0, 0};
+ host->ControlWrite(&setup, data, sizeof(data));
+ }
+ int readNMEA(char* data, int size) {
+ return host->BulkRead((uint8_t*)data, size);
+ }
+
+private:
+ USBHost * host;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostMouse.h Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,16 @@
+// Simple USBHost Mouse for FRDM-KL46Z
+#include "USBHost.h"
+
+class USBHostMouse {
+public:
+ USBHostMouse() {
+ host = USBHost::getHostInst();
+ }
+ int readReport(uint8_t* data) {
+ return host->InterruptRead(data, 4);
+ }
+
+private:
+ USBHost * host;
+};
+
--- a/USBHostMSD.cpp Thu Jan 23 08:32:54 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/* mbed USBHost Library
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "USBHostMSD.h"
-
-#define CBW_SIGNATURE 0x43425355
-#define CSW_SIGNATURE 0x53425355
-
-#define DEVICE_TO_HOST 0x80
-#define HOST_TO_DEVICE 0x00
-
-#define GET_MAX_LUN (0xFE)
-#define BO_MASS_STORAGE_RESET (0xFF)
-
-USBHostMSD::USBHostMSD(const char * rootdir) : FATFileSystem(rootdir)
-{
- host = USBHost::getHostInst();
- init();
-}
-
-void USBHostMSD::init() {
- dev_connected = false;
- dev = NULL;
- bulk_in = NULL;
- bulk_out = NULL;
- dev_connected = false;
- blockSize = 0;
- blockCount = 0;
- msd_intf = 1; //msd_intf = -1;
- msd_device_found = false;
- disk_init = false;
- dev_connected = false;
- nb_ep = 0;
-}
-
-
-bool USBHostMSD::connected()
-{
- return true;
-}
-
-bool USBHostMSD::connect()
-{
- return true;
-}
-
-int USBHostMSD::testUnitReady() {
- USB_DBG("Test unit ready");
- return SCSITransfer(NULL, 6, DEVICE_TO_HOST, 0, 0);
-}
-
-
-int USBHostMSD::readCapacity() {
- USB_DBG("Read capacity");
- uint8_t cmd[10] = {0x25,0,0,0,0,0,0,0,0,0};
- uint8_t result[8];
- int status = SCSITransfer(cmd, 10, DEVICE_TO_HOST, result, 8);
- if (status == 0) {
- blockCount = (result[0] << 24) | (result[1] << 16) | (result[2] << 8) | result[3];
- blockSize = (result[4] << 24) | (result[5] << 16) | (result[6] << 8) | result[7];
- USB_INFO("MSD [dev: %p] - blockCount: %lld, blockSize: %d, Capacity: %lld\r\n", dev, blockCount, blockSize, blockCount*blockSize);
- }
- return status;
-}
-
-
-int USBHostMSD::SCSIRequestSense() {
- USB_DBG("Request sense");
- uint8_t cmd[6] = {0x03,0,0,0,18,0};
- uint8_t result[18];
- int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 18);
- return status;
-}
-
-
-int USBHostMSD::inquiry(uint8_t lun, uint8_t page_code) {
- USB_DBG("Inquiry");
- uint8_t evpd = (page_code == 0) ? 0 : 1;
- uint8_t cmd[6] = {0x12, (lun << 5) | evpd, page_code, 0, 36, 0};
- uint8_t result[36];
- int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 36);
- if (status == 0) {
- char vid_pid[17];
- memcpy(vid_pid, &result[8], 8);
- vid_pid[8] = 0;
- USB_INFO("MSD [dev: %p] - Vendor ID: %s", dev, vid_pid);
-
- memcpy(vid_pid, &result[16], 16);
- vid_pid[16] = 0;
- USB_INFO("MSD [dev: %p] - Product ID: %s", dev, vid_pid);
-
- memcpy(vid_pid, &result[32], 4);
- vid_pid[4] = 0;
- USB_INFO("MSD [dev: %p] - Product rev: %s", dev, vid_pid);
- }
- return status;
-}
-
-int USBHostMSD::checkResult(uint8_t res, USBEndpoint * ep) {
- // if ep stalled: send clear feature
- if (res == USB_TYPE_STALL_ERROR) {
- res = controlWrite(dev,
- USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
- CLEAR_FEATURE,
- 0, ep->getAddress(), NULL, 0);
- // set state to IDLE if clear feature successful
- if (res == USB_TYPE_OK) {
- ep->setState(USB_TYPE_IDLE);
- }
- }
-
- if (res != USB_TYPE_OK)
- return -1;
-
- return 0;
-}
-
-
-int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len) {
-
- int res = 0;
-
- cbw.Signature = CBW_SIGNATURE;
- cbw.Tag = 0;
- cbw.DataLength = transfer_len;
- cbw.Flags = flags;
- cbw.LUN = 0;
- cbw.CBLength = cmd_len;
- memset(cbw.CB,0,sizeof(cbw.CB));
- if (cmd) {
- memcpy(cbw.CB,cmd,cmd_len);
- }
-
- // send the cbw
- USB_DBG("Send CBW");
- res = bulkWrite(dev, bulk_out,(uint8_t *)&cbw, 31);
- if (checkResult(res, bulk_out))
- return -1;
-
- // data stage if needed
- if (data) {
- USB_DBG("data stage");
- if (flags == HOST_TO_DEVICE) {
-
- res = bulkWrite(dev, bulk_out, data, transfer_len);
- if (checkResult(res, bulk_out))
- return -1;
-
- } else if (flags == DEVICE_TO_HOST) {
-
- res = bulkRead(dev, bulk_in, data, transfer_len);
- if (checkResult(res, bulk_in))
- return -1;
- }
- }
-
- // status stage
- csw.Signature = 0;
- USB_DBG("Read CSW");
- res = bulkRead(dev, bulk_in,(uint8_t *)&csw, 13);
- if (checkResult(res, bulk_in))
- return -1;
-
- if (csw.Signature != CSW_SIGNATURE) {
- return -1;
- }
-
- USB_DBG("recv csw: status: %d", csw.Status);
-
- // ModeSense?
- if ((csw.Status == 1) && (cmd[0] != 0x03)) {
- USB_DBG("request mode sense");
- return SCSIRequestSense();
- }
-
- // perform reset recovery
- if ((csw.Status == 2) && (cmd[0] != 0x03)) {
-
- // send Bulk-Only Mass Storage Reset request
- res = controlWrite( dev,
- USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
- BO_MASS_STORAGE_RESET,
- 0, msd_intf, NULL, 0);
-
- // unstall both endpoints
- res = controlWrite( dev,
- USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
- CLEAR_FEATURE,
- 0, bulk_in->getAddress(), NULL, 0);
-
- res = controlWrite( dev,
- USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
- CLEAR_FEATURE,
- 0, bulk_out->getAddress(), NULL, 0);
-
- }
-
- return csw.Status;
-}
-
-
-int USBHostMSD::dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction) {
- uint8_t cmd[10];
- memset(cmd,0,10);
- cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
-
- cmd[2] = (block >> 24) & 0xff;
- cmd[3] = (block >> 16) & 0xff;
- cmd[4] = (block >> 8) & 0xff;
- cmd[5] = block & 0xff;
-
- cmd[7] = (nbBlock >> 8) & 0xff;
- cmd[8] = nbBlock & 0xff;
-
- return SCSITransfer(cmd, 10, direction, buf, blockSize*nbBlock);
-}
-
-int USBHostMSD::getMaxLun() {
- uint8_t buf[1], res;
- res = controlRead( dev, USB_RECIPIENT_INTERFACE | USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS,
- 0xfe, 0, msd_intf, buf, 1);
- USB_DBG("max lun: %d", buf[0]);
- return res;
-}
-
-int USBHostMSD::disk_initialize() {
- USB_DBG("FILESYSTEM: init");
- int i, timeout = 10;
-
- //getMaxLun();
-
- for (i = 0; i < timeout; i++) {
- wait_ms(100);
- if (!testUnitReady())
- break;
- }
-
- if (i == timeout) {
- disk_init = false;
- return -1;
- }
-
- inquiry(0, 0);
- disk_init = 1;
- return readCapacity();
-}
-
-int USBHostMSD::disk_write(const uint8_t *buffer, uint64_t block_number) {
- USB_DBG("FILESYSTEM: write block: %lld", block_number);
- if (!disk_init) {
- disk_initialize();
- }
- if (!disk_init)
- return -1;
- return dataTransfer((uint8_t *)buffer, block_number, 1, HOST_TO_DEVICE);
-}
-
-int USBHostMSD::disk_read(uint8_t * buffer, uint64_t block_number) {
- USB_DBG("FILESYSTEM: read block %lld", block_number);
- if (!disk_init) {
- disk_initialize();
- }
- if (!disk_init)
- return -1;
- return dataTransfer((uint8_t *)buffer, block_number, 1, DEVICE_TO_HOST);
-}
-
-uint64_t USBHostMSD::disk_sectors() {
- USB_DBG("FILESYSTEM: sectors");
- if (!disk_init) {
- disk_initialize();
- }
- if (!disk_init)
- return 0;
- return blockCount;
-}
-
--- a/USBHostMSD.h Thu Jan 23 08:32:54 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/* mbed USBHost Library
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef USBHOSTMSD_H
-#define USBHOSTMSD_H
-
-#if 0
-#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0);
-#else
-#define USB_DBG(...) while(0);
-#endif
-
-#define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0);
-
-#if 1
-#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");}while(0);
-#else
-#define USB_INFO(...) while(0);
-#endif
-
-//#include "USBHostConf.h"
-enum USB_TYPE {
- USB_TYPE_OK = 0,
- // completion code
- USB_TYPE_STALL_ERROR = 4,
- // general usb state
- USB_TYPE_IDLE = 16,
- USB_TYPE_ERROR = 18,
-};
-
-// ----------- Control RequestType Fields -----------
-#define USB_DEVICE_TO_HOST 0x80
-#define USB_HOST_TO_DEVICE 0x00
-#define USB_REQUEST_TYPE_CLASS 0x20
-#define USB_REQUEST_TYPE_STANDARD 0x00
-#define USB_RECIPIENT_DEVICE 0x00
-#define USB_RECIPIENT_INTERFACE 0x01
-#define USB_RECIPIENT_ENDPOINT 0x02
-
-// -------------- USB Standard Requests --------------
-#define CLEAR_FEATURE 0x01
-
-#include "USBHost.h"
-#include "FATFileSystem.h"
-
-class USBDeviceConnected { //dummy
-};
-
-struct USBEndpoint { // dummy
- void setState(uint8_t st){};
- uint8_t getAddress(){ return 0; };
-};
-
-/**
- * A class to communicate a USB flash disk
- */
-class USBHostMSD : public FATFileSystem {
-public:
- /**
- * Constructor
- *
- * @param rootdir mount name
- */
- USBHostMSD(const char * rootdir);
-
- /**
- * Check if a MSD device is connected
- *
- * @return true if a MSD device is connected
- */
- bool connected();
-
- /**
- * Try to connect to a MSD device
- *
- * @return true if connection was successful
- */
- bool connect();
-
-protected:
-
- // From FATFileSystem
- virtual int disk_initialize();
- virtual int disk_status() {return 0;};
- virtual int disk_read(uint8_t * buffer, uint64_t sector);
- virtual int disk_write(const uint8_t * buffer, uint64_t sector);
- virtual int disk_sync() {return 0;};
- virtual uint64_t disk_sectors();
-
-private:
- USBHost * host;
- USBDeviceConnected * dev;
- bool dev_connected;
- USBEndpoint * bulk_in;
- USBEndpoint * bulk_out;
- uint8_t nb_ep;
-
- // Bulk-only CBW
- typedef __packed struct {
- uint32_t Signature;
- uint32_t Tag;
- uint32_t DataLength;
- uint8_t Flags;
- uint8_t LUN;
- uint8_t CBLength;
- uint8_t CB[16];
- } CBW;
-
- // Bulk-only CSW
- typedef __packed struct {
- uint32_t Signature;
- uint32_t Tag;
- uint32_t DataResidue;
- uint8_t Status;
- } CSW;
-
- CBW cbw;
- CSW csw;
-
- int SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len);
- int testUnitReady();
- int readCapacity();
- int inquiry(uint8_t lun, uint8_t page_code);
- int SCSIRequestSense();
- int dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction);
- int checkResult(uint8_t res, USBEndpoint * ep);
- int getMaxLun();
-
- int blockSize;
- uint64_t blockCount;
-
- int msd_intf;
- bool msd_device_found;
- bool disk_init;
-
- void init();
-
- // KL46Z-USBHost interface
- USB_TYPE controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
- SETUP_PACKET setup = {requestType, request, value, index};
- int result = host->ControlRead(&setup, buf, len);
- USB_DBG2("result=%d %02x", result, host->LastStatus);
- return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR;
- }
-
- USB_TYPE controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
- SETUP_PACKET setup = {requestType, request, value, index};
- int result = host->ControlWrite(&setup, buf, len);
- USB_DBG2("result=%d %02x", result, host->LastStatus);
- return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR;
- }
-
- USB_TYPE bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true) {
- int result = host->BulkRead(buf, len);
- if (result >= 0) {
- return USB_TYPE_OK;
- }
- //USB_DBG2("result=%d %02x", result, host->LastStatus);
- return USB_TYPE_ERROR;
- }
-
- USB_TYPE bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true) {
- int result = host->BulkWrite(buf, len);
- if (result >= 0) {
- return USB_TYPE_OK;
- }
- USB_DBG2("result=%d %02x", result, host->LastStatus);
- return USB_TYPE_ERROR;
- }
-};
-
-#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostMSD/FATFileSystem.lib Sat Jan 25 12:51:44 2014 +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/USBHostMSD/USBHostMSD.cpp Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,291 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "USBHostMSD.h"
+
+#define CBW_SIGNATURE 0x43425355
+#define CSW_SIGNATURE 0x53425355
+
+#define DEVICE_TO_HOST 0x80
+#define HOST_TO_DEVICE 0x00
+
+#define GET_MAX_LUN (0xFE)
+#define BO_MASS_STORAGE_RESET (0xFF)
+
+USBHostMSD::USBHostMSD(const char * rootdir) : FATFileSystem(rootdir)
+{
+ host = USBHost::getHostInst();
+ init();
+ report = &host->report;
+}
+
+void USBHostMSD::init() {
+ dev_connected = false;
+ dev = NULL;
+ bulk_in = NULL;
+ bulk_out = NULL;
+ dev_connected = false;
+ blockSize = 0;
+ blockCount = 0;
+ msd_intf = 1; //msd_intf = -1;
+ msd_device_found = false;
+ disk_init = false;
+ dev_connected = false;
+ nb_ep = 0;
+}
+
+
+bool USBHostMSD::connected()
+{
+ return true;
+}
+
+bool USBHostMSD::connect()
+{
+ return true;
+}
+
+int USBHostMSD::testUnitReady() {
+ USB_DBG("Test unit ready");
+ return SCSITransfer(NULL, 6, DEVICE_TO_HOST, 0, 0);
+}
+
+
+int USBHostMSD::readCapacity() {
+ USB_DBG("Read capacity");
+ uint8_t cmd[10] = {0x25,0,0,0,0,0,0,0,0,0};
+ uint8_t result[8];
+ int status = SCSITransfer(cmd, 10, DEVICE_TO_HOST, result, 8);
+ if (status == 0) {
+ blockCount = (result[0] << 24) | (result[1] << 16) | (result[2] << 8) | result[3];
+ blockSize = (result[4] << 24) | (result[5] << 16) | (result[6] << 8) | result[7];
+ USB_INFO("MSD blockCount: %lld, blockSize: %d, Capacity: %lld\r\n", blockCount, blockSize, blockCount*blockSize);
+ }
+ return status;
+}
+
+
+int USBHostMSD::SCSIRequestSense() {
+ USB_DBG("Request sense");
+ uint8_t cmd[6] = {0x03,0,0,0,18,0};
+ uint8_t result[18];
+ int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 18);
+ return status;
+}
+
+
+int USBHostMSD::inquiry(uint8_t lun, uint8_t page_code) {
+ USB_DBG("Inquiry");
+ uint8_t evpd = (page_code == 0) ? 0 : 1;
+ uint8_t cmd[6] = {0x12, (lun << 5) | evpd, page_code, 0, 36, 0};
+ uint8_t result[36];
+ int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 36);
+ if (status == 0) {
+ char vid_pid[17];
+ memcpy(vid_pid, &result[8], 8);
+ vid_pid[8] = 0;
+ USB_INFO("MSD Vendor ID: %s", vid_pid);
+
+ memcpy(vid_pid, &result[16], 16);
+ vid_pid[16] = 0;
+ USB_INFO("MSD Product ID: %s", vid_pid);
+
+ memcpy(vid_pid, &result[32], 4);
+ vid_pid[4] = 0;
+ USB_INFO("MSD Product rev: %s", vid_pid);
+ }
+ return status;
+}
+
+int USBHostMSD::checkResult(uint8_t res, USBEndpoint * ep) {
+ // if ep stalled: send clear feature
+ if (res == USB_TYPE_STALL_ERROR) {
+ res = host->controlWrite(dev,
+ USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
+ CLEAR_FEATURE,
+ 0, ep->getAddress(), NULL, 0);
+ // set state to IDLE if clear feature successful
+ if (res == USB_TYPE_OK) {
+ ep->setState(USB_TYPE_IDLE);
+ }
+ }
+
+ if (res != USB_TYPE_OK)
+ return -1;
+
+ return 0;
+}
+
+
+int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len) {
+
+ int res = 0;
+
+ cbw.Signature = CBW_SIGNATURE;
+ cbw.Tag = 0;
+ cbw.DataLength = transfer_len;
+ cbw.Flags = flags;
+ cbw.LUN = 0;
+ cbw.CBLength = cmd_len;
+ memset(cbw.CB,0,sizeof(cbw.CB));
+ if (cmd) {
+ memcpy(cbw.CB,cmd,cmd_len);
+ }
+
+ // send the cbw
+ USB_DBG("Send CBW");
+ res = host->bulkWrite(dev, bulk_out,(uint8_t *)&cbw, 31);
+ if (checkResult(res, bulk_out))
+ return -1;
+
+ // data stage if needed
+ if (data) {
+ USB_DBG("data stage");
+ if (flags == HOST_TO_DEVICE) {
+
+ res = host->bulkWrite(dev, bulk_out, data, transfer_len);
+ if (checkResult(res, bulk_out))
+ return -1;
+
+ } else if (flags == DEVICE_TO_HOST) {
+
+ res = host->bulkRead(dev, bulk_in, data, transfer_len);
+ if (checkResult(res, bulk_in))
+ return -1;
+ }
+ }
+
+ // status stage
+ csw.Signature = 0;
+ USB_DBG("Read CSW");
+ res = host->bulkRead(dev, bulk_in,(uint8_t *)&csw, 13);
+ if (checkResult(res, bulk_in))
+ return -1;
+
+ if (csw.Signature != CSW_SIGNATURE) {
+ return -1;
+ }
+
+ USB_DBG("recv csw: status: %d", csw.Status);
+
+ // ModeSense?
+ if ((csw.Status == 1) && (cmd[0] != 0x03)) {
+ USB_DBG("request mode sense");
+ return SCSIRequestSense();
+ }
+
+ // perform reset recovery
+ if ((csw.Status == 2) && (cmd[0] != 0x03)) {
+
+ // send Bulk-Only Mass Storage Reset request
+ res = host->controlWrite( dev,
+ USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
+ BO_MASS_STORAGE_RESET,
+ 0, msd_intf, NULL, 0);
+
+ // unstall both endpoints
+ res = host->controlWrite( dev,
+ USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
+ CLEAR_FEATURE,
+ 0, bulk_in->getAddress(), NULL, 0);
+
+ res = host->controlWrite( dev,
+ USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
+ CLEAR_FEATURE,
+ 0, bulk_out->getAddress(), NULL, 0);
+
+ }
+
+ return csw.Status;
+}
+
+
+int USBHostMSD::dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction) {
+ uint8_t cmd[10];
+ memset(cmd,0,10);
+ cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
+
+ cmd[2] = (block >> 24) & 0xff;
+ cmd[3] = (block >> 16) & 0xff;
+ cmd[4] = (block >> 8) & 0xff;
+ cmd[5] = block & 0xff;
+
+ cmd[7] = (nbBlock >> 8) & 0xff;
+ cmd[8] = nbBlock & 0xff;
+
+ return SCSITransfer(cmd, 10, direction, buf, blockSize*nbBlock);
+}
+
+int USBHostMSD::getMaxLun() {
+ uint8_t buf[1], res;
+ res = host->controlRead( dev, USB_RECIPIENT_INTERFACE | USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS,
+ 0xfe, 0, msd_intf, buf, 1);
+ USB_DBG("max lun: %d", buf[0]);
+ return res;
+}
+
+int USBHostMSD::disk_initialize() {
+ USB_DBG("FILESYSTEM: init");
+ int i, timeout = 10;
+
+ //getMaxLun();
+
+ for (i = 0; i < timeout; i++) {
+ wait_ms(100);
+ if (!testUnitReady())
+ break;
+ }
+
+ if (i == timeout) {
+ disk_init = false;
+ return -1;
+ }
+
+ inquiry(0, 0);
+ disk_init = 1;
+ return readCapacity();
+}
+
+int USBHostMSD::disk_write(const uint8_t *buffer, uint64_t block_number) {
+ USB_DBG("FILESYSTEM: write block: %lld", block_number);
+ if (!disk_init) {
+ disk_initialize();
+ }
+ if (!disk_init)
+ return -1;
+ return dataTransfer((uint8_t *)buffer, block_number, 1, HOST_TO_DEVICE);
+}
+
+int USBHostMSD::disk_read(uint8_t * buffer, uint64_t block_number) {
+ USB_DBG("FILESYSTEM: read block %lld", block_number);
+ if (!disk_init) {
+ disk_initialize();
+ }
+ if (!disk_init)
+ return -1;
+ return dataTransfer((uint8_t *)buffer, block_number, 1, DEVICE_TO_HOST);
+}
+
+uint64_t USBHostMSD::disk_sectors() {
+ USB_DBG("FILESYSTEM: sectors");
+ if (!disk_init) {
+ disk_initialize();
+ }
+ if (!disk_init)
+ return 0;
+ return blockCount;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostMSD/USBHostMSD.h Sat Jan 25 12:51:44 2014 +0000
@@ -0,0 +1,122 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USBHOSTMSD_H
+#define USBHOSTMSD_H
+
+#if 0
+#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0);
+#else
+#define USB_DBG(...) while(0);
+#endif
+
+#if 1
+#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");}while(0);
+#else
+#define USB_INFO(...) while(0);
+#endif
+
+#include "USBHostConf.h"
+#include "USBHost.h"
+#include "FATFileSystem.h"
+
+/**
+ * A class to communicate a USB flash disk
+ */
+class USBHostMSD : public FATFileSystem {
+public:
+ /**
+ * Constructor
+ *
+ * @param rootdir mount name
+ */
+ USBHostMSD(const char * rootdir);
+
+ /**
+ * Check if a MSD device is connected
+ *
+ * @return true if a MSD device is connected
+ */
+ bool connected();
+
+ /**
+ * Try to connect to a MSD device
+ *
+ * @return true if connection was successful
+ */
+ bool connect();
+
+ Report* report;
+protected:
+
+ // From FATFileSystem
+ virtual int disk_initialize();
+ virtual int disk_status() {return 0;};
+ virtual int disk_read(uint8_t * buffer, uint64_t sector);
+ virtual int disk_write(const uint8_t * buffer, uint64_t sector);
+ virtual int disk_sync() {return 0;};
+ virtual uint64_t disk_sectors();
+
+private:
+ USBHost * host;
+ USBDeviceConnected * dev;
+ bool dev_connected;
+ USBEndpoint * bulk_in;
+ USBEndpoint * bulk_out;
+ uint8_t nb_ep;
+
+ // Bulk-only CBW
+ typedef __packed struct {
+ uint32_t Signature;
+ uint32_t Tag;
+ uint32_t DataLength;
+ uint8_t Flags;
+ uint8_t LUN;
+ uint8_t CBLength;
+ uint8_t CB[16];
+ } CBW;
+
+ // Bulk-only CSW
+ typedef __packed struct {
+ uint32_t Signature;
+ uint32_t Tag;
+ uint32_t DataResidue;
+ uint8_t Status;
+ } CSW;
+
+ CBW cbw;
+ CSW csw;
+
+ int SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len);
+ int testUnitReady();
+ int readCapacity();
+ int inquiry(uint8_t lun, uint8_t page_code);
+ int SCSIRequestSense();
+ int dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction);
+ int checkResult(uint8_t res, USBEndpoint * ep);
+ int getMaxLun();
+
+ int blockSize;
+ uint64_t blockCount;
+
+ int msd_intf;
+ bool msd_device_found;
+ bool disk_init;
+
+ void init();
+};
+
+#endif
--- a/USBHostMouse.h Thu Jan 23 08:32:54 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-// Simple USBHost Mouse for FRDM-KL46Z
-#include "USBHost.h"
-
-class USBHostMouse {
-public:
- USBHostMouse() {
- host = USBHost::getHostInst();
- }
- int readReport(uint8_t* data) {
- return host->InterruptRead(data, 4);
- }
-
-private:
- USBHost * host;
-};
-
