Usb read
Dependencies: FATFileSystem
Fork of F401RE-USBHost by
Revision 9:7f9f64cf5ded, committed 2014-02-03
- Comitter:
- va009039
- Date:
- Mon Feb 03 13:00:16 2014 +0000
- Parent:
- 8:6463cd1964c0
- Child:
- 10:40c7f6788902
- Commit message:
- add interrupt write transfer.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Mon Feb 03 13:00:16 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/FATFileSystem/#b6669c987c8e
--- a/USBHost/USBDeviceConnected.cpp Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBDeviceConnected.cpp Mon Feb 03 13:00:16 2014 +0000 @@ -15,8 +15,7 @@ */ #include "USBDeviceConnected.h" -//#include "dbg.h" -#define USB_DBG(...) while(0) +#include "dbg.h" USBDeviceConnected::USBDeviceConnected() { init(); @@ -35,54 +34,33 @@ device_subclass = 0; proto = 0; lowSpeed = false; - for (int i = 0; i < MAX_INTF; i++) { - memset((void *)&intf[i], 0, sizeof(INTERFACE)); - intf[i].in_use = false; - for (int j = 0; j < MAX_ENDPOINT_PER_INTERFACE; j++) { - intf[i].ep[j] = NULL; - //strcpy(intf[i].name, "Unknown"); - } - } + intf.clear(); //hub_parent = NULL; //hub = NULL; - nb_interf = 0; -} - -INTERFACE * USBDeviceConnected::getInterface(uint8_t index) { - if (index >= MAX_INTF) - return NULL; - - if (intf[index].in_use) - return &intf[index]; - - return NULL; } bool USBDeviceConnected::addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) { - if ((intf_nb >= MAX_INTF) || (intf[intf_nb].in_use)) { + USB_DBG("intf_nb=%d", intf_nb); + INTERFACE* inter = intf.get(intf_nb); + if (inter) { return false; - } - intf[intf_nb].in_use = true; - intf[intf_nb].intf_class = intf_class; - intf[intf_nb].intf_subclass = intf_subclass; - intf[intf_nb].intf_protocol = intf_protocol; - intf[intf_nb].nb_endpoint = 0; + } + inter = new INTERFACE; + inter->in_use = true; + inter->intf_class = intf_class; + inter->intf_subclass = intf_subclass; + inter->intf_protocol = intf_protocol; + intf.put(intf_nb, inter); return true; } bool USBDeviceConnected::addEndpoint(uint8_t intf_nb, USBEndpoint * ept) { - if ((intf_nb >= MAX_INTF) || (intf[intf_nb].in_use == false) || (intf[intf_nb].nb_endpoint >= MAX_ENDPOINT_PER_INTERFACE)) { + INTERFACE* inter = intf.get(intf_nb); + if (inter == NULL) { return false; } - intf[intf_nb].nb_endpoint++; - - for (int i = 0; i < MAX_ENDPOINT_PER_INTERFACE; i++) { - if (intf[intf_nb].ep[i] == NULL) { - intf[intf_nb].ep[i] = ept; - return true; - } - } - return false; + inter->ep.push(ept); + return true; } void USBDeviceConnected::init(uint8_t hub_, uint8_t port_, bool lowSpeed_) { @@ -102,15 +80,15 @@ USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index) { - if (intf_nb >= MAX_INTF) { - return NULL; - } - for (int i = 0; i < MAX_ENDPOINT_PER_INTERFACE; i++) { - if ((intf[intf_nb].ep[i]->getType() == type) && (intf[intf_nb].ep[i]->getDir() == dir)) { + USB_DBG("intf_nb=%d", intf_nb); + INTERFACE* inter = intf.get(intf_nb); + USB_TEST_ASSERT(inter); + for (int i = 0; i < inter->ep.size(); i++) { + if ((inter->ep.at(i)->getType() == type) && (inter->ep.at(i)->getDir() == dir)) { if(index) { index--; } else { - return intf[intf_nb].ep[i]; + return inter->ep.at(i); } } } @@ -118,8 +96,7 @@ } USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, uint8_t index) { - if ((intf_nb >= MAX_INTF) || (index >= MAX_ENDPOINT_PER_INTERFACE)) { - return NULL; - } - return intf[intf_nb].ep[index]; + INTERFACE* inter = intf.get(intf_nb); + USB_TEST_ASSERT(inter); + return inter->ep.at(index); }
--- a/USBHost/USBDeviceConnected.h Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBDeviceConnected.h Mon Feb 03 13:00:16 2014 +0000 @@ -17,19 +17,25 @@ #include "USBEndpoint.h" #include "USBHostConf.h" +#include "myqueue.h" +#include "mymap.h" class USBEndpoint; -typedef struct { +struct INTERFACE { + INTERFACE() { + in_use = false; + intf_class = 0; + intf_subclass = 0; + intf_protocol = 0; + ep.clear(); + } bool in_use; - uint8_t nb_endpoint; uint8_t intf_class; uint8_t intf_subclass; uint8_t intf_protocol; - USBEndpoint * ep[MAX_ENDPOINT_PER_INTERFACE]; - //FunctionPointer detach; - //char name[10]; -} INTERFACE; + myqueue<USBEndpoint*>ep; +}; /** * USBDeviceConnected class @@ -83,14 +89,6 @@ bool addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); /** - * Get a specific interface - * - * @param index index of the interface to be fetched - * @returns interface - */ - INTERFACE * getInterface(uint8_t index); - - /** * Disconnect the device by calling a callback function registered by a driver */ void disconnect(); @@ -122,7 +120,7 @@ USBEndpoint* getEpCtl() { return ep_ctl; } private: - INTERFACE intf[MAX_INTF]; + mymap<int,INTERFACE*>intf; uint8_t hub_nb; uint8_t port; uint16_t vid;
--- a/USBHost/USBEndpoint.h Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBEndpoint.h Mon Feb 03 13:00:16 2014 +0000 @@ -15,17 +15,58 @@ */ #pragma once +#include "FunctionPointer.h" #include "USBHostTypes.h" #include "USBDeviceConnected.h" + class USBDeviceConnected; +/** +* USBEndpoint class +*/ class USBEndpoint { public: + /** + * Constructor + */ USBEndpoint() : data01_toggle(DATA0),address(0),MaxPacketSize(8) { dev = NULL; } + + /** + * Attach a member function to call when a transfer is finished + * + * @param tptr pointer to the object to call the member function on + * @param mptr pointer to the member function to be called + */ + template<typename T> + inline void attach(T* tptr, void (T::*mptr)(void)) { + if((mptr != NULL) && (tptr != NULL)) { + rx.attach(tptr, mptr); + } + } + + /** + * Attach a callback called when a transfer is finished + * + * @param fptr function pointer + */ + inline void attach(void (*fptr)(void)) { + if(fptr != NULL) { + rx.attach(fptr); + } + } + + /** + * Call the handler associted to the end of a transfer + */ + inline void call() { + rx.call(); + }; + void setDevice(USBDeviceConnected* _dev) { dev = _dev; } void setState(uint8_t st){}; // dummy + void setBuffer(uint8_t* buf, int size) { buf_start = buf, buf_size = size; } void setLengthTransferred(int len) { transferred = len; }; void setSize(int size) { MaxPacketSize = size; } void setType(ENDPOINT_TYPE _type) { type = _type; }; @@ -35,6 +76,8 @@ USBDeviceConnected* getDevice() { return dev; } ENDPOINT_TYPE getType() { return type; }; int getLengthTransferred() { return transferred; } + uint8_t *getBufStart() { return buf_start; } + int getBufSize() { return buf_size; } uint8_t getAddress(){ return address; }; int getSize() { return MaxPacketSize; } ENDPOINT_DIRECTION getDir() { return (address & 0x80) ? IN : OUT; } @@ -49,6 +92,12 @@ USBDeviceConnected* dev; uint8_t data01_toggle; // DATA0,DATA1 uint8_t address; + int transferred; + uint8_t * buf_start; + int buf_size; + + FunctionPointer rx; + int MaxPacketSize; };
--- a/USBHost/USBHALHost.cpp Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBHALHost.cpp Mon Feb 03 13:00:16 2014 +0000 @@ -23,6 +23,8 @@ #define USB_TEST_ASSERT_FALSE(A) while(0) #endif +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); + #define BD_OWN_MASK (1<<7) #define BD_DATA01_MASK (1<<6) #define BD_KEEP_MASK (1<<5) @@ -138,7 +140,15 @@ bool USBHALHost::wait_attach() { attach_done = false; USB0->INTEN = USB_INTEN_ATTACHEN_MASK; - while(!attach_done); + Timer t; + t.reset(); + t.start(); + while(!attach_done) { + if (t.read_ms() > 5*1000) { + t.reset(); + USB_INFO("Please attach USB device."); + } + } wait_ms(100); USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK); root_lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true;
--- a/USBHost/USBHost.cpp Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBHost.cpp Mon Feb 03 13:00:16 2014 +0000 @@ -2,34 +2,6 @@ #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 - -#ifdef _USB_TEST -#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)) -#else -#define USB_TEST_ASSERT(A) while(0) -#define USB_TEST_ASSERT_FALSE(A) while(0) -#endif - -#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0); - USBHost* USBHost::inst = NULL; USBHost* USBHost::getHostInst() @@ -41,8 +13,14 @@ return inst; } +void USBHost::poll() +{ + if (inst) { + inst->task(); + } +} + USBHost::USBHost() { - DeviceLists_count = 0; } /* virtual */ bool USBHost::addDevice(int hub, int port, bool lowSpeed) { @@ -74,12 +52,11 @@ dev->setVid(dev_desc->idVendor); dev->setPid(dev_desc->idProduct); dev->setClass(dev_desc->bDeviceClass); - USB_INFO("hub: %d port: %d speed: %s vid: %04x pid: %04x class: %02x addr: %d\n", + USB_INFO("hub: %d port: %d speed: %s vid: %04x pid: %04x class: %02x addr: %d", hub, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(), dev->getAddress()); - USB_TEST_ASSERT(DeviceLists_count < MAX_DEVICE_CONNECTED); - DeviceLists[DeviceLists_count++] = dev; + DeviceLists.push(dev); if (dev->getClass() == HUB_CLASS) { const int config = 1; @@ -146,7 +123,6 @@ uint32_t index = 0; uint32_t len_desc = 0; uint8_t id = 0; - int nb_endpoints_used = 0; USBEndpoint * ep = NULL; uint8_t intf_nb = 0; bool parsing_intf = false; @@ -156,6 +132,7 @@ while (index < len) { len_desc = conf_descr[index]; id = conf_descr[index+1]; + USB_DBG_HEX(conf_descr+index, len_desc); switch (id) { case CONFIGURATION_DESCRIPTOR: USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); @@ -163,14 +140,10 @@ break; case INTERFACE_DESCRIPTOR: if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { - if (intf_nb++ <= MAX_INTF) { - current_intf = conf_descr[index + 2]; - dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); - nb_endpoints_used = 0; - USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); - } else { - USB_DBG("Drop intf..."); - } + intf_nb++; + current_intf = conf_descr[index + 2]; + dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); + USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); parsing_intf = true; } else { parsing_intf = false; @@ -179,19 +152,16 @@ case ENDPOINT_DESCRIPTOR: ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index); if (parsing_intf && (intf_nb <= MAX_INTF) ) { - if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) { - ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); - ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; - if(pEnumerator->useEndpoint(current_intf, type, dir)) { - ep = new USBEndpoint; - ep->setDevice(dev); - ep->setType(type); - ep->setAddress(ep_desc->bEndpointAddress); - ep->setSize(ep_desc->wMaxPacketSize); - USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); - dev->addEndpoint(current_intf, ep); - nb_endpoints_used++; - } + ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); + ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; + if(pEnumerator->useEndpoint(current_intf, type, dir)) { + ep = new USBEndpoint; + ep->setDevice(dev); + ep->setType(type); + ep->setAddress(ep_desc->bEndpointAddress); + ep->setSize(ep_desc->wMaxPacketSize); + USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); + dev->addEndpoint(current_intf, ep); } } break; @@ -223,9 +193,14 @@ 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(ep, buf, len); +USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setType(BULK_ENDPOINT); + ep->setBuffer(buf, len); + ep_queue.push(ep); + return USB_TYPE_PROCESSING; + } + int result = bulkReadBLOCK(ep, buf, len, -1); if (result >= 0) { return USB_TYPE_OK; } @@ -233,9 +208,9 @@ return USB_TYPE_ERROR; } -USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { +USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { USB_TEST_ASSERT(blocking); - int result = BulkWrite(ep, buf, len); + int result = bulkWriteNB(ep, buf, len); if (result >= 0) { return USB_TYPE_OK; } @@ -243,12 +218,32 @@ return USB_TYPE_ERROR; } -USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { - int result = InterruptRead(ep, buf, len); - if (result >= 0) { - return USB_TYPE_OK; +USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setType(INTERRUPT_ENDPOINT); + ep->setBuffer(buf, len); + ep_queue.push(ep); + return USB_TYPE_PROCESSING; } - return USB_TYPE_ERROR; + interruptReadNB(ep, buf, len); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + USB_TEST_ASSERT(blocking); + interruptWriteNB(ep, buf, len); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setType(ISOCHRONOUS_ENDPOINT); + ep->setBuffer(buf, len); + ep_queue.push(ep); + return USB_TYPE_PROCESSING; + } + isochronousReadNB(ep, buf, len); + return USB_TYPE_OK; } int USBHost::ControlRead(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) { @@ -316,7 +311,8 @@ return write_len; } -int USBHost::InterruptRead(USBEndpoint* ep, uint8_t* data, int size) { +int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) +{ USB_TEST_ASSERT(ep); USBDeviceConnected* dev = ep->getDevice(); USB_TEST_ASSERT(dev); @@ -346,7 +342,43 @@ return read_len; } -int USBHost::BulkRead(USBEndpoint* ep, uint8_t* data, int size, int timeout_ms) { +int USBHost::interruptWriteNB(USBEndpoint* ep, const uint8_t* data, int size) +{ + USB_TEST_ASSERT(ep); + USBDeviceConnected* dev = ep->getDevice(); + USB_TEST_ASSERT(dev); + setAddr(dev->getAddress(), dev->getSpeed()); + setEndpoint(); + const int retryLimit = 0; + int transferred_len = 0; + for(int n = 0; transferred_len < size; n++) { + int size2 = std::min(size-transferred_len, ep->getSize()); + int result = token_out(ep, data+transferred_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; + } + transferred_len += result; + if (result < ep->getSize()) { + break; + } + } + ep->setLengthTransferred(transferred_len); + return transferred_len; +} + +int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) +{ + return bulkReadBLOCK(ep, data, size, 0); +} + +int USBHost::bulkReadBLOCK(USBEndpoint* ep, uint8_t* data, int size, int timeout_ms) { USB_TEST_ASSERT(ep); USBDeviceConnected* dev = ep->getDevice(); USB_TEST_ASSERT(dev); @@ -381,7 +413,7 @@ return read_len; } -int USBHost::BulkWrite(USBEndpoint* ep, const uint8_t* data, int size) { +int USBHost::bulkWriteNB(USBEndpoint* ep, const uint8_t* data, int size) { USB_TEST_ASSERT(ep); USBDeviceConnected* dev = ep->getDevice(); USB_TEST_ASSERT(dev); @@ -410,7 +442,7 @@ return write_len; } -int USBHost::IsochronousRead(USBEndpoint* ep, uint8_t* data, int size) { +int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { USBDeviceConnected* dev = ep->getDevice(); USB_TEST_ASSERT(dev); setAddr(dev->getAddress()); @@ -421,3 +453,30 @@ return result; } +void USBHost::task() +{ + if (ep_queue.empty()) { + return; + } + USBEndpoint* ep = ep_queue.pop(); + USB_TEST_ASSERT(ep); + ep->setLengthTransferred(0); + switch(ep->getType()) { + case INTERRUPT_ENDPOINT: + if (ep->getDir() == IN) { + interruptReadNB(ep, ep->getBufStart(), ep->getBufSize()); + } + break; + case BULK_ENDPOINT: + if (ep->getDir() == IN) { + bulkReadNB(ep, ep->getBufStart(), ep->getBufSize()); + } + break; + case ISOCHRONOUS_ENDPOINT: + if (ep->getDir() == IN) { + isochronousReadNB(ep, ep->getBufStart(), ep->getBufSize()); + } + break; + } + ep->call(); +}
--- a/USBHost/USBHost.h Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBHost.h Mon Feb 03 13:00:16 2014 +0000 @@ -5,7 +5,8 @@ #include "USBDeviceConnected.h" #include "IUSBEnumerator.h" #include "USBHostConf.h" -#include "USBEndpoint.h" +#include "dbg.h" +#include "myqueue.h" class USBHost : public USBHALHost { public: @@ -43,6 +44,7 @@ * @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 * @@ -96,6 +98,19 @@ USB_TYPE interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); /** + * Isochronous read + * + * @param dev the isochronous 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 isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking = true); + + /** * Enumerate a device. * * @param dev device which will be enumerated @@ -112,7 +127,7 @@ * @returns pointer on the "index" device */ USBDeviceConnected * getDevice(uint8_t index) { - return (index < DeviceLists_count) ? DeviceLists[index] : NULL; + return DeviceLists.empty() ? NULL : DeviceLists.at(index); } /** @@ -127,8 +142,13 @@ void registerDriver(USBDeviceConnected * dev, uint8_t intf, T* tptr, void (T::*mptr)(void)) { } - int BulkRead(USBEndpoint*ep, uint8_t* data, int size, int timeout_ms = -1); - int IsochronousRead(USBEndpoint*ep, uint8_t* data, int size); + // KL46Z-USBHost extensions + int interruptReadNB(USBEndpoint* ep, uint8_t* data, int size); + int interruptWriteNB(USBEndpoint* ep, const uint8_t* data, int size); + int bulkReadNB(USBEndpoint*ep, uint8_t* data, int size); + int bulkWriteNB(USBEndpoint*ep, const uint8_t* data, int size); + int isochronousReadNB(USBEndpoint*ep, uint8_t* data, int size); + static void poll(); private: USBHost(); @@ -136,13 +156,13 @@ virtual bool addDevice(int hub, int port, bool lowSpeed); void root_enumeration(USBDeviceConnected* dev); void parseConfDescr(USBDeviceConnected* dev, uint8_t* conf_descr, uint32_t len, IUSBEnumerator* pEnumerator); - USBDeviceConnected* DeviceLists[MAX_DEVICE_CONNECTED]; - int DeviceLists_count; + myqueue<USBDeviceConnected*>DeviceLists; int ControlRead(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size); int ControlWrite(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data = NULL, int size = 0); - int BulkWrite(USBEndpoint*ep, const uint8_t* data, int size); - int InterruptRead(USBEndpoint*ep, uint8_t* data, int size); + int bulkReadBLOCK(USBEndpoint*ep, uint8_t* data, int size, int timeout_ms); + void task(); + myqueue<USBEndpoint*>ep_queue; // USB HUB bool Hub(USBDeviceConnected* dev);
--- a/USBHost/USBHostConf.h Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBHostConf.h Mon Feb 03 13:00:16 2014 +0000 @@ -64,21 +64,6 @@ #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)
--- a/USBHost/USBHostHub.cpp Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBHostHub.cpp Mon Feb 03 13:00:16 2014 +0000 @@ -1,22 +1,5 @@ #include "USBHost.h" -#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) -extern void debug_hex(uint8_t* buf, int size); -#else -#define USB_DBG(...) while(0) -#define USB_DBG_HEX(A,B) while(0) -#endif - -#ifdef _USB_TEST -#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)) -#else -#define USB_TEST_ASSERT(A) while(0) -#define USB_TEST_ASSERT_FALSE(A) while(0) -#endif - #define PORT_CONNECTION 0 #define PORT_ENABLE 1 #define PORT_SUSPEND 2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/dbg.h Mon Feb 03 13:00:16 2014 +0000 @@ -0,0 +1,93 @@ +/* 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_DEBUG_H +#define USB_DEBUG_H + +//Debug is disabled by default +#ifndef DEBUG +#define DEBUG 3 /*INFO,ERR,WARN*/ +#endif +#ifndef DEBUG2 +#define DEBUG2 0 +#endif +#define DEBUG_TRANSFER 0 +#define DEBUG_EP_STATE 0 +#define DEBUG_EVENT 0 + +#if (DEBUG > 3) +#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); +//#define USB_DBG(x, ...) std::printf("[USB_DBG: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#define USB_DBG_HEX(A,B) debug_hex(A,B) +extern void debug_hex(uint8_t* buf, int size); +#define USB_DBG_ERRSTAT() report.print_errstat(); +#else +#define USB_DBG(x, ...) +#define USB_DBG_HEX(A,B) while(0) +#define USB_DBG_ERRSTAT() while(0) +#endif + +#if (DEBUG2 > 3) +#define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); +#else +#define USB_DBG2(...) while(0); +#endif + +#if (DEBUG > 2) +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");}while(0); +//#define USB_INFO(x, ...) std::printf("[USB_INFO: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_INFO(x, ...) +#endif + +#if (DEBUG > 1) +#define USB_WARN(x, ...) std::printf("[USB_WARNING: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_WARN(x, ...) +#endif + +#if (DEBUG > 0) +#define USB_ERR(x, ...) std::printf("[USB_ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_ERR(x, ...) +#endif + +#if (DEBUG_TRANSFER) +#define USB_DBG_TRANSFER(x, ...) std::printf("[USB_TRANSFER: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_DBG_TRANSFER(x, ...) +#endif + +#if (DEBUG_EVENT) +#define USB_DBG_EVENT(x, ...) std::printf("[USB_EVENT: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_DBG_EVENT(x, ...) +#endif + +template <bool>struct CtAssert; +template <>struct CtAssert<true> {}; +#define CTASSERT(A) CtAssert<A>(); + +#ifdef _USB_TEST +#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)) +#else +#define USB_TEST_ASSERT(A) while(0) +#define USB_TEST_ASSERT_FALSE(A) while(0) +#endif + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/mymap.h Mon Feb 03 13:00:16 2014 +0000 @@ -0,0 +1,53 @@ +#pragma once + +template<class K,class T> +class mymap { + struct mypair { + K key; + T value; + }; +public: + mymap() { + m_size = 0; + m_limit = 4; + m_buf = new mypair[m_limit]; + } + void put(K key, T value) { + int i = find(key); + if (i == (-1)) { + if (m_size >= m_limit) { + int new_limit = m_limit + 4; + mypair* new_buf = new mypair[new_limit]; + for(int i = 0; i < m_size; i++) { + new_buf[i] = m_buf[i]; + } + delete[] m_buf; + m_buf = new_buf; + m_limit = new_limit; + } + i = m_size++; + m_buf[i].key = key; + } + m_buf[i].value = value; + } + T get(K key) { + int i = find(key); + return (i == -1) ? NULL : m_buf[i].value; + } + bool empty() { return m_size == 0 ? true : false; } + int size() { return m_size; } + void clear() { m_size = 0; } + +private: + int find(K key) { + for(int i = 0; i < m_size; i++) { + if (m_buf[i].key == key) { + return i; + } + } + return -1; + } + int m_limit; + int m_size; + mypair *m_buf; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/myqueue.h Mon Feb 03 13:00:16 2014 +0000 @@ -0,0 +1,48 @@ +#pragma once + +template<class T> +class myqueue { +public: + myqueue() { + m_w = m_r = 0; + m_size = 0; + m_limit = 4; + m_buf = new T[m_limit]; + } + void push(T v) { + if (m_size >= m_limit) { + int new_limit = m_limit + 4; + T* new_buf = new T[new_limit]; + for(int i = 0; i < m_size; i++) { + new_buf[i] = m_buf[i]; + } + delete[] m_buf; + m_buf = new_buf; + m_limit = new_limit; + } + m_buf[m_w++] = v; + if (m_w >= m_limit) { + m_w = 0; + } + m_size++; + } + T pop() { + T v = m_buf[m_r++]; + if (m_r >= m_limit) { + m_r = 0; + } + m_size--; + return v; + } + bool empty() { return (m_w == m_r) ? true : false; } + int size() { return m_size; } + void clear() { m_size = 0; } + T at(int i) { return m_buf[i]; } + +private: + int m_limit; + int m_size; + int m_w; + int m_r; + T *m_buf; +};
--- a/USBHostGPS/USBHostGPS.cpp Fri Jan 31 13:45:07 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -#include "USBHostGPS.h" - -#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) -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) -#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); - - -USBHostGPS::USBHostGPS(int baud_) -{ - host = USBHost::getHostInst(); - init(); - baud = baud_; -} - -void USBHostGPS::init() { - dev = NULL; - bulk_in = NULL; - onUpdate = NULL; - dev_connected = false; - gps_device_found = false; - gps_intf = -1; -} - -bool USBHostGPS::connected() { - return dev_connected; -} - -bool USBHostGPS::connect() { - - if (dev_connected) { - return true; - } - - for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { - if ((dev = host->getDevice(i)) != NULL) { - if(host->enumerate(dev, this)) { - break; - } - if (gps_device_found) { - bulk_in = dev->getEndpoint(gps_intf, BULK_ENDPOINT, IN); - USB_TEST_ASSERT(bulk_in); - // stop bit = 1, parity = none, 8bit - uint8_t data[] = {baud&0xff, baud>>8, baud>>16, baud>>24, 0x00, 0x00, 0x08}; - USB_TYPE rc = host->controlWrite(dev, 0x21, PL2303_SET_LINE_CODING, 0, 0, data, sizeof(data)); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - USB_INFO("New GPS device: VID:%04x PID:%04x [dev: %p - intf: %d]\n", dev->getVid(), dev->getPid(), dev, gps_intf); - dev_connected = true; - return true; - } - } - } - init(); - return false; -} - -/*virtual*/ void USBHostGPS::setVidPid(uint16_t vid, uint16_t pid) -{ - USB_DBG("vid:%04x pid:%04x", vid, pid); - if (pid == 0x2303) { - gps_device_found = true; - } -} - -/*virtual*/ bool USBHostGPS::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed -{ - USB_DBG("intf: %d class: %02x %02x %02x", intf_nb, intf_class, intf_subclass, intf_protocol); - if (gps_device_found) { - if (gps_intf == -1) { - gps_intf = intf_nb; - return true; - } - } - return false; -} - -/*virtual*/ bool USBHostGPS::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used -{ - USB_DBG("intf_nb=%d type=%d dir=%d", intf_nb, type, dir); - if (gps_device_found) { - if (intf_nb == gps_intf) { - if (type == BULK_ENDPOINT && dir == IN) { - return true; - } - } - } - return false; -} -
--- a/USBHostGPS/USBHostGPS.h Fri Jan 31 13:45:07 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -// Simple USBHost GPS Dongle for FRDM-KL46Z -#include "USBHost.h" - -#define PL2303_SET_LINE_CODING 0x20 - -class USBHostGPS : public IUSBEnumerator { -public: - - /** - * Constructor - */ - USBHostGPS(int baud = 38400); - - /** - * Try to connect a USB GPS device - * - * @return true if connection was successful - */ - bool connect(); - - /** - * Check if a USB GPS is connected - * - * @returns true if a mouse is connected - */ - bool connected(); - - int readNMEA(char* data, int size, int timeout_ms) { - int result = host->BulkRead(bulk_in, (uint8_t*)data, size, timeout_ms); - return (result >= 0) ? bulk_in->getLengthTransferred() : 0; - } - void attachEvent(void (*ptr)(uint8_t* data, int size)) { - if (ptr != NULL) { - onUpdate = ptr; - } - } - void poll() { - int result = host->BulkRead(bulk_in, buf, sizeof(buf), 0); - if (result >= 0) { - if (onUpdate) { - (*onUpdate)(buf, bulk_in->getLengthTransferred()); - } - } - } - -protected: - //From IUSBEnumerator - virtual void setVidPid(uint16_t vid, uint16_t pid); - virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed - virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used - -private: - USBHost * host; - USBDeviceConnected* dev; - USBEndpoint* bulk_in; - bool dev_connected; - bool gps_device_found; - int gps_intf; - void (*onUpdate)(uint8_t* data, int size); - uint8_t buf[64]; - int baud; - void init(); -};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostHID/USBHostKeyboard.cpp Mon Feb 03 13:00:16 2014 +0000 @@ -0,0 +1,184 @@ +/* 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 "USBHostKeyboard.h" + +#if USBHOST_KEYBOARD + +static uint8_t keymap[4][0x39] = { + { 0, 0, 0, 0, 'a', 'b' /*0x05*/, + 'c', 'd', 'e', 'f', 'g' /*0x0a*/, + 'h', 'i', 'j', 'k', 'l'/*0x0f*/, + 'm', 'n', 'o', 'p', 'q'/*0x14*/, + 'r', 's', 't', 'u', 'v'/*0x19*/, + 'w', 'x', 'y', 'z', '1'/*0x1E*/, + '2', '3', '4', '5', '6'/*0x23*/, + '7', '8', '9', '0', 0x0A /*enter*/, /*0x28*/ + 0x1B /*escape*/, 0x08 /*backspace*/, 0x09/*tab*/, 0x20/*space*/, '-', /*0x2d*/ + '=', '[', ']', '\\', '#', /*0x32*/ + ';', '\'', 0, ',', '.', /*0x37*/ + '/'}, + + /* CTRL MODIFIER */ + { 0, 0, 0, 0, 0, 0 /*0x05*/, + 0, 0, 0, 0, 0 /*0x0a*/, + 0, 0, 0, 0, 0/*0x0f*/, + 0, 0, 0, 0, 0/*0x14*/, + 0, 0, 0, 0, 0/*0x19*/, + 0, 0, 0, 0, 0/*0x1E*/, + 0, 0, 0, 0, 0/*0x23*/, + 0, 0, 0, 0, 0 /*enter*/, /*0x28*/ + 0, 0, 0, 0, 0, /*0x2d*/ + 0, 0, 0, 0, 0, /*0x32*/ + 0, 0, 0, 0, 0, /*0x37*/ + 0}, + + /* SHIFT MODIFIER */ + { 0, 0, 0, 0, 'A', 'B' /*0x05*/, + 'C', 'D', 'E', 'F', 'G' /*0x0a*/, + 'H', 'I', 'J', 'K', 'L'/*0x0f*/, + 'M', 'N', 'O', 'P', 'Q'/*0x14*/, + 'R', 'S', 'T', 'U', 'V'/*0x19*/, + 'W', 'X', 'Y', 'Z', '!'/*0x1E*/, + '@', '#', '$', '%', '^'/*0x23*/, + '&', '*', '(', ')', 0, /*0x28*/ + 0, 0, 0, 0, 0, /*0x2d*/ + '+', '{', '}', '|', '~', /*0x32*/ + ':', '"', 0, '<', '>', /*0x37*/ + '?'}, + + /* ALT MODIFIER */ + { 0, 0, 0, 0, 0, 0 /*0x05*/, + 0, 0, 0, 0, 0 /*0x0a*/, + 0, 0, 0, 0, 0/*0x0f*/, + 0, 0, 0, 0, 0/*0x14*/, + 0, 0, 0, 0, 0/*0x19*/, + 0, 0, 0, 0, 0/*0x1E*/, + 0, 0, 0, 0, 0/*0x23*/, + 0, 0, 0, 0, 0 /*enter*/, /*0x28*/ + 0, 0, 0, 0, 0, /*0x2d*/ + 0, 0, 0, 0, 0, /*0x32*/ + 0, 0, 0, 0, 0, /*0x37*/ + 0} + +}; + + +USBHostKeyboard::USBHostKeyboard() { + host = USBHost::getHostInst(); + init(); +} + + +void USBHostKeyboard::init() { + dev = NULL; + int_in = NULL; + report_id = 0; + onKey = NULL; + onKeyCode = NULL; + dev_connected = false; + keyboard_intf = -1; + keyboard_device_found = false; +} + +bool USBHostKeyboard::connected() { + return dev_connected; +} + + +bool USBHostKeyboard::connect() { + + if (dev_connected) { + return true; + } + + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { + if ((dev = host->getDevice(i)) != NULL) { + + if (host->enumerate(dev, this)) + break; + + if (keyboard_device_found) { + int_in = dev->getEndpoint(keyboard_intf, INTERRUPT_ENDPOINT, IN); + + if (!int_in) + break; + + USB_INFO("New Keyboard device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, keyboard_intf); + dev->setName("Keyboard", keyboard_intf); + host->registerDriver(dev, keyboard_intf, this, &USBHostKeyboard::init); + + int_in->attach(this, &USBHostKeyboard::rxHandler); + host->interruptRead(dev, int_in, report, int_in->getSize(), false); + + dev_connected = true; + return true; + } + } + } + init(); + return false; +} + +void USBHostKeyboard::rxHandler() { + int len = int_in->getLengthTransferred(); + int index = (len == 9) ? 1 : 0; + int len_listen = int_in->getSize(); + uint8_t key = 0; + if (len == 8 || len == 9) { + uint8_t modifier = (report[index] == 4) ? 3 : report[index]; + len_listen = len; + key = keymap[modifier][report[index + 2]]; + if (key && onKey) { + (*onKey)(key); + } + if ((report[index + 2] || modifier) && onKeyCode) { + (*onKeyCode)(report[index + 2], modifier); + } + } + if (dev && int_in) + host->interruptRead(dev, int_in, report, len_listen, false); +} + +/*virtual*/ void USBHostKeyboard::setVidPid(uint16_t vid, uint16_t pid) +{ + // we don't check VID/PID for keyboard driver +} + +/*virtual*/ bool USBHostKeyboard::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed +{ + if ((keyboard_intf == -1) && + (intf_class == HID_CLASS) && + (intf_subclass == 0x01) && + (intf_protocol == 0x01)) { + keyboard_intf = intf_nb; + return true; + } + return false; +} + +/*virtual*/ bool USBHostKeyboard::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if (intf_nb == keyboard_intf) { + if (type == INTERRUPT_ENDPOINT && dir == IN) { + keyboard_device_found = true; + return true; + } + } + return false; +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostHID/USBHostKeyboard.h Mon Feb 03 13:00:16 2014 +0000 @@ -0,0 +1,102 @@ +/* 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 USBHOSTKEYBOARD_H +#define USBHOSTKEYBOARD_H + +#include "USBHostConf.h" + +#if USBHOST_KEYBOARD + +#include "USBHost.h" + +/** + * A class to communicate a USB keyboard + */ +class USBHostKeyboard : public IUSBEnumerator { +public: + + /** + * Constructor + */ + USBHostKeyboard(); + + /** + * Try to connect a keyboard device + * + * @return true if connection was successful + */ + bool connect(); + + /** + * Check if a keyboard is connected + * + * @returns true if a keyboard is connected + */ + bool connected(); + + /** + * Attach a callback called when a keyboard event is received + * + * @param ptr function pointer + */ + inline void attach(void (*ptr)(uint8_t key)) { + if (ptr != NULL) { + onKey = ptr; + } + } + + /** + * Attach a callback called when a keyboard event is received + * + * @param ptr function pointer + */ + inline void attach(void (*ptr)(uint8_t keyCode, uint8_t modifier)) { + if (ptr != NULL) { + onKeyCode = ptr; + } + } + +protected: + //From IUSBEnumerator + virtual void setVidPid(uint16_t vid, uint16_t pid); + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used + +private: + USBHost * host; + USBDeviceConnected * dev; + USBEndpoint * int_in; + uint8_t report[9]; + int keyboard_intf; + bool keyboard_device_found; + + bool dev_connected; + + void rxHandler(); + + void (*onKey)(uint8_t key); + void (*onKeyCode)(uint8_t key, uint8_t modifier); + + int report_id; + + void init(); + +}; + +#endif + +#endif
--- a/USBHostHID/USBHostMouse.cpp Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHostHID/USBHostMouse.cpp Mon Feb 03 13:00:16 2014 +0000 @@ -1,175 +1,144 @@ -#include "USBHostMouse.h" - -#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 USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0); - -USBHostMouse::USBHostMouse() { - host = USBHost::getHostInst(); - init(); -} - -void USBHostMouse::init() { - dev = NULL; - int_in = NULL; - onUpdate = NULL; - onButtonUpdate = NULL; - onXUpdate = NULL; - onYUpdate = NULL; - onZUpdate = NULL; - report_id = 0; - dev_connected = false; - mouse_device_found = false; - mouse_intf = -1; - - buttons = 0; - x = 0; - y = 0; - z = 0; -} - -bool USBHostMouse::connected() { - return dev_connected; -} - -bool USBHostMouse::connect() { - - if (dev_connected) { - return true; - } - - for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { - if ((dev = host->getDevice(i)) != NULL) { - - if(host->enumerate(dev, this)) - break; - - if (mouse_device_found) { - - int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN); - USB_DBG("int_in=%p", int_in); - if (!int_in) - break; - - USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]\n", dev->getVid(), dev->getPid(), dev, mouse_intf); - dev->setName("Mouse", mouse_intf); - host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init); - - //int_in->attach(this, &USBHostMouse::rxHandler); - host->interruptRead(dev, int_in, report, int_in->getSize(), false); - - dev_connected = true; - return true; - } - } - } - init(); - return false; -} - -/*virtual*/ void USBHostMouse::setVidPid(uint16_t vid, uint16_t pid) -{ - USB_DBG("vid:%04x pid:%04x", vid, pid); - // we don't check VID/PID for mouse driver -} - -/*virtual*/ bool USBHostMouse::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed -{ - USB_DBG("intf: %d class: %02x %02x %02x", intf_nb, intf_class, intf_subclass, intf_protocol); - if ((mouse_intf == -1) && - (intf_class == HID_CLASS) && - (intf_subclass == 0x01) && - (intf_protocol == 0x02)) { - mouse_intf = intf_nb; - return true; - } - return false; -} - -/*virtual*/ bool USBHostMouse::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used -{ - USB_DBG("intf_nb=%d type=%d dir=%d", intf_nb, type, dir); - - if (intf_nb == mouse_intf) { - if (type == INTERRUPT_ENDPOINT && dir == IN) { - mouse_device_found = true; - return true; - } - } - return false; -} - -#if 0 -void USBHostMouse::setup() { - dev = host->getDevice(0); - if (dev->getClass() == HUB_CLASS) { - for(int i = 1; ; i++) { - dev = host->getDevice(i); - if (dev == NULL) { - break; - } - if (enumeration(dev)) { - break; - } - } - USB_TEST_ASSERT(ep_int_in); - } else { - ep_int_in = NULL; - } -} - -bool USBHostMouse::enumeration(USBDeviceConnected* dev) { - // config descriptor - uint8_t desc[4]; - int rc = host->controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - USB_DBG_HEX(desc, 4); - - int TotalLength = desc[2]|desc[3]<<8; - uint8_t* buf = new uint8_t[TotalLength]; - rc = host->controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - //USB_DBG_HEX(buf, TotalLength); - bool found = false; - for(int i = 0; i < TotalLength; ) { - int Length = buf[i]; - uint8_t DescriptorType = buf[i+1]; - if (DescriptorType == 0x04) { // interface - InterfaceDescriptor* desc = reinterpret_cast<InterfaceDescriptor*>(buf+i); - if (desc->bInterfaceClass == 0x03) { - found = true; - } - } else if (DescriptorType == 0x05) { // endpoint - EndpointDescriptor* desc = reinterpret_cast<EndpointDescriptor*>(buf+i); - if (desc->bmAttributes == 0x03 && - (desc->bEndpointAddress & 0x80)) { // interrupt in - ep_int_in = new USBEndpoint; - ep_int_in->setDevice(dev); - ep_int_in->setAddress(desc->bEndpointAddress); - ep_int_in->setSize(desc->wMaxPacketSize); - } - } - USB_DBG_HEX(buf+i, Length); - i += Length; - } - delete[] buf; - if (!found) { - return false; - } - int config = 1; - host->controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); - wait_ms(100); - return true; -} -#endif - +/* 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 "USBHostMouse.h" + +#if USBHOST_MOUSE + +USBHostMouse::USBHostMouse() { + host = USBHost::getHostInst(); + init(); +} + +void USBHostMouse::init() { + dev = NULL; + int_in = NULL; + onUpdate = NULL; + onButtonUpdate = NULL; + onXUpdate = NULL; + onYUpdate = NULL; + onZUpdate = NULL; + report_id = 0; + dev_connected = false; + mouse_device_found = false; + mouse_intf = -1; + + buttons = 0; + x = 0; + y = 0; + z = 0; +} + +bool USBHostMouse::connected() { + return dev_connected; +} + +bool USBHostMouse::connect() { + + if (dev_connected) { + return true; + } + + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { + if ((dev = host->getDevice(i)) != NULL) { + + if(host->enumerate(dev, this)) + break; + + if (mouse_device_found) { + + int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN); + if (!int_in) + break; + + USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, mouse_intf); + dev->setName("Mouse", mouse_intf); + host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init); + + int_in->attach(this, &USBHostMouse::rxHandler); + host->interruptRead(dev, int_in, report, int_in->getSize(), false); + + dev_connected = true; + return true; + } + } + } + init(); + return false; +} + +void USBHostMouse::rxHandler() { + int len_listen = int_in->getSize(); + + if (onUpdate) { + (*onUpdate)(report[0] & 0x07, report[1], report[2], report[3]); + } + + if (onButtonUpdate && (buttons != (report[0] & 0x07))) { + (*onButtonUpdate)(report[0] & 0x07); + } + + if (onXUpdate && (x != report[1])) { + (*onXUpdate)(report[1]); + } + + if (onYUpdate && (y != report[2])) { + (*onYUpdate)(report[2]); + } + + if (onZUpdate && (z != report[3])) { + (*onZUpdate)(report[3]); + } + + // update mouse state + buttons = report[0] & 0x07; + x = report[1]; + y = report[2]; + z = report[3]; + + if (dev) + host->interruptRead(dev, int_in, report, len_listen, false); +} + +/*virtual*/ void USBHostMouse::setVidPid(uint16_t vid, uint16_t pid) +{ + // we don't check VID/PID for mouse driver +} + +/*virtual*/ bool USBHostMouse::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed +{ + if ((mouse_intf == -1) && + (intf_class == HID_CLASS) && + (intf_subclass == 0x01) && + (intf_protocol == 0x02)) { + mouse_intf = intf_nb; + return true; + } + return false; +} + +/*virtual*/ bool USBHostMouse::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if (intf_nb == mouse_intf) { + if (type == INTERRUPT_ENDPOINT && dir == IN) { + mouse_device_found = true; + return true; + } + } + return false; +} + +#endif
--- a/USBHostHID/USBHostMouse.h Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHostHID/USBHostMouse.h Mon Feb 03 13:00:16 2014 +0000 @@ -1,88 +1,139 @@ -/* 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 "USBHost.h" - -class USBHostMouse : public IUSBEnumerator { -public: - - /** - * Constructor - */ - USBHostMouse(); - - /** - * Try to connect a mouse device - * - * @return true if connection was successful - */ - bool connect(); - - /** - * Check if a mouse is connected - * - * @returns true if a mouse is connected - */ - bool connected(); - - int readReport(uint8_t* data) { - int rc = host->interruptRead(dev, int_in, data, 4); - return rc == USB_TYPE_OK ? 4 : 0; - } - void attachEvent(void (*ptr)(uint8_t* data, int size)) { - if (ptr != NULL) { - onUpdate = ptr; - } - } - void poll() { - USB_TYPE rc = host->interruptRead(dev, int_in, report, sizeof(report)); - if (rc == USB_TYPE_OK) { - if (onUpdate) { - (*onUpdate)(report, int_in->getLengthTransferred()); - } - } - } - -protected: - //From IUSBEnumerator - virtual void setVidPid(uint16_t vid, uint16_t pid); - virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed - virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used - -private: - USBHost * host; - USBDeviceConnected * dev; - USBEndpoint * int_in; - uint8_t report[4]; - - bool dev_connected; - bool mouse_device_found; - int mouse_intf; - - uint8_t buttons; - int8_t x; - int8_t y; - int8_t z; - - void (*onUpdate)(uint8_t* data, int size); - void (*onButtonUpdate)(uint8_t buttons); - void (*onXUpdate)(int8_t x); - void (*onYUpdate)(int8_t y); - void (*onZUpdate)(int8_t z); - int report_id; - void init(); -}; - +/* 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 USBHOSTMOUSE_H +#define USBHOSTMOUSE_H + +#include "USBHostConf.h" + +#if USBHOST_MOUSE + +#include "USBHost.h" + +/** + * A class to communicate a USB mouse + */ +class USBHostMouse : public IUSBEnumerator { +public: + + /** + * Constructor + */ + USBHostMouse(); + + /** + * Try to connect a mouse device + * + * @return true if connection was successful + */ + bool connect(); + + /** + * Check if a mouse is connected + * + * @returns true if a mouse is connected + */ + bool connected(); + + /** + * Attach a callback called when a mouse event is received + * + * @param ptr function pointer + */ + inline void attachEvent(void (*ptr)(uint8_t buttons, int8_t x, int8_t y, int8_t z)) { + if (ptr != NULL) { + onUpdate = ptr; + } + } + + /** + * Attach a callback called when the button state changes + * + * @param ptr function pointer + */ + inline void attachButtonEvent(void (*ptr)(uint8_t buttons)) { + if (ptr != NULL) { + onButtonUpdate = ptr; + } + } + + /** + * Attach a callback called when the X axis value changes + * + * @param ptr function pointer + */ + inline void attachXEvent(void (*ptr)(int8_t x)) { + if (ptr != NULL) { + onXUpdate = ptr; + } + } + + /** + * Attach a callback called when the Y axis value changes + * + * @param ptr function pointer + */ + inline void attachYEvent(void (*ptr)(int8_t y)) { + if (ptr != NULL) { + onYUpdate = ptr; + } + } + + /** + * Attach a callback called when the Z axis value changes (scrolling) + * + * @param ptr function pointer + */ + inline void attachZEvent(void (*ptr)(int8_t z)) { + if (ptr != NULL) { + onZUpdate = ptr; + } + } + +protected: + //From IUSBEnumerator + virtual void setVidPid(uint16_t vid, uint16_t pid); + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used + +private: + USBHost * host; + USBDeviceConnected * dev; + USBEndpoint * int_in; + uint8_t report[4]; + + bool dev_connected; + bool mouse_device_found; + int mouse_intf; + + uint8_t buttons; + int8_t x; + int8_t y; + int8_t z; + + void rxHandler(); + void (*onUpdate)(uint8_t buttons, int8_t x, int8_t y, int8_t z); + void (*onButtonUpdate)(uint8_t buttons); + void (*onXUpdate)(int8_t x); + void (*onYUpdate)(int8_t y); + void (*onZUpdate)(int8_t z); + int report_id; + void init(); +}; + +#endif + +#endif
--- a/USBHostMSD/FATFileSystem.lib Fri Jan 31 13:45:07 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/USBHostMSD/USBHostMSD.cpp Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHostMSD/USBHostMSD.cpp Mon Feb 03 13:00:16 2014 +0000 @@ -1,352 +1,356 @@ -/* 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_device_found = false; - disk_init = false; - dev_connected = false; - nb_ep = 0; -} - -bool USBHostMSD::connected() -{ - return dev_connected; -} - -bool USBHostMSD::connect() -{ - if (dev_connected) { - return true; - } - - for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { - if ((dev = host->getDevice(i)) != NULL) { - - //USB_DBG("Trying to connect MSD device dev=%p\n", dev); - - if(host->enumerate(dev, this)) - break; - - if (msd_device_found) { - bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN); - bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT); - - if (!bulk_in || !bulk_out) - continue; - - USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, msd_intf); - dev->setName("MSD", msd_intf); - host->registerDriver(dev, msd_intf, this, &USBHostMSD::init); - - dev_connected = true; - return true; - } - } //if() - } //for() - init(); - return false; -} - -/*virtual*/ void USBHostMSD::setVidPid(uint16_t vid, uint16_t pid) -{ - USB_DBG2("vid:%04x pid:%04x", vid, pid); - // we don't check VID/PID for MSD driver -} - -/*virtual*/ bool USBHostMSD::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed -{ - USB_DBG2("intf: %d class: %02x %02x %02x", intf_nb, intf_class, intf_subclass, intf_protocol); - - if ((msd_intf == -1) && - (intf_class == MSD_CLASS) && - (intf_subclass == 0x06) && - (intf_protocol == 0x50)) { - msd_intf = intf_nb; - return true; - } - return false; -} - -/*virtual*/ bool USBHostMSD::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used -{ - USB_DBG2("intf_nb=%d type=%d dir=%d", intf_nb, type, dir); - if (intf_nb == msd_intf) { - if (type == BULK_ENDPOINT) { - nb_ep++; - if (nb_ep == 2) - msd_device_found = true; - return true; - } - } - return false; -} - -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; -} - +/* 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" + +#if USBHOST_MSD + +#include "dbg.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_device_found = false; + disk_init = false; + dev_connected = false; + nb_ep = 0; +} + + +bool USBHostMSD::connected() +{ + return dev_connected; +} + +bool USBHostMSD::connect() +{ + + if (dev_connected) { + return true; + } + + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { + if ((dev = host->getDevice(i)) != NULL) { + + USB_DBG("Trying to connect MSD device\r\n"); + + if(host->enumerate(dev, this)) + break; + + if (msd_device_found) { + bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN); + bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT); + + if (!bulk_in || !bulk_out) + continue; + + USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, msd_intf); + dev->setName("MSD", msd_intf); + host->registerDriver(dev, msd_intf, this, &USBHostMSD::init); + + dev_connected = true; + return true; + } + } //if() + } //for() + init(); + return false; +} + +/*virtual*/ void USBHostMSD::setVidPid(uint16_t vid, uint16_t pid) +{ + // we don't check VID/PID for MSD driver +} + +/*virtual*/ bool USBHostMSD::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed +{ + if ((msd_intf == -1) && + (intf_class == MSD_CLASS) && + (intf_subclass == 0x06) && + (intf_protocol == 0x50)) { + msd_intf = intf_nb; + return true; + } + return false; +} + +/*virtual*/ bool USBHostMSD::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if (intf_nb == msd_intf) { + if (type == BULK_ENDPOINT) { + nb_ep++; + if (nb_ep == 2) + msd_device_found = true; + return true; + } + } + return false; +} + + +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, uint8_t((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 = 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"); + /* U16 */int i, timeout = 10; + + getMaxLun(); + + for (i = 0; i < timeout; i++) { + wait_ms(100); //Thread::wait(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; +} + +#endif
--- a/USBHostMSD/USBHostMSD.h Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHostMSD/USBHostMSD.h Mon Feb 03 13:00:16 2014 +0000 @@ -1,131 +1,119 @@ -/* 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 _USB_DBG -#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 0 -#define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); -#else -#define USB_DBG2(...) 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 IUSBEnumerator, 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 IUSBEnumerator - virtual void setVidPid(uint16_t vid, uint16_t pid); - virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed - virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used - - // 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 +/* 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 + +#include "USBHostConf.h" + +#if USBHOST_MSD + +#include "USBHost.h" +#include "FATFileSystem.h" + +/** + * A class to communicate a USB flash disk + */ +class USBHostMSD : public IUSBEnumerator, 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 IUSBEnumerator + virtual void setVidPid(uint16_t vid, uint16_t pid); + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used + + // 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 struct { + uint32_t Signature; + uint32_t Tag; + uint32_t DataLength; + uint8_t Flags; + uint8_t LUN; + uint8_t CBLength; + uint8_t CB[16]; + } PACKED CBW; + + // Bulk-only CSW + typedef struct { + uint32_t Signature; + uint32_t Tag; + uint32_t DataResidue; + uint8_t Status; + } PACKED 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 + +#endif