1 /* mbed USBHost Library
2 * Copyright (c) 2006-2013 ARM Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "USBHostSerial.h"
23 #define CHECK_INTERFACE(cls,subcls,proto) \
24 (((cls == 0xFF) && (subcls == 0xFF) && (proto == 0xFF)) /* QUALCOM CDC */ || \
25 ((cls == SERIAL_CLASS) && (subcls == 0x00) && (proto == 0x00)) /* STANDARD CDC */ )
27 #if (USBHOST_SERIAL <= 1)
29 USBHostSerial::USBHostSerial()
31 host = USBHost::getHostInst();
33 dev_connected = false;
36 bool USBHostSerial::connected()
41 void USBHostSerial::disconnect(void)
47 bool USBHostSerial::connect() {
51 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
53 USBDeviceConnected* d = host->getDevice(i);
59 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
61 USBDeviceConnected* d = host->getDevice(i);
64 USB_DBG("Trying to connect serial device \r\n");
65 if(host->enumerate(d, this))
68 USBEndpoint* bulk_in = d->getEndpoint(port_intf, BULK_ENDPOINT, IN);
69 USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT);
70 if (bulk_in && bulk_out)
72 USBHostSerialPort::connect(host,d,port_intf,bulk_in, bulk_out);
81 /*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid)
83 // we don't check VID/PID for MSD driver
86 /*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
89 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
97 /*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
99 if (ports_found && (intf_nb == port_intf)) {
100 if (type == BULK_ENDPOINT)
106 #else // (USBHOST_SERIAL > 1)
108 //------------------------------------------------------------------------------
110 USBHostMultiSerial::USBHostMultiSerial()
112 host = USBHost::getHostInst();
114 memset(ports, NULL, sizeof(ports));
116 dev_connected = false;
119 USBHostMultiSerial::~USBHostMultiSerial()
124 bool USBHostMultiSerial::connected()
126 return dev_connected;
129 void USBHostMultiSerial::disconnect(void)
131 for (int port = 0; port < USBHOST_SERIAL; port ++)
143 bool USBHostMultiSerial::connect() {
147 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
149 USBDeviceConnected* d = host->getDevice(i);
155 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
157 USBDeviceConnected* d = host->getDevice(i);
160 USB_DBG("Trying to connect serial device \r\n");
161 if(host->enumerate(d, this))
164 for (int port = 0; port < ports_found; port ++)
166 USBEndpoint* bulk_in = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN);
167 USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT);
168 if (bulk_in && bulk_out)
170 ports[port] = new USBHostSerialPort();
173 ports[port]->connect(host,d,port_intf[port],bulk_in, bulk_out);
175 dev_connected = true;
184 /*virtual*/ void USBHostMultiSerial::setVidPid(uint16_t vid, uint16_t pid)
186 // we don't check VID/PID for MSD driver
189 /*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
191 if ((ports_found < USBHOST_SERIAL) &&
192 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
193 port_intf[ports_found++] = intf_nb;
199 /*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
201 if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) {
202 if (type == BULK_ENDPOINT)
210 //------------------------------------------------------------------------------
212 #define SET_LINE_CODING 0x20
214 USBHostSerialPort::USBHostSerialPort(): circ_buf()
219 void USBHostSerialPort::init(void)
228 line_coding.baudrate = 9600;
229 line_coding.data_bits = 8;
230 line_coding.parity = None;
231 line_coding.stop_bits = 1;
235 void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev,
236 uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out)
240 serial_intf = _serial_intf;
242 bulk_out = _bulk_out;
244 USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf);
245 dev->setName("Serial", serial_intf);
246 host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init);
248 size_bulk_in = bulk_in->getSize();
249 size_bulk_out = bulk_out->getSize();
250 bulk_in->attach(this, &USBHostSerialPort::rxHandler);
251 bulk_out->attach(this, &USBHostSerialPort::txHandler);
252 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
255 void USBHostSerialPort::rxHandler() {
257 int len = bulk_in->getLengthTransferred();
258 if (bulk_in->getState() == USB_TYPE_IDLE) {
259 for (int i = 0; i < len; i++) {
260 circ_buf.queue(buf[i]);
263 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
268 void USBHostSerialPort::txHandler() {
270 if (bulk_out->getState() == USB_TYPE_IDLE) {
276 int USBHostSerialPort::_putc(int c) {
278 if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) {
285 void USBHostSerialPort::baud(int baudrate) {
286 line_coding.baudrate = baudrate;
287 format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.stop_bits);
290 void USBHostSerialPort::format(int bits, Parity parity, int stop_bits) {
291 line_coding.data_bits = bits;
292 line_coding.parity = parity;
293 line_coding.stop_bits = (stop_bits == 1) ? 0 : 2;
296 host->controlWrite( dev,
297 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
299 0, serial_intf, (uint8_t *)&line_coding, 7);
302 int USBHostSerialPort::_getc() {
304 if (bulk_in == NULL) {
308 while (circ_buf.isEmpty());
309 circ_buf.dequeue(&c);
313 int USBHostSerialPort::writeBuf(const char* b, int s)
320 int i = (s < size_bulk_out) ? s : size_bulk_out;
321 if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK)
328 int USBHostSerialPort::readBuf(char* b, int s)
339 uint8_t USBHostSerialPort::available() {
340 return circ_buf.available();