USB Host WAN Dongle library

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Committer:
ashleymills
Date:
Fri Sep 20 10:40:15 2013 +0000
Revision:
27:980fe31c14f7
Parent:
24:f4b676f61906
Added support for Ublox LISA U200 module

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donatien 10:08bce4cd973a 1 /* Copyright (c) 2010-2012 mbed.org, MIT License
donatien 9:c9e9817c398c 2 *
donatien 9:c9e9817c398c 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
donatien 9:c9e9817c398c 4 * and associated documentation files (the "Software"), to deal in the Software without
donatien 9:c9e9817c398c 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
donatien 9:c9e9817c398c 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
donatien 9:c9e9817c398c 7 * Software is furnished to do so, subject to the following conditions:
donatien 9:c9e9817c398c 8 *
donatien 9:c9e9817c398c 9 * The above copyright notice and this permission notice shall be included in all copies or
donatien 9:c9e9817c398c 10 * substantial portions of the Software.
donatien 9:c9e9817c398c 11 *
donatien 9:c9e9817c398c 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
donatien 9:c9e9817c398c 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
donatien 9:c9e9817c398c 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
donatien 9:c9e9817c398c 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
donatien 9:c9e9817c398c 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
donatien 9:c9e9817c398c 17 */
donatien 9:c9e9817c398c 18
ashleymills 24:f4b676f61906 19 #define __DEBUG__ 0
donatien 9:c9e9817c398c 20 #ifndef __MODULE__
donatien 9:c9e9817c398c 21 #define __MODULE__ "WANDongleSerialPort.cpp"
donatien 9:c9e9817c398c 22 #endif
donatien 9:c9e9817c398c 23
donatien 12:a712bad7a979 24 #include "core/dbg.h"
donatien 9:c9e9817c398c 25 #include <cstdint>
donatien 9:c9e9817c398c 26 #include "rtos.h"
donatien 9:c9e9817c398c 27
donatien 9:c9e9817c398c 28 #include "WANDongleSerialPort.h"
donatien 9:c9e9817c398c 29
donatien 9:c9e9817c398c 30 WANDongleSerialPort::WANDongleSerialPort() : cb_tx_en(false), cb_rx_en(false), listener(NULL)
donatien 9:c9e9817c398c 31 {
donatien 9:c9e9817c398c 32 reset();
donatien 9:c9e9817c398c 33 }
donatien 9:c9e9817c398c 34
donatien 9:c9e9817c398c 35 void WANDongleSerialPort::init(USBHost* pHost)
donatien 9:c9e9817c398c 36 {
donatien 9:c9e9817c398c 37 host = pHost;
donatien 9:c9e9817c398c 38 }
donatien 9:c9e9817c398c 39
donatien 9:c9e9817c398c 40 void WANDongleSerialPort::reset()
donatien 9:c9e9817c398c 41 {
donatien 10:08bce4cd973a 42 tx_mtx.lock();
donatien 10:08bce4cd973a 43 rx_mtx.lock();
donatien 10:08bce4cd973a 44
donatien 9:c9e9817c398c 45 bulk_in = NULL;
donatien 9:c9e9817c398c 46 bulk_out = NULL;
donatien 9:c9e9817c398c 47
donatien 9:c9e9817c398c 48 buf_out_len = 0;
donatien 9:c9e9817c398c 49 max_out_size = 0;
donatien 9:c9e9817c398c 50 lock_tx = false;
donatien 9:c9e9817c398c 51 cb_tx_pending = false;
donatien 9:c9e9817c398c 52
donatien 9:c9e9817c398c 53 buf_in_len = 0;
donatien 9:c9e9817c398c 54 buf_in_read_pos = 0;
donatien 9:c9e9817c398c 55 lock_rx = false;
donatien 9:c9e9817c398c 56 cb_rx_pending = false;
donatien 10:08bce4cd973a 57
donatien 10:08bce4cd973a 58 tx_mtx.unlock();
donatien 10:08bce4cd973a 59 rx_mtx.unlock();
donatien 9:c9e9817c398c 60 }
donatien 9:c9e9817c398c 61
donatien 9:c9e9817c398c 62 int WANDongleSerialPort::readPacket()
donatien 9:c9e9817c398c 63 {
donatien 10:08bce4cd973a 64 DBG("Read packet on %p", this);
donatien 9:c9e9817c398c 65 rx_mtx.lock();
donatien 9:c9e9817c398c 66 if(lock_rx)
donatien 9:c9e9817c398c 67 {
donatien 9:c9e9817c398c 68 ERR("Fail");
donatien 9:c9e9817c398c 69 rx_mtx.unlock();
donatien 9:c9e9817c398c 70 return -1;
donatien 9:c9e9817c398c 71 }
donatien 10:08bce4cd973a 72
donatien 10:08bce4cd973a 73 if( bulk_in == NULL )
donatien 10:08bce4cd973a 74 {
donatien 10:08bce4cd973a 75 WARN("Port is disconnected");
donatien 10:08bce4cd973a 76 rx_mtx.unlock();
donatien 10:08bce4cd973a 77 return -1;
donatien 10:08bce4cd973a 78 }
donatien 9:c9e9817c398c 79
donatien 9:c9e9817c398c 80 lock_rx = true; //Receiving
donatien 9:c9e9817c398c 81 rx_mtx.unlock();
donatien 9:c9e9817c398c 82 // DBG("readPacket");
donatien 9:c9e9817c398c 83 //lock_rx.lock();
donatien 9:c9e9817c398c 84 host->lock();
donatien 9:c9e9817c398c 85 USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer
donatien 9:c9e9817c398c 86 if(res != USB_TYPE_PROCESSING)
donatien 9:c9e9817c398c 87 {
donatien 9:c9e9817c398c 88 host->unlock();
donatien 9:c9e9817c398c 89 //lock_rx.unlock();
donatien 9:c9e9817c398c 90 ERR("host->bulkRead() returned %d", res);
donatien 9:c9e9817c398c 91 Thread::wait(100);
donatien 9:c9e9817c398c 92 return -1;
donatien 9:c9e9817c398c 93 }
donatien 9:c9e9817c398c 94 host->unlock();
donatien 9:c9e9817c398c 95 return 0;
donatien 9:c9e9817c398c 96 }
donatien 9:c9e9817c398c 97
donatien 9:c9e9817c398c 98 int WANDongleSerialPort::writePacket()
donatien 9:c9e9817c398c 99 {
donatien 9:c9e9817c398c 100 tx_mtx.lock();
donatien 9:c9e9817c398c 101 if(lock_tx)
donatien 9:c9e9817c398c 102 {
donatien 9:c9e9817c398c 103 ERR("Fail");
donatien 9:c9e9817c398c 104 tx_mtx.unlock();
donatien 9:c9e9817c398c 105 return -1;
donatien 9:c9e9817c398c 106 }
donatien 10:08bce4cd973a 107
donatien 10:08bce4cd973a 108 if( bulk_out == NULL )
donatien 10:08bce4cd973a 109 {
donatien 10:08bce4cd973a 110 WARN("Port is disconnected");
donatien 10:08bce4cd973a 111 tx_mtx.unlock();
donatien 10:08bce4cd973a 112 return -1;
donatien 10:08bce4cd973a 113 }
donatien 9:c9e9817c398c 114
donatien 9:c9e9817c398c 115 lock_tx = true; //Transmitting
donatien 9:c9e9817c398c 116 tx_mtx.unlock();
donatien 9:c9e9817c398c 117 // DBG("writePacket");
donatien 9:c9e9817c398c 118
donatien 9:c9e9817c398c 119 //lock_tx.lock();
donatien 9:c9e9817c398c 120 host->lock();
donatien 9:c9e9817c398c 121 USB_TYPE res = host->bulkWrite(dev, (USBEndpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
donatien 9:c9e9817c398c 122 if(res != USB_TYPE_PROCESSING)
donatien 9:c9e9817c398c 123 {
donatien 9:c9e9817c398c 124 host->unlock();
donatien 9:c9e9817c398c 125 //lock_tx.unlock();
donatien 9:c9e9817c398c 126 ERR("host->bulkWrite() returned %d", res);
donatien 9:c9e9817c398c 127 Thread::wait(100);
donatien 9:c9e9817c398c 128 return -1;
donatien 9:c9e9817c398c 129 }
donatien 9:c9e9817c398c 130 host->unlock();
donatien 9:c9e9817c398c 131 return 0;
donatien 9:c9e9817c398c 132 }
donatien 9:c9e9817c398c 133
donatien 9:c9e9817c398c 134 int WANDongleSerialPort::putc(int c)
donatien 9:c9e9817c398c 135 {
donatien 9:c9e9817c398c 136 tx_mtx.lock();
donatien 9:c9e9817c398c 137 if(!lock_tx)
donatien 9:c9e9817c398c 138 {
donatien 9:c9e9817c398c 139 if(buf_out_len < max_out_size)
donatien 9:c9e9817c398c 140 {
donatien 9:c9e9817c398c 141 buf_out[buf_out_len] = (uint8_t)c;
donatien 9:c9e9817c398c 142 buf_out_len++;
donatien 9:c9e9817c398c 143 }
donatien 9:c9e9817c398c 144 }
donatien 9:c9e9817c398c 145 else
donatien 9:c9e9817c398c 146 {
donatien 9:c9e9817c398c 147 ERR("CAN'T WRITE!");
donatien 9:c9e9817c398c 148 }
donatien 9:c9e9817c398c 149 tx_mtx.unlock();
donatien 9:c9e9817c398c 150 return c;
donatien 9:c9e9817c398c 151 }
donatien 9:c9e9817c398c 152
donatien 9:c9e9817c398c 153 int WANDongleSerialPort::getc()
donatien 9:c9e9817c398c 154 {
donatien 9:c9e9817c398c 155 rx_mtx.lock();
donatien 9:c9e9817c398c 156 int c = 0;
donatien 9:c9e9817c398c 157 if(!lock_rx)
donatien 9:c9e9817c398c 158 {
donatien 9:c9e9817c398c 159 if(buf_in_read_pos < buf_in_len)
donatien 9:c9e9817c398c 160 {
donatien 9:c9e9817c398c 161 c = (int)buf_in[buf_in_read_pos];
donatien 9:c9e9817c398c 162 buf_in_read_pos++;
donatien 9:c9e9817c398c 163 }
donatien 9:c9e9817c398c 164 }
donatien 9:c9e9817c398c 165 else
donatien 9:c9e9817c398c 166 {
donatien 9:c9e9817c398c 167 ERR("CAN'T READ!");
donatien 9:c9e9817c398c 168 }
donatien 9:c9e9817c398c 169 rx_mtx.unlock();
donatien 9:c9e9817c398c 170 return c;
donatien 9:c9e9817c398c 171 }
donatien 9:c9e9817c398c 172
donatien 9:c9e9817c398c 173 int WANDongleSerialPort::readable()
donatien 9:c9e9817c398c 174 {
donatien 9:c9e9817c398c 175 rx_mtx.lock();
donatien 9:c9e9817c398c 176 if (lock_rx)
donatien 9:c9e9817c398c 177 {
donatien 9:c9e9817c398c 178 rx_mtx.unlock();
donatien 9:c9e9817c398c 179 return 0;
donatien 9:c9e9817c398c 180 }
donatien 9:c9e9817c398c 181
donatien 9:c9e9817c398c 182 /* if( !lock_rx.trylock() )
donatien 9:c9e9817c398c 183 {
donatien 9:c9e9817c398c 184 return 0;
donatien 9:c9e9817c398c 185 }*/
donatien 9:c9e9817c398c 186 int res = buf_in_len - buf_in_read_pos;
donatien 9:c9e9817c398c 187 //lock_rx.unlock();
donatien 9:c9e9817c398c 188 rx_mtx.unlock();
donatien 9:c9e9817c398c 189 return res;
donatien 9:c9e9817c398c 190 }
donatien 9:c9e9817c398c 191
donatien 9:c9e9817c398c 192 int WANDongleSerialPort::writeable()
donatien 9:c9e9817c398c 193 {
donatien 9:c9e9817c398c 194 tx_mtx.lock();
donatien 9:c9e9817c398c 195 if (lock_tx)
donatien 9:c9e9817c398c 196 {
donatien 9:c9e9817c398c 197 tx_mtx.unlock();
donatien 9:c9e9817c398c 198 return 0;
donatien 9:c9e9817c398c 199 }
donatien 9:c9e9817c398c 200
donatien 9:c9e9817c398c 201 /*if( !lock_tx.trylock() )
donatien 9:c9e9817c398c 202 {
donatien 9:c9e9817c398c 203 return 0;
donatien 9:c9e9817c398c 204 }*/
donatien 9:c9e9817c398c 205 int res = max_out_size - buf_out_len;
donatien 9:c9e9817c398c 206 tx_mtx.unlock();
donatien 9:c9e9817c398c 207 //lock_tx.unlock();
donatien 9:c9e9817c398c 208 return res;
donatien 9:c9e9817c398c 209 }
donatien 9:c9e9817c398c 210
donatien 9:c9e9817c398c 211 void WANDongleSerialPort::attach(IUSBHostSerialListener* pListener)
donatien 9:c9e9817c398c 212 {
donatien 9:c9e9817c398c 213 if(pListener == NULL)
donatien 9:c9e9817c398c 214 {
donatien 9:c9e9817c398c 215 setupIrq(false, RxIrq);
donatien 9:c9e9817c398c 216 setupIrq(false, TxIrq);
donatien 9:c9e9817c398c 217 }
donatien 9:c9e9817c398c 218 listener = pListener;
donatien 9:c9e9817c398c 219 if(pListener != NULL)
donatien 9:c9e9817c398c 220 {
donatien 9:c9e9817c398c 221 setupIrq(true, RxIrq);
donatien 9:c9e9817c398c 222 setupIrq(true, TxIrq);
donatien 9:c9e9817c398c 223 }
donatien 9:c9e9817c398c 224 }
donatien 9:c9e9817c398c 225
donatien 9:c9e9817c398c 226 void WANDongleSerialPort::setupIrq(bool en, IrqType irq /*= RxIrq*/)
donatien 9:c9e9817c398c 227 {
donatien 9:c9e9817c398c 228 switch(irq)
donatien 9:c9e9817c398c 229 {
donatien 9:c9e9817c398c 230 case RxIrq:
donatien 9:c9e9817c398c 231 rx_mtx.lock();
donatien 9:c9e9817c398c 232 cb_rx_en = en;
donatien 9:c9e9817c398c 233 if(en && cb_rx_pending)
donatien 9:c9e9817c398c 234 {
donatien 9:c9e9817c398c 235 cb_rx_pending = false;
donatien 9:c9e9817c398c 236 rx_mtx.unlock();
donatien 9:c9e9817c398c 237 listener->readable(); //Process the interrupt that was raised
donatien 9:c9e9817c398c 238 }
donatien 9:c9e9817c398c 239 else
donatien 9:c9e9817c398c 240 {
donatien 9:c9e9817c398c 241 rx_mtx.unlock();
donatien 9:c9e9817c398c 242 }
donatien 9:c9e9817c398c 243 break;
donatien 9:c9e9817c398c 244 case TxIrq:
donatien 9:c9e9817c398c 245 tx_mtx.lock();
donatien 9:c9e9817c398c 246 cb_tx_en = en;
donatien 9:c9e9817c398c 247 if(en && cb_tx_pending)
donatien 9:c9e9817c398c 248 {
donatien 9:c9e9817c398c 249 cb_tx_pending = false;
donatien 9:c9e9817c398c 250 tx_mtx.unlock();
donatien 9:c9e9817c398c 251 listener->writeable(); //Process the interrupt that was raised
donatien 9:c9e9817c398c 252 }
donatien 9:c9e9817c398c 253 else
donatien 9:c9e9817c398c 254 {
donatien 9:c9e9817c398c 255 tx_mtx.unlock();
donatien 9:c9e9817c398c 256 }
donatien 9:c9e9817c398c 257 break;
donatien 9:c9e9817c398c 258 }
donatien 9:c9e9817c398c 259 }
donatien 9:c9e9817c398c 260
donatien 9:c9e9817c398c 261
donatien 9:c9e9817c398c 262 void WANDongleSerialPort::connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp )
donatien 9:c9e9817c398c 263 {
donatien 9:c9e9817c398c 264 dev = pDev;
donatien 9:c9e9817c398c 265 bulk_in = pInEp;
donatien 9:c9e9817c398c 266 bulk_out = pOutEp;
donatien 9:c9e9817c398c 267 max_out_size = bulk_out->getSize();
donatien 9:c9e9817c398c 268 if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
donatien 9:c9e9817c398c 269 {
donatien 9:c9e9817c398c 270 max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
donatien 9:c9e9817c398c 271 }
donatien 9:c9e9817c398c 272 bulk_in->attach(this, &WANDongleSerialPort::rxHandler);
donatien 9:c9e9817c398c 273 bulk_out->attach(this, &WANDongleSerialPort::txHandler);
donatien 9:c9e9817c398c 274 readPacket(); //Start receiving data
donatien 9:c9e9817c398c 275 }
donatien 9:c9e9817c398c 276
donatien 9:c9e9817c398c 277 void WANDongleSerialPort::disconnect( )
donatien 9:c9e9817c398c 278 {
donatien 9:c9e9817c398c 279 reset();
donatien 9:c9e9817c398c 280 }
donatien 9:c9e9817c398c 281
donatien 9:c9e9817c398c 282 //Private methods
donatien 9:c9e9817c398c 283
donatien 9:c9e9817c398c 284
donatien 9:c9e9817c398c 285 void WANDongleSerialPort::rxHandler()
donatien 9:c9e9817c398c 286 {
donatien 9:c9e9817c398c 287 if (((USBEndpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
donatien 9:c9e9817c398c 288 {
donatien 9:c9e9817c398c 289 buf_in_read_pos = 0;
donatien 9:c9e9817c398c 290 buf_in_len = ((USBEndpoint *) bulk_in)->getLengthTransferred(); //Update length
donatien 9:c9e9817c398c 291 //lock_rx.unlock();
donatien 9:c9e9817c398c 292 rx_mtx.lock();
donatien 9:c9e9817c398c 293 lock_rx = false; //Transmission complete
donatien 9:c9e9817c398c 294 if(cb_rx_en)
donatien 9:c9e9817c398c 295 {
donatien 9:c9e9817c398c 296 rx_mtx.unlock();
donatien 9:c9e9817c398c 297 listener->readable(); //Call handler from the IRQ context
donatien 9:c9e9817c398c 298 //readPacket() should be called by the handler subsequently once the buffer has been emptied
donatien 9:c9e9817c398c 299 }
donatien 9:c9e9817c398c 300 else
donatien 9:c9e9817c398c 301 {
donatien 9:c9e9817c398c 302 cb_rx_pending = true; //Queue the callback
donatien 9:c9e9817c398c 303 rx_mtx.unlock();
donatien 9:c9e9817c398c 304 }
donatien 9:c9e9817c398c 305
donatien 9:c9e9817c398c 306 }
donatien 9:c9e9817c398c 307 else //Error, try reading again
donatien 9:c9e9817c398c 308 {
donatien 9:c9e9817c398c 309 //lock_rx.unlock();
donatien 10:08bce4cd973a 310 DBG("Trying again");
donatien 9:c9e9817c398c 311 readPacket();
donatien 9:c9e9817c398c 312 }
donatien 9:c9e9817c398c 313 }
donatien 9:c9e9817c398c 314
donatien 9:c9e9817c398c 315 void WANDongleSerialPort::txHandler()
donatien 9:c9e9817c398c 316 {
donatien 9:c9e9817c398c 317 if (((USBEndpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success
donatien 9:c9e9817c398c 318 {
donatien 9:c9e9817c398c 319 tx_mtx.lock();
donatien 9:c9e9817c398c 320 buf_out_len = 0; //Reset length
donatien 9:c9e9817c398c 321 lock_tx = false; //Transmission complete
donatien 9:c9e9817c398c 322 //lock_tx.unlock();
donatien 9:c9e9817c398c 323 if(cb_tx_en)
donatien 9:c9e9817c398c 324 {
donatien 9:c9e9817c398c 325 tx_mtx.unlock();
donatien 9:c9e9817c398c 326 listener->writeable(); //Call handler from the IRQ context
donatien 9:c9e9817c398c 327 //writePacket() should be called by the handler subsequently once the buffer has been filled
donatien 9:c9e9817c398c 328 }
donatien 9:c9e9817c398c 329 else
donatien 9:c9e9817c398c 330 {
donatien 9:c9e9817c398c 331 cb_tx_pending = true; //Queue the callback
donatien 9:c9e9817c398c 332 tx_mtx.unlock();
donatien 9:c9e9817c398c 333 }
donatien 9:c9e9817c398c 334 }
donatien 9:c9e9817c398c 335 else //Error, try reading again
donatien 9:c9e9817c398c 336 {
donatien 9:c9e9817c398c 337 //lock_tx.unlock();
donatien 9:c9e9817c398c 338 writePacket();
donatien 9:c9e9817c398c 339 }
donatien 9:c9e9817c398c 340 }