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.
WANDongleSerialPort.cpp
00001 /* Copyright (c) 2010-2012 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "USBHostConf.h" 00020 00021 #ifdef USBHOST_3GMODULE 00022 00023 #define __DEBUG__ 0 00024 #ifndef __MODULE__ 00025 #define __MODULE__ "WANDongleSerialPort.cpp" 00026 #endif 00027 00028 #include "dbg.h" 00029 #include <stdint.h> 00030 #include "rtos.h" 00031 00032 #include "WANDongleSerialPort.h" 00033 00034 WANDongleSerialPort::WANDongleSerialPort() : cb_tx_en(false), cb_rx_en(false), listener(NULL) 00035 { 00036 reset(); 00037 } 00038 00039 void WANDongleSerialPort::init(USBHost* pHost) 00040 { 00041 host = pHost; 00042 } 00043 00044 void WANDongleSerialPort::reset() 00045 { 00046 tx_mtx.lock(); 00047 rx_mtx.lock(); 00048 00049 bulk_in = NULL; 00050 bulk_out = NULL; 00051 00052 buf_out_len = 0; 00053 max_out_size = 0; 00054 lock_tx = false; 00055 cb_tx_pending = false; 00056 00057 buf_in_len = 0; 00058 buf_in_read_pos = 0; 00059 lock_rx = false; 00060 cb_rx_pending = false; 00061 00062 tx_mtx.unlock(); 00063 rx_mtx.unlock(); 00064 } 00065 00066 int WANDongleSerialPort::readPacket() 00067 { 00068 USB_DBG("Read packet on %p", this); 00069 rx_mtx.lock(); 00070 if(lock_rx) 00071 { 00072 USB_ERR("Fail"); 00073 rx_mtx.unlock(); 00074 return -1; 00075 } 00076 00077 if( bulk_in == NULL ) 00078 { 00079 USB_WARN("Port is disconnected"); 00080 rx_mtx.unlock(); 00081 return -1; 00082 } 00083 00084 lock_rx = true; //Receiving 00085 rx_mtx.unlock(); 00086 // USB_DBG("readPacket"); 00087 //lock_rx.lock(); 00088 USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer 00089 if(res != USB_TYPE_PROCESSING) 00090 { 00091 //lock_rx.unlock(); 00092 USB_ERR("host->bulkRead() returned %d", res); 00093 Thread::wait(100); 00094 return -1; 00095 } 00096 return 0; 00097 } 00098 00099 int WANDongleSerialPort::writePacket() 00100 { 00101 tx_mtx.lock(); 00102 if(lock_tx) 00103 { 00104 USB_ERR("Fail"); 00105 tx_mtx.unlock(); 00106 return -1; 00107 } 00108 00109 if( bulk_out == NULL ) 00110 { 00111 USB_WARN("Port is disconnected"); 00112 tx_mtx.unlock(); 00113 return -1; 00114 } 00115 00116 lock_tx = true; //Transmitting 00117 tx_mtx.unlock(); 00118 // USB_DBG("writePacket"); 00119 00120 //lock_tx.lock(); 00121 USB_TYPE res = host->bulkWrite(dev, (USBEndpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer 00122 if(res != USB_TYPE_PROCESSING) 00123 { 00124 //lock_tx.unlock(); 00125 USB_ERR("host->bulkWrite() returned %d", res); 00126 Thread::wait(100); 00127 return -1; 00128 } 00129 return 0; 00130 } 00131 00132 int WANDongleSerialPort::putc(int c) 00133 { 00134 tx_mtx.lock(); 00135 if(!lock_tx) 00136 { 00137 if(buf_out_len < max_out_size) 00138 { 00139 buf_out[buf_out_len] = (uint8_t)c; 00140 buf_out_len++; 00141 } 00142 } 00143 else 00144 { 00145 USB_ERR("CAN'T WRITE!"); 00146 } 00147 tx_mtx.unlock(); 00148 return c; 00149 } 00150 00151 int WANDongleSerialPort::getc() 00152 { 00153 rx_mtx.lock(); 00154 int c = 0; 00155 if(!lock_rx) 00156 { 00157 if(buf_in_read_pos < buf_in_len) 00158 { 00159 c = (int)buf_in[buf_in_read_pos]; 00160 buf_in_read_pos++; 00161 } 00162 } 00163 else 00164 { 00165 USB_ERR("CAN'T READ!"); 00166 } 00167 rx_mtx.unlock(); 00168 return c; 00169 } 00170 00171 int WANDongleSerialPort::readable() 00172 { 00173 rx_mtx.lock(); 00174 if (lock_rx) 00175 { 00176 rx_mtx.unlock(); 00177 return 0; 00178 } 00179 00180 /* if( !lock_rx.trylock() ) 00181 { 00182 return 0; 00183 }*/ 00184 int res = buf_in_len - buf_in_read_pos; 00185 //lock_rx.unlock(); 00186 rx_mtx.unlock(); 00187 return res; 00188 } 00189 00190 int WANDongleSerialPort::writeable() 00191 { 00192 tx_mtx.lock(); 00193 if (lock_tx) 00194 { 00195 tx_mtx.unlock(); 00196 return 0; 00197 } 00198 00199 /*if( !lock_tx.trylock() ) 00200 { 00201 return 0; 00202 }*/ 00203 int res = max_out_size - buf_out_len; 00204 tx_mtx.unlock(); 00205 //lock_tx.unlock(); 00206 return res; 00207 } 00208 00209 void WANDongleSerialPort::attach(IUSBHostSerialListener* pListener) 00210 { 00211 if(pListener == NULL) 00212 { 00213 setupIrq(false, RxIrq); 00214 setupIrq(false, TxIrq); 00215 } 00216 listener = pListener; 00217 if(pListener != NULL) 00218 { 00219 setupIrq(true, RxIrq); 00220 setupIrq(true, TxIrq); 00221 } 00222 } 00223 00224 void WANDongleSerialPort::setupIrq(bool en, IrqType irq /*= RxIrq*/) 00225 { 00226 switch(irq) 00227 { 00228 case RxIrq: 00229 rx_mtx.lock(); 00230 cb_rx_en = en; 00231 if(en && cb_rx_pending) 00232 { 00233 cb_rx_pending = false; 00234 rx_mtx.unlock(); 00235 listener->readable(); //Process the interrupt that was raised 00236 } 00237 else 00238 { 00239 rx_mtx.unlock(); 00240 } 00241 break; 00242 case TxIrq: 00243 tx_mtx.lock(); 00244 cb_tx_en = en; 00245 if(en && cb_tx_pending) 00246 { 00247 cb_tx_pending = false; 00248 tx_mtx.unlock(); 00249 listener->writeable(); //Process the interrupt that was raised 00250 } 00251 else 00252 { 00253 tx_mtx.unlock(); 00254 } 00255 break; 00256 } 00257 } 00258 00259 00260 void WANDongleSerialPort::connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp ) 00261 { 00262 dev = pDev; 00263 bulk_in = pInEp; 00264 bulk_out = pOutEp; 00265 max_out_size = bulk_out->getSize(); 00266 if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE ) 00267 { 00268 max_out_size = WANDONGLE_MAX_OUTEP_SIZE; 00269 } 00270 bulk_in->attach(this, &WANDongleSerialPort::rxHandler); 00271 bulk_out->attach(this, &WANDongleSerialPort::txHandler); 00272 readPacket(); //Start receiving data 00273 } 00274 00275 void WANDongleSerialPort::disconnect( ) 00276 { 00277 reset(); 00278 } 00279 00280 //Private methods 00281 00282 00283 void WANDongleSerialPort::rxHandler() 00284 { 00285 if (((USBEndpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success 00286 { 00287 buf_in_read_pos = 0; 00288 buf_in_len = ((USBEndpoint *) bulk_in)->getLengthTransferred(); //Update length 00289 //lock_rx.unlock(); 00290 rx_mtx.lock(); 00291 lock_rx = false; //Transmission complete 00292 if(cb_rx_en) 00293 { 00294 rx_mtx.unlock(); 00295 listener->readable(); //Call handler from the IRQ context 00296 //readPacket() should be called by the handler subsequently once the buffer has been emptied 00297 } 00298 else 00299 { 00300 cb_rx_pending = true; //Queue the callback 00301 rx_mtx.unlock(); 00302 } 00303 00304 } 00305 else //Error, try reading again 00306 { 00307 //lock_rx.unlock(); 00308 USB_DBG("Trying again"); 00309 readPacket(); 00310 } 00311 } 00312 00313 void WANDongleSerialPort::txHandler() 00314 { 00315 if (((USBEndpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success 00316 { 00317 tx_mtx.lock(); 00318 buf_out_len = 0; //Reset length 00319 lock_tx = false; //Transmission complete 00320 //lock_tx.unlock(); 00321 if(cb_tx_en) 00322 { 00323 tx_mtx.unlock(); 00324 listener->writeable(); //Call handler from the IRQ context 00325 //writePacket() should be called by the handler subsequently once the buffer has been filled 00326 } 00327 else 00328 { 00329 cb_tx_pending = true; //Queue the callback 00330 tx_mtx.unlock(); 00331 } 00332 } 00333 else //Error, try reading again 00334 { 00335 //lock_tx.unlock(); 00336 writePacket(); 00337 } 00338 } 00339 00340 #endif /* USBHOST_3GMODULE */
Generated on Tue Jul 12 2022 18:18:55 by
