Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 dev_connected = true; 00075 } 00076 } 00077 } 00078 return dev != NULL; 00079 } 00080 00081 /*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid) 00082 { 00083 // we don't check VID/PID for MSD driver 00084 } 00085 00086 /*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 00087 { 00088 if (!ports_found && 00089 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) { 00090 port_intf = intf_nb; 00091 ports_found = true; 00092 return true; 00093 } 00094 return false; 00095 } 00096 00097 /*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used 00098 { 00099 if (ports_found && (intf_nb == port_intf)) { 00100 if (type == BULK_ENDPOINT) 00101 return true; 00102 } 00103 return false; 00104 } 00105 00106 #else // (USBHOST_SERIAL > 1) 00107 00108 //------------------------------------------------------------------------------ 00109 00110 USBHostMultiSerial::USBHostMultiSerial() 00111 { 00112 host = USBHost::getHostInst(); 00113 dev = NULL; 00114 memset(ports, NULL, sizeof(ports)); 00115 ports_found = 0; 00116 dev_connected = false; 00117 } 00118 00119 USBHostMultiSerial::~USBHostMultiSerial() 00120 { 00121 disconnect(); 00122 } 00123 00124 bool USBHostMultiSerial::connected() 00125 { 00126 return dev_connected; 00127 } 00128 00129 void USBHostMultiSerial::disconnect(void) 00130 { 00131 for (int port = 0; port < USBHOST_SERIAL; port ++) 00132 { 00133 if (ports[port]) 00134 { 00135 delete ports[port]; 00136 ports[port] = NULL; 00137 } 00138 } 00139 ports_found = 0; 00140 dev = NULL; 00141 } 00142 00143 bool USBHostMultiSerial::connect() { 00144 00145 if (dev) 00146 { 00147 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) 00148 { 00149 USBDeviceConnected* d = host->getDevice(i); 00150 if (dev == d) 00151 return true; 00152 } 00153 disconnect(); 00154 } 00155 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) 00156 { 00157 USBDeviceConnected* d = host->getDevice(i); 00158 if (d != NULL) { 00159 00160 USB_DBG("Trying to connect serial device \r\n"); 00161 if(host->enumerate(d, this)) 00162 break; 00163 00164 for (int port = 0; port < ports_found; port ++) 00165 { 00166 USBEndpoint* bulk_in = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN); 00167 USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT); 00168 if (bulk_in && bulk_out) 00169 { 00170 ports[port] = new USBHostSerialPort(); 00171 if (ports[port]) 00172 { 00173 ports[port]->connect(host,d,port_intf[port],bulk_in, bulk_out); 00174 dev = d; 00175 dev_connected = true; 00176 } 00177 } 00178 } 00179 } 00180 } 00181 return dev != NULL; 00182 } 00183 00184 /*virtual*/ void USBHostMultiSerial::setVidPid(uint16_t vid, uint16_t pid) 00185 { 00186 // we don't check VID/PID for MSD driver 00187 } 00188 00189 /*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 00190 { 00191 if ((ports_found < USBHOST_SERIAL) && 00192 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) { 00193 port_intf[ports_found++] = intf_nb; 00194 return true; 00195 } 00196 return false; 00197 } 00198 00199 /*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used 00200 { 00201 if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) { 00202 if (type == BULK_ENDPOINT) 00203 return true; 00204 } 00205 return false; 00206 } 00207 00208 #endif 00209 00210 //------------------------------------------------------------------------------ 00211 00212 #define SET_LINE_CODING 0x20 00213 00214 USBHostSerialPort::USBHostSerialPort(): circ_buf() 00215 { 00216 init(); 00217 } 00218 00219 void USBHostSerialPort::init(void) 00220 { 00221 host = NULL; 00222 dev = NULL; 00223 serial_intf = NULL; 00224 size_bulk_in = 0; 00225 size_bulk_out = 0; 00226 bulk_in = NULL; 00227 bulk_out = NULL; 00228 line_coding.baudrate = 9600; 00229 line_coding.data_bits = 8; 00230 line_coding.parity = None; 00231 line_coding.stop_bits = 1; 00232 circ_buf.flush(); 00233 } 00234 00235 void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev, 00236 uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out) 00237 { 00238 host = _host; 00239 dev = _dev; 00240 serial_intf = _serial_intf; 00241 bulk_in = _bulk_in; 00242 bulk_out = _bulk_out; 00243 00244 USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf); 00245 dev->setName("Serial", serial_intf); 00246 host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init); 00247 baud(9600); 00248 size_bulk_in = bulk_in->getSize(); 00249 size_bulk_out = bulk_out->getSize(); 00250 bulk_in->attach(this, &USBHostSerialPort::rxHandler); 00251 bulk_out->attach(this, &USBHostSerialPort::txHandler); 00252 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); 00253 } 00254 00255 void USBHostSerialPort::rxHandler() { 00256 if (bulk_in) { 00257 int len = bulk_in->getLengthTransferred(); 00258 if (bulk_in->getState() == USB_TYPE_IDLE) { 00259 for (int i = 0; i < len; i++) { 00260 circ_buf.queue(buf[i]); 00261 } 00262 rx.call(); 00263 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); 00264 } 00265 } 00266 } 00267 00268 void USBHostSerialPort::txHandler() { 00269 if (bulk_out) { 00270 if (bulk_out->getState() == USB_TYPE_IDLE) { 00271 tx.call(); 00272 } 00273 } 00274 } 00275 00276 int USBHostSerialPort::_putc(int c) { 00277 if (bulk_out) { 00278 if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) { 00279 return 1; 00280 } 00281 } 00282 return -1; 00283 } 00284 00285 void USBHostSerialPort::baud(int baudrate) { 00286 line_coding.baudrate = baudrate; 00287 format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.stop_bits); 00288 } 00289 00290 void USBHostSerialPort::format(int bits, Parity parity, int stop_bits) { 00291 line_coding.data_bits = bits; 00292 line_coding.parity = parity; 00293 line_coding.stop_bits = (stop_bits == 1) ? 0 : 2; 00294 00295 // set line coding 00296 host->controlWrite( dev, 00297 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, 00298 SET_LINE_CODING, 00299 0, serial_intf, (uint8_t *)&line_coding, 7); 00300 } 00301 00302 int USBHostSerialPort::_getc() { 00303 uint8_t c = 0; 00304 if (bulk_in == NULL) { 00305 init(); 00306 return -1; 00307 } 00308 while (circ_buf.isEmpty()); 00309 circ_buf.dequeue(&c); 00310 return c; 00311 } 00312 00313 int USBHostSerialPort::writeBuf(const char* b, int s) 00314 { 00315 int c = 0; 00316 if (bulk_out) 00317 { 00318 while (c < s) 00319 { 00320 int i = (s < size_bulk_out) ? s : size_bulk_out; 00321 if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK) 00322 c += i; 00323 } 00324 } 00325 return s; 00326 } 00327 00328 int USBHostSerialPort::readBuf(char* b, int s) 00329 { 00330 int i = 0; 00331 if (bulk_in) 00332 { 00333 for (i = 0; i < s; ) 00334 b[i++] = getc(); 00335 } 00336 return i; 00337 } 00338 00339 uint8_t USBHostSerialPort::available() { 00340 return circ_buf.available(); 00341 } 00342 00343 00344 00345 #endif
Generated on Tue Jul 12 2022 14:25:20 by
