2018.07.26
Dependencies: FATFileSystem mbed-rtos
Fork of USBHost by
Revision 19:bd46ea19486b, committed 2013-12-16
- Comitter:
- mbed_official
- Date:
- Mon Dec 16 09:00:18 2013 +0000
- Parent:
- 18:37c948cf0dbf
- Child:
- 20:8f510a2502ef
- Commit message:
- Synchronized with git revision 170ac6562b7b2b5bb43f8ecf82b2af18b37eeb9c
Full URL: https://github.com/mbedmicro/mbed/commit/170ac6562b7b2b5bb43f8ecf82b2af18b37eeb9c/
improve USB host library and cellular modem stack
Changed in this revision
--- a/USBHost/USBHostConf.h Thu Oct 17 10:15:19 2013 +0100 +++ b/USBHost/USBHostConf.h Mon Dec 16 09:00:18 2013 +0000 @@ -49,7 +49,7 @@ #define USBHOST_MOUSE 1 /* -* Enable USBHostSerial +* Enable USBHostSerial or USBHostMultiSerial (if set > 1) */ #define USBHOST_SERIAL 1
--- a/USBHost/dbg.h Thu Oct 17 10:15:19 2013 +0100 +++ b/USBHost/dbg.h Mon Dec 16 09:00:18 2013 +0000 @@ -18,17 +18,35 @@ #define USB_DEBUG_H //Debug is disabled by default -#define DEBUG 0 +#define DEBUG 3 /*INFO,ERR,WARN*/ #define DEBUG_TRANSFER 0 #define DEBUG_EP_STATE 0 #define DEBUG_EVENT 0 -#if (DEBUG) +#if (DEBUG > 3) #define USB_DBG(x, ...) std::printf("[USB_DBG: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); #else #define USB_DBG(x, ...) #endif +#if (DEBUG > 2) +#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 @@ -41,9 +59,6 @@ #define USB_DBG_EVENT(x, ...) #endif -#define USB_INFO(x, ...) std::printf("[USB_INFO: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); -#define USB_WARN(x, ...) std::printf("[USB_WARNING: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); -#define USB_ERR(x, ...) std::printf("[USB_ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); #endif
--- a/USBHostSerial/USBHostSerial.cpp Thu Oct 17 10:15:19 2013 +0100 +++ b/USBHostSerial/USBHostSerial.cpp Mon Dec 16 09:00:18 2013 +0000 @@ -20,27 +20,17 @@ #include "dbg.h" -#define SET_LINE_CODING 0x20 +#define CHECK_INTERFACE(cls,subcls,proto) \ + (((cls == 0xFF) && (subcls == 0xFF) && (proto == 0xFF)) /* QUALCOM CDC */ || \ + ((cls == SERIAL_CLASS) && (subcls == 0x00) && (proto == 0x00)) /* STANDARD CDC */ ) -USBHostSerial::USBHostSerial(): circ_buf() { - host = USBHost::getHostInst(); - size_bulk_in = 0; - size_bulk_out = 0; - init(); -} +#if (USBHOST_SERIAL <= 1) -void USBHostSerial::init() { - dev = NULL; - bulk_in = NULL; - bulk_out = NULL; +USBHostSerial::USBHostSerial() +{ + host = USBHost::getHostInst(); + ports_found = 0; dev_connected = false; - serial_intf = -1; - serial_device_found = false; - line_coding.baudrate = 9600; - line_coding.data_bits = 8; - line_coding.parity = None; - line_coding.stop_bits = 1; - circ_buf.flush(); } bool USBHostSerial::connected() @@ -48,49 +38,219 @@ return dev_connected; } +void USBHostSerial::disconnect(void) +{ + ports_found = 0; + dev = NULL; +} + bool USBHostSerial::connect() { - if (dev_connected) { - return true; + if (dev) + { + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) + { + USBDeviceConnected* d = host->getDevice(i); + if (dev == d) + return true; + } + disconnect(); } - for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { - if ((dev = host->getDevice(i)) != NULL) { + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) + { + USBDeviceConnected* d = host->getDevice(i); + if (d != NULL) { - USB_DBG("Trying to connect serial device\r\n"); - - if(host->enumerate(dev, this)) + USB_DBG("Trying to connect serial device \r\n"); + if(host->enumerate(d, this)) break; - if (serial_device_found) { - bulk_in = dev->getEndpoint(serial_intf, BULK_ENDPOINT, IN); - bulk_out = dev->getEndpoint(serial_intf, BULK_ENDPOINT, OUT); - - if (!bulk_in || !bulk_out) - break; - - USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf); - dev->setName("Serial", serial_intf); - host->registerDriver(dev, serial_intf, this, &USBHostSerial::init); - - baud(9600); - - size_bulk_in = bulk_in->getSize(); - size_bulk_out = bulk_out->getSize(); - - bulk_in->attach(this, &USBHostSerial::rxHandler); - bulk_out->attach(this, &USBHostSerial::txHandler); - - host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); - dev_connected = true; - return true; + USBEndpoint* bulk_in = d->getEndpoint(port_intf, BULK_ENDPOINT, IN); + USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT); + if (bulk_in && bulk_out) + { + USBHostSerialPort::connect(host,d,port_intf,bulk_in, bulk_out); + dev = d; } } } - init(); + return dev != NULL; +} + +/*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid) +{ + // we don't check VID/PID for MSD driver +} + +/*virtual*/ bool USBHostSerial::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 ((ports_found < USBHOST_MAXSERIAL) && + CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) { + port_intf = intf_nb; + ports_found = true; + return true; + } + return false; +} + +/*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if (ports_found && (intf_nb == port_intf)) { + if (type == BULK_ENDPOINT) + return true; + } return false; } -void USBHostSerial::rxHandler() { +#else // (USBHOST_SERIAL > 1) + +//------------------------------------------------------------------------------ + +USBHostMultiSerial::USBHostMultiSerial() +{ + host = USBHost::getHostInst(); + dev = NULL; + memset(ports, NULL, sizeof(ports)); + ports_found = 0; + dev_connected = false; +} + +USBHostMultiSerial::~USBHostMultiSerial() +{ + disconnect(); +} + +bool USBHostMultiSerial::connected() +{ + return dev_connected; +} + +void USBHostMultiSerial::disconnect(void) +{ + for (int port = 0; port < USBHOST_SERIAL; port ++) + { + if (ports[port]) + { + delete ports[port]; + ports[port] = NULL; + } + } + ports_found = 0; + dev = NULL; +} + +bool USBHostMultiSerial::connect() { + + if (dev) + { + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) + { + USBDeviceConnected* d = host->getDevice(i); + if (dev == d) + return true; + } + disconnect(); + } + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) + { + USBDeviceConnected* d = host->getDevice(i); + if (d != NULL) { + + USB_DBG("Trying to connect serial device \r\n"); + if(host->enumerate(d, this)) + break; + + for (int port = 0; port < ports_found; port ++) + { + USBEndpoint* bulk_in = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN); + USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT); + if (bulk_in && bulk_out) + { + ports[port] = new USBHostSerialPort(); + if (ports[port]) + { + ports[port]->connect(host,d,port_intf[port],bulk_in, bulk_out); + dev = d; + } + } + } + } + } + return dev != NULL; +} + +/*virtual*/ void USBHostMultiSerial::setVidPid(uint16_t vid, uint16_t pid) +{ + // we don't check VID/PID for MSD driver +} + +/*virtual*/ bool USBHostMultiSerial::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 ((ports_found < USBHOST_SERIAL) && + CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) { + port_intf[ports_found++] = intf_nb; + return true; + } + return false; +} + +/*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) { + if (type == BULK_ENDPOINT) + return true; + } + return false; +} + +#endif + +//------------------------------------------------------------------------------ + +#define SET_LINE_CODING 0x20 + +USBHostSerialPort::USBHostSerialPort(): circ_buf() +{ + init(); +} + +void USBHostSerialPort::init(void) +{ + host = NULL; + dev = NULL; + serial_intf = NULL; + size_bulk_in = 0; + size_bulk_out = 0; + bulk_in = NULL; + bulk_out = NULL; + line_coding.baudrate = 9600; + line_coding.data_bits = 8; + line_coding.parity = None; + line_coding.stop_bits = 1; + circ_buf.flush(); +} + +void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev, + uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out) +{ + host = _host; + dev = _dev; + serial_intf = _serial_intf; + bulk_in = _bulk_in; + bulk_out = _bulk_out; + + USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf); + dev->setName("Serial", serial_intf); + host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init); + //baud(9600); + size_bulk_in = bulk_in->getSize(); + size_bulk_out = bulk_out->getSize(); + bulk_in->attach(this, &USBHostSerialPort::rxHandler); + bulk_out->attach(this, &USBHostSerialPort::txHandler); + host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); +} + +void USBHostSerialPort::rxHandler() { if (bulk_in) { int len = bulk_in->getLengthTransferred(); if (bulk_in->getState() == USB_TYPE_IDLE) { @@ -103,7 +263,7 @@ } } -void USBHostSerial::txHandler() { +void USBHostSerialPort::txHandler() { if (bulk_out) { if (bulk_out->getState() == USB_TYPE_IDLE) { tx.call(); @@ -111,7 +271,7 @@ } } -int USBHostSerial::_putc(int c) { +int USBHostSerialPort::_putc(int c) { if (bulk_out) { if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) { return 1; @@ -120,12 +280,12 @@ return -1; } -void USBHostSerial::baud(int baudrate) { +void USBHostSerialPort::baud(int baudrate) { line_coding.baudrate = baudrate; format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.stop_bits); } -void USBHostSerial::format(int bits, Parity parity, int stop_bits) { +void USBHostSerialPort::format(int bits, Parity parity, int stop_bits) { line_coding.data_bits = bits; line_coding.parity = parity; line_coding.stop_bits = (stop_bits == 1) ? 0 : 2; @@ -137,7 +297,7 @@ 0, serial_intf, (uint8_t *)&line_coding, 7); } -int USBHostSerial::_getc() { +int USBHostSerialPort::_getc() { uint8_t c = 0; if (bulk_in == NULL) { init(); @@ -148,37 +308,36 @@ return c; } +int USBHostSerialPort::writeBuf(const char* b, int s) +{ + int c = 0; + if (bulk_out) + { + while (c < s) + { + int i = (s < size_bulk_out) ? s : size_bulk_out; + if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK) + c += i; + } + } + return s; +} -uint8_t USBHostSerial::available() { +int USBHostSerialPort::readBuf(char* b, int s) +{ + int i = 0; + if (bulk_in) + { + for (i = 0; i < s; ) + b[i++] = getc(); + } + return i; +} + +uint8_t USBHostSerialPort::available() { return circ_buf.available(); } -/*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid) -{ - // we don't check VID/PID for MSD driver -} -/*virtual*/ bool USBHostSerial::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 ((serial_intf == -1) && - (intf_class == SERIAL_CLASS) && - (intf_subclass == 0x00) && - (intf_protocol == 0x00)) { - serial_intf = intf_nb; - return true; - } - return false; -} - -/*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used -{ - if (intf_nb == serial_intf) { - if (type == BULK_ENDPOINT) { - serial_device_found = true; - return true; - } - } - return false; -} #endif
--- a/USBHostSerial/USBHostSerial.h Thu Oct 17 10:15:19 2013 +0100 +++ b/USBHostSerial/USBHostSerial.h Mon Dec 16 09:00:18 2013 +0000 @@ -28,12 +28,12 @@ /** * A class to communicate a USB virtual serial port */ -class USBHostSerial : public IUSBEnumerator, public Stream { +class USBHostSerialPort : public Stream { public: /** * Constructor */ - USBHostSerial(); + USBHostSerialPort(); enum IrqType { RxIrq, @@ -48,20 +48,9 @@ Space }; - /** - * Check if a virtual serial port is connected - * - * @returns true if a serial device is connected - */ - bool connected(); - - /** - * Try to connect a serial device - * - * @return true if connection was successful - */ - bool connect(); - + void connect(USBHost* _host, USBDeviceConnected * _dev, + uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out); + /** * Check the number of bytes available. * @@ -111,34 +100,29 @@ /** Set the transmission format used by the Serial port * * @param bits The number of bits in a word (default = 8) - * @param parity The parity used (USBHostSerial::None, USBHostSerial::Odd, USBHostSerial::Even, USBHostSerial::Mark, USBHostSerial::Space; default = USBHostSerial::None) + * @param parity The parity used (USBHostSerialPort::None, USBHostSerialPort::Odd, USBHostSerialPort::Even, USBHostSerialPort::Mark, USBHostSerialPort::Space; default = USBHostSerialPort::None) * @param stop The number of stop bits (1 or 2; default = 1) */ - void format(int bits = 8, Parity parity = USBHostSerial::None, int stop_bits = 1); - + void format(int bits = 8, Parity parity = USBHostSerialPort::None, int stop_bits = 1); + virtual int writeBuf(const char* b, int s); + virtual int readBuf(char* b, int s); 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 - virtual int _getc(); virtual int _putc(int c); private: USBHost * host; USBDeviceConnected * dev; + USBEndpoint * bulk_in; USBEndpoint * bulk_out; uint32_t size_bulk_in; uint32_t size_bulk_out; - bool dev_connected; - void init(); - MtxCircBuffer<uint8_t, 64> circ_buf; + MtxCircBuffer<uint8_t, 128> circ_buf; uint8_t buf[64]; @@ -156,10 +140,91 @@ FunctionPointer rx; FunctionPointer tx; - int serial_intf; - bool serial_device_found; + uint8_t serial_intf; +}; + +#if (USBHOST_SERIAL <= 1) + +class USBHostSerial : public IUSBEnumerator, public USBHostSerialPort +{ +public: + USBHostSerial(); + + /** + * Try to connect a serial device + * + * @return true if connection was successful + */ + bool connect(); + + void disconnect(); + + /** + * Check if a any serial port is connected + * + * @returns true if a serial device is connected + */ + bool connected(); + +protected: + USBHost* host; + USBDeviceConnected* dev; + uint8_t port_intf; + int ports_found; + + //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: + bool dev_connected; +}; + +#else // (USBHOST_SERIAL > 1) +class USBHostMultiSerial : public IUSBEnumerator { +public: + USBHostMultiSerial(); + virtual ~USBHostMultiSerial(); + + USBHostSerialPort* getPort(int port) + { + return port < USBHOST_SERIAL ? ports[port] : NULL; + } + + /** + * Try to connect a serial device + * + * @return true if connection was successful + */ + bool connect(); + + void disconnect(); + + /** + * Check if a any serial port is connected + * + * @returns true if a serial device is connected + */ + bool connected(); + +protected: + USBHost* host; + USBDeviceConnected* dev; + USBHostSerialPort* ports[USBHOST_SERIAL]; + uint8_t port_intf[USBHOST_SERIAL]; + int ports_found; + + //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: + bool dev_connected; }; +#endif // (USBHOST_SERIAL <= 1) #endif