mbed-os

Fork of mbed-os by erkin yucel

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* mbed USBHost Library
elessair 0:f269e3021894 2 * Copyright (c) 2006-2013 ARM Limited
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 */
elessair 0:f269e3021894 16
elessair 0:f269e3021894 17 #include "USBHostSerial.h"
elessair 0:f269e3021894 18
elessair 0:f269e3021894 19 #if USBHOST_SERIAL
elessair 0:f269e3021894 20
elessair 0:f269e3021894 21 #include "dbg.h"
elessair 0:f269e3021894 22
elessair 0:f269e3021894 23 #define CHECK_INTERFACE(cls,subcls,proto) \
elessair 0:f269e3021894 24 (((cls == 0xFF) && (subcls == 0xFF) && (proto == 0xFF)) /* QUALCOM CDC */ || \
elessair 0:f269e3021894 25 ((cls == SERIAL_CLASS) && (subcls == 0x00) && (proto == 0x00)) /* STANDARD CDC */ )
elessair 0:f269e3021894 26
elessair 0:f269e3021894 27 #if (USBHOST_SERIAL <= 1)
elessair 0:f269e3021894 28
elessair 0:f269e3021894 29 USBHostSerial::USBHostSerial()
elessair 0:f269e3021894 30 {
elessair 0:f269e3021894 31 host = USBHost::getHostInst();
elessair 0:f269e3021894 32 ports_found = 0;
elessair 0:f269e3021894 33 dev_connected = false;
elessair 0:f269e3021894 34 }
elessair 0:f269e3021894 35
elessair 0:f269e3021894 36 bool USBHostSerial::connected()
elessair 0:f269e3021894 37 {
elessair 0:f269e3021894 38 return dev_connected;
elessair 0:f269e3021894 39 }
elessair 0:f269e3021894 40
elessair 0:f269e3021894 41 void USBHostSerial::disconnect(void)
elessair 0:f269e3021894 42 {
elessair 0:f269e3021894 43 ports_found = 0;
elessair 0:f269e3021894 44 dev = NULL;
elessair 0:f269e3021894 45 }
elessair 0:f269e3021894 46
elessair 0:f269e3021894 47 bool USBHostSerial::connect() {
elessair 0:f269e3021894 48
elessair 0:f269e3021894 49 if (dev)
elessair 0:f269e3021894 50 {
elessair 0:f269e3021894 51 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
elessair 0:f269e3021894 52 {
elessair 0:f269e3021894 53 USBDeviceConnected* d = host->getDevice(i);
elessair 0:f269e3021894 54 if (dev == d)
elessair 0:f269e3021894 55 return true;
elessair 0:f269e3021894 56 }
elessair 0:f269e3021894 57 disconnect();
elessair 0:f269e3021894 58 }
elessair 0:f269e3021894 59 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
elessair 0:f269e3021894 60 {
elessair 0:f269e3021894 61 USBDeviceConnected* d = host->getDevice(i);
elessair 0:f269e3021894 62 if (d != NULL) {
elessair 0:f269e3021894 63
elessair 0:f269e3021894 64 USB_DBG("Trying to connect serial device \r\n");
elessair 0:f269e3021894 65 if(host->enumerate(d, this))
elessair 0:f269e3021894 66 break;
elessair 0:f269e3021894 67
elessair 0:f269e3021894 68 USBEndpoint* bulk_in = d->getEndpoint(port_intf, BULK_ENDPOINT, IN);
elessair 0:f269e3021894 69 USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT);
elessair 0:f269e3021894 70 if (bulk_in && bulk_out)
elessair 0:f269e3021894 71 {
elessair 0:f269e3021894 72 USBHostSerialPort::connect(host,d,port_intf,bulk_in, bulk_out);
elessair 0:f269e3021894 73 dev = d;
elessair 0:f269e3021894 74 dev_connected = true;
elessair 0:f269e3021894 75 }
elessair 0:f269e3021894 76 }
elessair 0:f269e3021894 77 }
elessair 0:f269e3021894 78 return dev != NULL;
elessair 0:f269e3021894 79 }
elessair 0:f269e3021894 80
elessair 0:f269e3021894 81 /*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid)
elessair 0:f269e3021894 82 {
elessair 0:f269e3021894 83 // we don't check VID/PID for MSD driver
elessair 0:f269e3021894 84 }
elessair 0:f269e3021894 85
elessair 0:f269e3021894 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
elessair 0:f269e3021894 87 {
elessair 0:f269e3021894 88 if (!ports_found &&
elessair 0:f269e3021894 89 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
elessair 0:f269e3021894 90 port_intf = intf_nb;
elessair 0:f269e3021894 91 ports_found = true;
elessair 0:f269e3021894 92 return true;
elessair 0:f269e3021894 93 }
elessair 0:f269e3021894 94 return false;
elessair 0:f269e3021894 95 }
elessair 0:f269e3021894 96
elessair 0:f269e3021894 97 /*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
elessair 0:f269e3021894 98 {
elessair 0:f269e3021894 99 if (ports_found && (intf_nb == port_intf)) {
elessair 0:f269e3021894 100 if (type == BULK_ENDPOINT)
elessair 0:f269e3021894 101 return true;
elessair 0:f269e3021894 102 }
elessair 0:f269e3021894 103 return false;
elessair 0:f269e3021894 104 }
elessair 0:f269e3021894 105
elessair 0:f269e3021894 106 #else // (USBHOST_SERIAL > 1)
elessair 0:f269e3021894 107
elessair 0:f269e3021894 108 //------------------------------------------------------------------------------
elessair 0:f269e3021894 109
elessair 0:f269e3021894 110 USBHostMultiSerial::USBHostMultiSerial()
elessair 0:f269e3021894 111 {
elessair 0:f269e3021894 112 host = USBHost::getHostInst();
elessair 0:f269e3021894 113 dev = NULL;
elessair 0:f269e3021894 114 memset(ports, NULL, sizeof(ports));
elessair 0:f269e3021894 115 ports_found = 0;
elessair 0:f269e3021894 116 dev_connected = false;
elessair 0:f269e3021894 117 }
elessair 0:f269e3021894 118
elessair 0:f269e3021894 119 USBHostMultiSerial::~USBHostMultiSerial()
elessair 0:f269e3021894 120 {
elessair 0:f269e3021894 121 disconnect();
elessair 0:f269e3021894 122 }
elessair 0:f269e3021894 123
elessair 0:f269e3021894 124 bool USBHostMultiSerial::connected()
elessair 0:f269e3021894 125 {
elessair 0:f269e3021894 126 return dev_connected;
elessair 0:f269e3021894 127 }
elessair 0:f269e3021894 128
elessair 0:f269e3021894 129 void USBHostMultiSerial::disconnect(void)
elessair 0:f269e3021894 130 {
elessair 0:f269e3021894 131 for (int port = 0; port < USBHOST_SERIAL; port ++)
elessair 0:f269e3021894 132 {
elessair 0:f269e3021894 133 if (ports[port])
elessair 0:f269e3021894 134 {
elessair 0:f269e3021894 135 delete ports[port];
elessair 0:f269e3021894 136 ports[port] = NULL;
elessair 0:f269e3021894 137 }
elessair 0:f269e3021894 138 }
elessair 0:f269e3021894 139 ports_found = 0;
elessair 0:f269e3021894 140 dev = NULL;
elessair 0:f269e3021894 141 }
elessair 0:f269e3021894 142
elessair 0:f269e3021894 143 bool USBHostMultiSerial::connect() {
elessair 0:f269e3021894 144
elessair 0:f269e3021894 145 if (dev)
elessair 0:f269e3021894 146 {
elessair 0:f269e3021894 147 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
elessair 0:f269e3021894 148 {
elessair 0:f269e3021894 149 USBDeviceConnected* d = host->getDevice(i);
elessair 0:f269e3021894 150 if (dev == d)
elessair 0:f269e3021894 151 return true;
elessair 0:f269e3021894 152 }
elessair 0:f269e3021894 153 disconnect();
elessair 0:f269e3021894 154 }
elessair 0:f269e3021894 155 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
elessair 0:f269e3021894 156 {
elessair 0:f269e3021894 157 USBDeviceConnected* d = host->getDevice(i);
elessair 0:f269e3021894 158 if (d != NULL) {
elessair 0:f269e3021894 159
elessair 0:f269e3021894 160 USB_DBG("Trying to connect serial device \r\n");
elessair 0:f269e3021894 161 if(host->enumerate(d, this))
elessair 0:f269e3021894 162 break;
elessair 0:f269e3021894 163
elessair 0:f269e3021894 164 for (int port = 0; port < ports_found; port ++)
elessair 0:f269e3021894 165 {
elessair 0:f269e3021894 166 USBEndpoint* bulk_in = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN);
elessair 0:f269e3021894 167 USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT);
elessair 0:f269e3021894 168 if (bulk_in && bulk_out)
elessair 0:f269e3021894 169 {
elessair 0:f269e3021894 170 ports[port] = new USBHostSerialPort();
elessair 0:f269e3021894 171 if (ports[port])
elessair 0:f269e3021894 172 {
elessair 0:f269e3021894 173 ports[port]->connect(host,d,port_intf[port],bulk_in, bulk_out);
elessair 0:f269e3021894 174 dev = d;
elessair 0:f269e3021894 175 dev_connected = true;
elessair 0:f269e3021894 176 }
elessair 0:f269e3021894 177 }
elessair 0:f269e3021894 178 }
elessair 0:f269e3021894 179 }
elessair 0:f269e3021894 180 }
elessair 0:f269e3021894 181 return dev != NULL;
elessair 0:f269e3021894 182 }
elessair 0:f269e3021894 183
elessair 0:f269e3021894 184 /*virtual*/ void USBHostMultiSerial::setVidPid(uint16_t vid, uint16_t pid)
elessair 0:f269e3021894 185 {
elessair 0:f269e3021894 186 // we don't check VID/PID for MSD driver
elessair 0:f269e3021894 187 }
elessair 0:f269e3021894 188
elessair 0:f269e3021894 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
elessair 0:f269e3021894 190 {
elessair 0:f269e3021894 191 if ((ports_found < USBHOST_SERIAL) &&
elessair 0:f269e3021894 192 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
elessair 0:f269e3021894 193 port_intf[ports_found++] = intf_nb;
elessair 0:f269e3021894 194 return true;
elessair 0:f269e3021894 195 }
elessair 0:f269e3021894 196 return false;
elessair 0:f269e3021894 197 }
elessair 0:f269e3021894 198
elessair 0:f269e3021894 199 /*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
elessair 0:f269e3021894 200 {
elessair 0:f269e3021894 201 if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) {
elessair 0:f269e3021894 202 if (type == BULK_ENDPOINT)
elessair 0:f269e3021894 203 return true;
elessair 0:f269e3021894 204 }
elessair 0:f269e3021894 205 return false;
elessair 0:f269e3021894 206 }
elessair 0:f269e3021894 207
elessair 0:f269e3021894 208 #endif
elessair 0:f269e3021894 209
elessair 0:f269e3021894 210 //------------------------------------------------------------------------------
elessair 0:f269e3021894 211
elessair 0:f269e3021894 212 #define SET_LINE_CODING 0x20
elessair 0:f269e3021894 213
elessair 0:f269e3021894 214 USBHostSerialPort::USBHostSerialPort(): circ_buf()
elessair 0:f269e3021894 215 {
elessair 0:f269e3021894 216 init();
elessair 0:f269e3021894 217 }
elessair 0:f269e3021894 218
elessair 0:f269e3021894 219 void USBHostSerialPort::init(void)
elessair 0:f269e3021894 220 {
elessair 0:f269e3021894 221 host = NULL;
elessair 0:f269e3021894 222 dev = NULL;
elessair 0:f269e3021894 223 serial_intf = NULL;
elessair 0:f269e3021894 224 size_bulk_in = 0;
elessair 0:f269e3021894 225 size_bulk_out = 0;
elessair 0:f269e3021894 226 bulk_in = NULL;
elessair 0:f269e3021894 227 bulk_out = NULL;
elessair 0:f269e3021894 228 line_coding.baudrate = 9600;
elessair 0:f269e3021894 229 line_coding.data_bits = 8;
elessair 0:f269e3021894 230 line_coding.parity = None;
elessair 0:f269e3021894 231 line_coding.stop_bits = 1;
elessair 0:f269e3021894 232 circ_buf.flush();
elessair 0:f269e3021894 233 }
elessair 0:f269e3021894 234
elessair 0:f269e3021894 235 void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev,
elessair 0:f269e3021894 236 uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out)
elessair 0:f269e3021894 237 {
elessair 0:f269e3021894 238 host = _host;
elessair 0:f269e3021894 239 dev = _dev;
elessair 0:f269e3021894 240 serial_intf = _serial_intf;
elessair 0:f269e3021894 241 bulk_in = _bulk_in;
elessair 0:f269e3021894 242 bulk_out = _bulk_out;
elessair 0:f269e3021894 243
elessair 0:f269e3021894 244 USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf);
elessair 0:f269e3021894 245 dev->setName("Serial", serial_intf);
elessair 0:f269e3021894 246 host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init);
elessair 0:f269e3021894 247 baud(9600);
elessair 0:f269e3021894 248 size_bulk_in = bulk_in->getSize();
elessair 0:f269e3021894 249 size_bulk_out = bulk_out->getSize();
elessair 0:f269e3021894 250 bulk_in->attach(this, &USBHostSerialPort::rxHandler);
elessair 0:f269e3021894 251 bulk_out->attach(this, &USBHostSerialPort::txHandler);
elessair 0:f269e3021894 252 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
elessair 0:f269e3021894 253 }
elessair 0:f269e3021894 254
elessair 0:f269e3021894 255 void USBHostSerialPort::rxHandler() {
elessair 0:f269e3021894 256 if (bulk_in) {
elessair 0:f269e3021894 257 int len = bulk_in->getLengthTransferred();
elessair 0:f269e3021894 258 if (bulk_in->getState() == USB_TYPE_IDLE) {
elessair 0:f269e3021894 259 for (int i = 0; i < len; i++) {
elessair 0:f269e3021894 260 circ_buf.queue(buf[i]);
elessair 0:f269e3021894 261 }
elessair 0:f269e3021894 262 rx.call();
elessair 0:f269e3021894 263 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
elessair 0:f269e3021894 264 }
elessair 0:f269e3021894 265 }
elessair 0:f269e3021894 266 }
elessair 0:f269e3021894 267
elessair 0:f269e3021894 268 void USBHostSerialPort::txHandler() {
elessair 0:f269e3021894 269 if (bulk_out) {
elessair 0:f269e3021894 270 if (bulk_out->getState() == USB_TYPE_IDLE) {
elessair 0:f269e3021894 271 tx.call();
elessair 0:f269e3021894 272 }
elessair 0:f269e3021894 273 }
elessair 0:f269e3021894 274 }
elessair 0:f269e3021894 275
elessair 0:f269e3021894 276 int USBHostSerialPort::_putc(int c) {
elessair 0:f269e3021894 277 if (bulk_out) {
elessair 0:f269e3021894 278 if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) {
elessair 0:f269e3021894 279 return 1;
elessair 0:f269e3021894 280 }
elessair 0:f269e3021894 281 }
elessair 0:f269e3021894 282 return -1;
elessair 0:f269e3021894 283 }
elessair 0:f269e3021894 284
elessair 0:f269e3021894 285 void USBHostSerialPort::baud(int baudrate) {
elessair 0:f269e3021894 286 line_coding.baudrate = baudrate;
elessair 0:f269e3021894 287 format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.stop_bits);
elessair 0:f269e3021894 288 }
elessair 0:f269e3021894 289
elessair 0:f269e3021894 290 void USBHostSerialPort::format(int bits, Parity parity, int stop_bits) {
elessair 0:f269e3021894 291 line_coding.data_bits = bits;
elessair 0:f269e3021894 292 line_coding.parity = parity;
elessair 0:f269e3021894 293 line_coding.stop_bits = (stop_bits == 1) ? 0 : 2;
elessair 0:f269e3021894 294
elessair 0:f269e3021894 295 // set line coding
elessair 0:f269e3021894 296 host->controlWrite( dev,
elessair 0:f269e3021894 297 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
elessair 0:f269e3021894 298 SET_LINE_CODING,
elessair 0:f269e3021894 299 0, serial_intf, (uint8_t *)&line_coding, 7);
elessair 0:f269e3021894 300 }
elessair 0:f269e3021894 301
elessair 0:f269e3021894 302 int USBHostSerialPort::_getc() {
elessair 0:f269e3021894 303 uint8_t c = 0;
elessair 0:f269e3021894 304 if (bulk_in == NULL) {
elessair 0:f269e3021894 305 init();
elessair 0:f269e3021894 306 return -1;
elessair 0:f269e3021894 307 }
elessair 0:f269e3021894 308 while (circ_buf.isEmpty());
elessair 0:f269e3021894 309 circ_buf.dequeue(&c);
elessair 0:f269e3021894 310 return c;
elessair 0:f269e3021894 311 }
elessair 0:f269e3021894 312
elessair 0:f269e3021894 313 int USBHostSerialPort::writeBuf(const char* b, int s)
elessair 0:f269e3021894 314 {
elessair 0:f269e3021894 315 int c = 0;
elessair 0:f269e3021894 316 if (bulk_out)
elessair 0:f269e3021894 317 {
elessair 0:f269e3021894 318 while (c < s)
elessair 0:f269e3021894 319 {
elessair 0:f269e3021894 320 int i = (s < size_bulk_out) ? s : size_bulk_out;
elessair 0:f269e3021894 321 if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK)
elessair 0:f269e3021894 322 c += i;
elessair 0:f269e3021894 323 }
elessair 0:f269e3021894 324 }
elessair 0:f269e3021894 325 return s;
elessair 0:f269e3021894 326 }
elessair 0:f269e3021894 327
elessair 0:f269e3021894 328 int USBHostSerialPort::readBuf(char* b, int s)
elessair 0:f269e3021894 329 {
elessair 0:f269e3021894 330 int i = 0;
elessair 0:f269e3021894 331 if (bulk_in)
elessair 0:f269e3021894 332 {
elessair 0:f269e3021894 333 for (i = 0; i < s; )
elessair 0:f269e3021894 334 b[i++] = getc();
elessair 0:f269e3021894 335 }
elessair 0:f269e3021894 336 return i;
elessair 0:f269e3021894 337 }
elessair 0:f269e3021894 338
elessair 0:f269e3021894 339 uint8_t USBHostSerialPort::available() {
elessair 0:f269e3021894 340 return circ_buf.available();
elessair 0:f269e3021894 341 }
elessair 0:f269e3021894 342
elessair 0:f269e3021894 343
elessair 0:f269e3021894 344
elessair 0:f269e3021894 345 #endif