USBHost library

Dependencies:   FATFileSystem

Dependents:   Project RoboticsCatAndMouse_HumanDriver RoboticsCatAndMouse_AutonomousDriver

Fork of USBHost by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHostSerial.cpp Source File

USBHostSerial.cpp

00001 /* mbed USBHost Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "USBHostSerial.h"
00018 
00019 #if USBHOST_SERIAL
00020 
00021 #include "dbg.h"
00022 
00023 #define CHECK_INTERFACE(cls,subcls,proto) \
00024         (((cls == 0xFF)         && (subcls == 0xFF) && (proto == 0xFF)) /* QUALCOM CDC */  || \
00025          ((cls == SERIAL_CLASS) && (subcls == 0x00) && (proto == 0x00)) /* STANDARD CDC */ )
00026 
00027 #if (USBHOST_SERIAL <= 1)
00028 
00029 USBHostSerial::USBHostSerial() 
00030 {
00031     host = USBHost::getHostInst();
00032     ports_found = 0;
00033     dev_connected = false;
00034 }
00035 
00036 bool USBHostSerial::connected()
00037 {
00038     return dev_connected;
00039 }
00040 
00041 void USBHostSerial::disconnect(void)
00042 {
00043     ports_found = 0;
00044     dev = NULL;
00045 }
00046 
00047 bool USBHostSerial::connect() {
00048 
00049     if (dev) 
00050     {
00051         for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) 
00052         {
00053             USBDeviceConnected* d = host->getDevice(i);
00054             if (dev == d)
00055                 return true;
00056         }
00057         disconnect();
00058     }
00059     for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) 
00060     {
00061         USBDeviceConnected* d = host->getDevice(i);
00062         if (d != NULL) {
00063             
00064             USB_DBG("Trying to connect serial device \r\n");
00065             if(host->enumerate(d, this))
00066                 break;
00067             
00068             USBEndpoint* bulk_in  = d->getEndpoint(port_intf, BULK_ENDPOINT, IN);
00069             USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT);
00070             if (bulk_in && bulk_out)
00071             {
00072                 USBHostSerialPort::connect(host,d,port_intf,bulk_in, bulk_out);
00073                 dev = d;
00074             }
00075         }
00076     }
00077     return dev != NULL;
00078 }
00079 
00080 /*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid)
00081 {
00082     // we don't check VID/PID for MSD driver
00083 }
00084 
00085 /*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
00086 {
00087     if (!ports_found && 
00088         CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
00089         port_intf = intf_nb;
00090         ports_found = true;
00091         return true;
00092     }
00093     return false;
00094 }
00095 
00096 /*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
00097 {
00098     if (ports_found && (intf_nb == port_intf)) {
00099         if (type == BULK_ENDPOINT) 
00100             return true;
00101     }
00102     return false;
00103 }
00104 
00105 #else // (USBHOST_SERIAL > 1)
00106 
00107 //------------------------------------------------------------------------------
00108 
00109 USBHostMultiSerial::USBHostMultiSerial() 
00110 {
00111     host = USBHost::getHostInst();
00112     dev = NULL;
00113     memset(ports, NULL, sizeof(ports));
00114     ports_found = 0;
00115     dev_connected = false;
00116 }
00117 
00118 USBHostMultiSerial::~USBHostMultiSerial()
00119 {
00120     disconnect();
00121 }
00122 
00123 bool USBHostMultiSerial::connected()
00124 {
00125     return dev_connected;
00126 }
00127 
00128 void USBHostMultiSerial::disconnect(void)
00129 {
00130     for (int port = 0; port < USBHOST_SERIAL; port ++) 
00131     {
00132         if (ports[port])
00133         {
00134             delete ports[port];
00135             ports[port] = NULL;
00136         }
00137     }
00138     ports_found = 0;
00139     dev = NULL;
00140 }
00141 
00142 bool USBHostMultiSerial::connect() {
00143 
00144     if (dev) 
00145     {
00146         for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) 
00147         {
00148             USBDeviceConnected* d = host->getDevice(i);
00149             if (dev == d)
00150                 return true;
00151         }
00152         disconnect();
00153     }
00154     for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) 
00155     {
00156         USBDeviceConnected* d = host->getDevice(i);
00157         if (d != NULL) {
00158             
00159             USB_DBG("Trying to connect serial device \r\n");
00160             if(host->enumerate(d, this))
00161                 break;
00162             
00163             for (int port = 0; port < ports_found; port ++) 
00164             {
00165                 USBEndpoint* bulk_in  = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN);
00166                 USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT);
00167                 if (bulk_in && bulk_out)
00168                 {
00169                     ports[port] = new USBHostSerialPort();
00170                     if (ports[port])
00171                     {
00172                         ports[port]->connect(host,d,port_intf[port],bulk_in, bulk_out);
00173                         dev = d;
00174                     }
00175                 }
00176             }
00177         }
00178     }
00179     return dev != NULL;
00180 }
00181 
00182 /*virtual*/ void USBHostMultiSerial::setVidPid(uint16_t vid, uint16_t pid)
00183 {
00184     // we don't check VID/PID for MSD driver
00185 }
00186 
00187 /*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
00188 {
00189     if ((ports_found < USBHOST_SERIAL) && 
00190         CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
00191         port_intf[ports_found++] = intf_nb;
00192         return true;
00193     }
00194     return false;
00195 }
00196 
00197 /*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
00198 {
00199     if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) {
00200         if (type == BULK_ENDPOINT) 
00201             return true;
00202     }
00203     return false;
00204 }
00205 
00206 #endif
00207 
00208 //------------------------------------------------------------------------------
00209 
00210 #define SET_LINE_CODING 0x20
00211 
00212 USBHostSerialPort::USBHostSerialPort(): circ_buf() 
00213 {
00214     init();
00215 }
00216 
00217 void USBHostSerialPort::init(void)
00218 {
00219     host = NULL;
00220     dev = NULL;
00221     serial_intf = NULL;
00222     size_bulk_in = 0;
00223     size_bulk_out = 0;
00224     bulk_in = NULL;
00225     bulk_out = NULL;
00226     line_coding.baudrate = 9600;
00227     line_coding.data_bits = 8;
00228     line_coding.parity = None;
00229     line_coding.stop_bits = 1;
00230     circ_buf.flush();
00231 }
00232 
00233 void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev, 
00234         uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out)
00235 {
00236     host = _host;
00237     dev = _dev;
00238     serial_intf = _serial_intf;
00239     bulk_in = _bulk_in;
00240     bulk_out = _bulk_out;
00241     
00242     USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf);
00243     dev->setName("Serial", serial_intf);
00244     host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init);
00245     //baud(9600);
00246     size_bulk_in = bulk_in->getSize();
00247     size_bulk_out = bulk_out->getSize();
00248     bulk_in->attach(this, &USBHostSerialPort::rxHandler);
00249     bulk_out->attach(this, &USBHostSerialPort::txHandler);
00250     host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
00251 }
00252 
00253 void USBHostSerialPort::rxHandler() {
00254     if (bulk_in) {
00255         int len = bulk_in->getLengthTransferred();
00256         if (bulk_in->getState() == USB_TYPE_IDLE) {
00257             for (int i = 0; i < len; i++) {
00258                 circ_buf.queue(buf[i]);
00259             }
00260             rx.call();
00261             host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
00262         }
00263     }
00264 }
00265 
00266 void USBHostSerialPort::txHandler() {
00267     if (bulk_out) {
00268         if (bulk_out->getState() == USB_TYPE_IDLE) {
00269             tx.call();
00270         }
00271     }
00272 }
00273 
00274 int USBHostSerialPort::_putc(int c) {
00275     if (bulk_out) {
00276         if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) {
00277             return 1;
00278         }
00279     }
00280     return -1;
00281 }
00282 
00283 void USBHostSerialPort::baud(int baudrate) {
00284     line_coding.baudrate = baudrate;
00285     format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.stop_bits);
00286 }
00287 
00288 void USBHostSerialPort::format(int bits, Parity parity, int stop_bits) {
00289     line_coding.data_bits = bits;
00290     line_coding.parity = parity;
00291     line_coding.stop_bits = (stop_bits == 1) ? 0 : 2;
00292     
00293     // set line coding
00294     host->controlWrite( dev,
00295                         USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
00296                         SET_LINE_CODING,
00297                         0, serial_intf, (uint8_t *)&line_coding, 7);
00298 }
00299 
00300 int USBHostSerialPort::_getc() {
00301     uint8_t c = 0;
00302     if (bulk_in == NULL) {
00303         init();
00304         return -1;
00305     }
00306     while (circ_buf.isEmpty());
00307     circ_buf.dequeue(&c);
00308     return c;
00309 }
00310 
00311 int USBHostSerialPort::writeBuf(const char* b, int s)
00312 {
00313     int c = 0;
00314     if (bulk_out) 
00315     {
00316         while (c < s)
00317         {
00318             int i = (s < size_bulk_out) ? s : size_bulk_out;
00319             if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK) 
00320                 c += i;
00321         }
00322     }
00323     return s;
00324 }
00325 
00326 int USBHostSerialPort::readBuf(char* b, int s)
00327 {
00328     int i = 0;
00329     if (bulk_in) 
00330     {
00331         for (i = 0; i < s; )
00332             b[i++] = getc();
00333     }
00334     return i;
00335 }
00336 
00337 uint8_t USBHostSerialPort::available() {
00338     return circ_buf.available();
00339 }
00340 
00341 
00342 
00343 #endif