USB Host WAN Dongle library

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Committer:
donatien
Date:
Tue Jun 26 13:43:54 2012 +0000
Revision:
2:a8b2d0cd9bbd
Child:
3:4394986752db
Test with multiple interfaces

Who changed what in which revision?

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