From 1fe4406f374291ab2e86e95a97341fd9c475fcb8 Mon Sep 17 00:00:00 2001 From: Jun Wako Date: Fri, 24 Apr 2015 16:26:14 +0900 Subject: Squashed 'tmk_core/' changes from 7967731..b9e0ea0 b9e0ea0 Merge commit '7fa9d8bdea3773d1195b04d98fcf27cf48ddd81d' as 'tool/mbed/mbed-sdk' 7fa9d8b Squashed 'tool/mbed/mbed-sdk/' content from commit 7c21ce5 git-subtree-dir: tmk_core git-subtree-split: b9e0ea08cb940de20b3610ecdda18e9d8cd7c552 --- .../USBHost/USBHostSerial/MtxCircBuffer.h | 89 ++++++ .../USBHost/USBHostSerial/USBHostSerial.cpp | 345 +++++++++++++++++++++ .../USBHost/USBHostSerial/USBHostSerial.h | 231 ++++++++++++++ 3 files changed, 665 insertions(+) create mode 100644 tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/MtxCircBuffer.h create mode 100644 tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.cpp create mode 100644 tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.h (limited to 'tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial') diff --git a/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/MtxCircBuffer.h b/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/MtxCircBuffer.h new file mode 100644 index 000000000..ff79affad --- /dev/null +++ b/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/MtxCircBuffer.h @@ -0,0 +1,89 @@ +/* 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 MTXCIRCBUFFER_H +#define MTXCIRCBUFFER_H + +#include "stdint.h" +#include "rtos.h" + +//Mutex protected circular buffer +template +class MtxCircBuffer { +public: + + MtxCircBuffer() { + write = 0; + read = 0; + } + + bool isFull() { + mtx.lock(); + bool r = (((write + 1) % size) == read); + mtx.unlock(); + return r; + } + + bool isEmpty() { + mtx.lock(); + bool r = (read == write); + mtx.unlock(); + return r; + } + + void flush() { + write = 0; + read = 0; + } + + void queue(T k) { + mtx.lock(); + while (((write + 1) % size) == read) { + mtx.unlock(); + Thread::wait(10); + mtx.lock(); + } + buf[write++] = k; + write %= size; + mtx.unlock(); + } + + uint16_t available() { + mtx.lock(); + uint16_t a = (write >= read) ? (write - read) : (size - read + write); + mtx.unlock(); + return a; + } + + bool dequeue(T * c) { + mtx.lock(); + bool empty = (read == write); + if (!empty) { + *c = buf[read++]; + read %= size; + } + mtx.unlock(); + return (!empty); + } + +private: + volatile uint16_t write; + volatile uint16_t read; + volatile T buf[size]; + Mutex mtx; +}; + +#endif diff --git a/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.cpp b/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.cpp new file mode 100644 index 000000000..428026ff5 --- /dev/null +++ b/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.cpp @@ -0,0 +1,345 @@ +/* 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 "USBHostSerial.h" + +#if USBHOST_SERIAL + +#include "dbg.h" + +#define CHECK_INTERFACE(cls,subcls,proto) \ + (((cls == 0xFF) && (subcls == 0xFF) && (proto == 0xFF)) /* QUALCOM CDC */ || \ + ((cls == SERIAL_CLASS) && (subcls == 0x00) && (proto == 0x00)) /* STANDARD CDC */ ) + +#if (USBHOST_SERIAL <= 1) + +USBHostSerial::USBHostSerial() +{ + host = USBHost::getHostInst(); + ports_found = 0; + dev_connected = false; +} + +bool USBHostSerial::connected() +{ + return dev_connected; +} + +void USBHostSerial::disconnect(void) +{ + ports_found = 0; + dev = NULL; +} + +bool USBHostSerial::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; + + 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; + dev_connected = true; + } + } + } + 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 && + 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; +} + +#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; + dev_connected = true; + } + } + } + } + } + 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) { + for (int i = 0; i < len; i++) { + circ_buf.queue(buf[i]); + } + rx.call(); + host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); + } + } +} + +void USBHostSerialPort::txHandler() { + if (bulk_out) { + if (bulk_out->getState() == USB_TYPE_IDLE) { + tx.call(); + } + } +} + +int USBHostSerialPort::_putc(int c) { + if (bulk_out) { + if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) { + return 1; + } + } + return -1; +} + +void USBHostSerialPort::baud(int baudrate) { + line_coding.baudrate = baudrate; + format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.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; + + // set line coding + host->controlWrite( dev, + USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, + SET_LINE_CODING, + 0, serial_intf, (uint8_t *)&line_coding, 7); +} + +int USBHostSerialPort::_getc() { + uint8_t c = 0; + if (bulk_in == NULL) { + init(); + return -1; + } + while (circ_buf.isEmpty()); + circ_buf.dequeue(&c); + 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; +} + +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(); +} + + + +#endif diff --git a/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.h b/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.h new file mode 100644 index 000000000..94fc8ad7c --- /dev/null +++ b/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.h @@ -0,0 +1,231 @@ +/* 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 USBHOSTSERIAL_H +#define USBHOSTSERIAL_H + +#include "USBHostConf.h" + +#if USBHOST_SERIAL + +#include "USBHost.h" +#include "Stream.h" +#include "MtxCircBuffer.h" + +/** + * A class to communicate a USB virtual serial port + */ +class USBHostSerialPort : public Stream { +public: + /** + * Constructor + */ + USBHostSerialPort(); + + enum IrqType { + RxIrq, + TxIrq + }; + + enum Parity { + None = 0, + Odd, + Even, + Mark, + Space + }; + + void connect(USBHost* _host, USBDeviceConnected * _dev, + uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out); + + /** + * Check the number of bytes available. + * + * @returns the number of bytes available + */ + uint8_t available(); + + /** + * Attach a member function to call when a packet is received. + * + * @param tptr pointer to the object to call the member function on + * @param mptr pointer to the member function to be called + * @param irq irq type + */ + template + inline void attach(T* tptr, void (T::*mptr)(void), IrqType irq = RxIrq) { + if ((mptr != NULL) && (tptr != NULL)) { + if (irq == RxIrq) { + rx.attach(tptr, mptr); + } else { + tx.attach(tptr, mptr); + } + } + } + + /** + * Attach a callback called when a packet is received + * + * @param ptr function pointer + */ + inline void attach(void (*fn)(void), IrqType irq = RxIrq) { + if (fn != NULL) { + if (irq == RxIrq) { + rx.attach(fn); + } else { + tx.attach(fn); + } + } + } + + /** Set the baud rate of the serial port + * + * @param baudrate The baudrate of the serial port (default = 9600). + */ + void baud(int baudrate = 9600); + + /** 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 (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 = USBHostSerialPort::None, int stop_bits = 1); + virtual int writeBuf(const char* b, int s); + virtual int readBuf(char* b, int s); + +protected: + 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; + + void init(); + + MtxCircBuffer circ_buf; + + uint8_t buf[64]; + + typedef struct { + uint32_t baudrate; + uint8_t stop_bits; + uint8_t parity; + uint8_t data_bits; + } PACKED LINE_CODING; + + LINE_CODING line_coding; + + void rxHandler(); + void txHandler(); + FunctionPointer rx; + FunctionPointer tx; + + 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 + +#endif -- cgit v1.2.3-24-g4f1b