USB Host WAN Dongle library

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Committer:
donatien
Date:
Wed Sep 12 07:48:31 2012 +0000
Revision:
12:a712bad7a979
Parent:
9:c9e9817c398c
Child:
13:c154e7f2e42f
#include "dbg.h" -> #include "core/dbg.h"

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donatien 9:c9e9817c398c 1 /* Copyright (c) 2010-2011 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
donatien 9:c9e9817c398c 19 #define __DEBUG__ 4 //Maximum verbosity
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 9:c9e9817c398c 42 bulk_in = NULL;
donatien 9:c9e9817c398c 43 bulk_out = NULL;
donatien 9:c9e9817c398c 44
donatien 9:c9e9817c398c 45 buf_out_len = 0;
donatien 9:c9e9817c398c 46 max_out_size = 0;
donatien 9:c9e9817c398c 47 lock_tx = false;
donatien 9:c9e9817c398c 48 cb_tx_pending = false;
donatien 9:c9e9817c398c 49
donatien 9:c9e9817c398c 50 buf_in_len = 0;
donatien 9:c9e9817c398c 51 buf_in_read_pos = 0;
donatien 9:c9e9817c398c 52 lock_rx = false;
donatien 9:c9e9817c398c 53 cb_rx_pending = false;
donatien 9:c9e9817c398c 54 }
donatien 9:c9e9817c398c 55
donatien 9:c9e9817c398c 56 int WANDongleSerialPort::readPacket()
donatien 9:c9e9817c398c 57 {
donatien 9:c9e9817c398c 58 rx_mtx.lock();
donatien 9:c9e9817c398c 59 if(lock_rx)
donatien 9:c9e9817c398c 60 {
donatien 9:c9e9817c398c 61 ERR("Fail");
donatien 9:c9e9817c398c 62 rx_mtx.unlock();
donatien 9:c9e9817c398c 63 return -1;
donatien 9:c9e9817c398c 64 }
donatien 9:c9e9817c398c 65
donatien 9:c9e9817c398c 66 lock_rx = true; //Receiving
donatien 9:c9e9817c398c 67 rx_mtx.unlock();
donatien 9:c9e9817c398c 68 // DBG("readPacket");
donatien 9:c9e9817c398c 69 //lock_rx.lock();
donatien 9:c9e9817c398c 70 host->lock();
donatien 9:c9e9817c398c 71 USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer
donatien 9:c9e9817c398c 72 if(res != USB_TYPE_PROCESSING)
donatien 9:c9e9817c398c 73 {
donatien 9:c9e9817c398c 74 host->unlock();
donatien 9:c9e9817c398c 75 //lock_rx.unlock();
donatien 9:c9e9817c398c 76 ERR("host->bulkRead() returned %d", res);
donatien 9:c9e9817c398c 77 Thread::wait(100);
donatien 9:c9e9817c398c 78 return -1;
donatien 9:c9e9817c398c 79 }
donatien 9:c9e9817c398c 80 host->unlock();
donatien 9:c9e9817c398c 81 return 0;
donatien 9:c9e9817c398c 82 }
donatien 9:c9e9817c398c 83
donatien 9:c9e9817c398c 84 int WANDongleSerialPort::writePacket()
donatien 9:c9e9817c398c 85 {
donatien 9:c9e9817c398c 86 tx_mtx.lock();
donatien 9:c9e9817c398c 87 if(lock_tx)
donatien 9:c9e9817c398c 88 {
donatien 9:c9e9817c398c 89 ERR("Fail");
donatien 9:c9e9817c398c 90 tx_mtx.unlock();
donatien 9:c9e9817c398c 91 return -1;
donatien 9:c9e9817c398c 92 }
donatien 9:c9e9817c398c 93
donatien 9:c9e9817c398c 94 lock_tx = true; //Transmitting
donatien 9:c9e9817c398c 95 tx_mtx.unlock();
donatien 9:c9e9817c398c 96 // DBG("writePacket");
donatien 9:c9e9817c398c 97
donatien 9:c9e9817c398c 98 //lock_tx.lock();
donatien 9:c9e9817c398c 99 host->lock();
donatien 9:c9e9817c398c 100 USB_TYPE res = host->bulkWrite(dev, (USBEndpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
donatien 9:c9e9817c398c 101 if(res != USB_TYPE_PROCESSING)
donatien 9:c9e9817c398c 102 {
donatien 9:c9e9817c398c 103 host->unlock();
donatien 9:c9e9817c398c 104 //lock_tx.unlock();
donatien 9:c9e9817c398c 105 ERR("host->bulkWrite() returned %d", res);
donatien 9:c9e9817c398c 106 Thread::wait(100);
donatien 9:c9e9817c398c 107 return -1;
donatien 9:c9e9817c398c 108 }
donatien 9:c9e9817c398c 109 host->unlock();
donatien 9:c9e9817c398c 110 return 0;
donatien 9:c9e9817c398c 111 }
donatien 9:c9e9817c398c 112
donatien 9:c9e9817c398c 113 int WANDongleSerialPort::putc(int c)
donatien 9:c9e9817c398c 114 {
donatien 9:c9e9817c398c 115 tx_mtx.lock();
donatien 9:c9e9817c398c 116 if(!lock_tx)
donatien 9:c9e9817c398c 117 {
donatien 9:c9e9817c398c 118 if(buf_out_len < max_out_size)
donatien 9:c9e9817c398c 119 {
donatien 9:c9e9817c398c 120 buf_out[buf_out_len] = (uint8_t)c;
donatien 9:c9e9817c398c 121 buf_out_len++;
donatien 9:c9e9817c398c 122 }
donatien 9:c9e9817c398c 123 }
donatien 9:c9e9817c398c 124 else
donatien 9:c9e9817c398c 125 {
donatien 9:c9e9817c398c 126 ERR("CAN'T WRITE!");
donatien 9:c9e9817c398c 127 }
donatien 9:c9e9817c398c 128 tx_mtx.unlock();
donatien 9:c9e9817c398c 129 return c;
donatien 9:c9e9817c398c 130 }
donatien 9:c9e9817c398c 131
donatien 9:c9e9817c398c 132 int WANDongleSerialPort::getc()
donatien 9:c9e9817c398c 133 {
donatien 9:c9e9817c398c 134 rx_mtx.lock();
donatien 9:c9e9817c398c 135 int c = 0;
donatien 9:c9e9817c398c 136 if(!lock_rx)
donatien 9:c9e9817c398c 137 {
donatien 9:c9e9817c398c 138 if(buf_in_read_pos < buf_in_len)
donatien 9:c9e9817c398c 139 {
donatien 9:c9e9817c398c 140 c = (int)buf_in[buf_in_read_pos];
donatien 9:c9e9817c398c 141 buf_in_read_pos++;
donatien 9:c9e9817c398c 142 }
donatien 9:c9e9817c398c 143 }
donatien 9:c9e9817c398c 144 else
donatien 9:c9e9817c398c 145 {
donatien 9:c9e9817c398c 146 ERR("CAN'T READ!");
donatien 9:c9e9817c398c 147 }
donatien 9:c9e9817c398c 148 rx_mtx.unlock();
donatien 9:c9e9817c398c 149 return c;
donatien 9:c9e9817c398c 150 }
donatien 9:c9e9817c398c 151
donatien 9:c9e9817c398c 152 int WANDongleSerialPort::readable()
donatien 9:c9e9817c398c 153 {
donatien 9:c9e9817c398c 154 rx_mtx.lock();
donatien 9:c9e9817c398c 155 if (lock_rx)
donatien 9:c9e9817c398c 156 {
donatien 9:c9e9817c398c 157 rx_mtx.unlock();
donatien 9:c9e9817c398c 158 return 0;
donatien 9:c9e9817c398c 159 }
donatien 9:c9e9817c398c 160
donatien 9:c9e9817c398c 161 /* if( !lock_rx.trylock() )
donatien 9:c9e9817c398c 162 {
donatien 9:c9e9817c398c 163 return 0;
donatien 9:c9e9817c398c 164 }*/
donatien 9:c9e9817c398c 165 int res = buf_in_len - buf_in_read_pos;
donatien 9:c9e9817c398c 166 //lock_rx.unlock();
donatien 9:c9e9817c398c 167 rx_mtx.unlock();
donatien 9:c9e9817c398c 168 return res;
donatien 9:c9e9817c398c 169 }
donatien 9:c9e9817c398c 170
donatien 9:c9e9817c398c 171 int WANDongleSerialPort::writeable()
donatien 9:c9e9817c398c 172 {
donatien 9:c9e9817c398c 173 tx_mtx.lock();
donatien 9:c9e9817c398c 174 if (lock_tx)
donatien 9:c9e9817c398c 175 {
donatien 9:c9e9817c398c 176 tx_mtx.unlock();
donatien 9:c9e9817c398c 177 return 0;
donatien 9:c9e9817c398c 178 }
donatien 9:c9e9817c398c 179
donatien 9:c9e9817c398c 180 /*if( !lock_tx.trylock() )
donatien 9:c9e9817c398c 181 {
donatien 9:c9e9817c398c 182 return 0;
donatien 9:c9e9817c398c 183 }*/
donatien 9:c9e9817c398c 184 int res = max_out_size - buf_out_len;
donatien 9:c9e9817c398c 185 tx_mtx.unlock();
donatien 9:c9e9817c398c 186 //lock_tx.unlock();
donatien 9:c9e9817c398c 187 return res;
donatien 9:c9e9817c398c 188 }
donatien 9:c9e9817c398c 189
donatien 9:c9e9817c398c 190 void WANDongleSerialPort::attach(IUSBHostSerialListener* pListener)
donatien 9:c9e9817c398c 191 {
donatien 9:c9e9817c398c 192 if(pListener == NULL)
donatien 9:c9e9817c398c 193 {
donatien 9:c9e9817c398c 194 setupIrq(false, RxIrq);
donatien 9:c9e9817c398c 195 setupIrq(false, TxIrq);
donatien 9:c9e9817c398c 196 }
donatien 9:c9e9817c398c 197 listener = pListener;
donatien 9:c9e9817c398c 198 if(pListener != NULL)
donatien 9:c9e9817c398c 199 {
donatien 9:c9e9817c398c 200 setupIrq(true, RxIrq);
donatien 9:c9e9817c398c 201 setupIrq(true, TxIrq);
donatien 9:c9e9817c398c 202 }
donatien 9:c9e9817c398c 203 }
donatien 9:c9e9817c398c 204
donatien 9:c9e9817c398c 205 void WANDongleSerialPort::setupIrq(bool en, IrqType irq /*= RxIrq*/)
donatien 9:c9e9817c398c 206 {
donatien 9:c9e9817c398c 207 switch(irq)
donatien 9:c9e9817c398c 208 {
donatien 9:c9e9817c398c 209 case RxIrq:
donatien 9:c9e9817c398c 210 rx_mtx.lock();
donatien 9:c9e9817c398c 211 cb_rx_en = en;
donatien 9:c9e9817c398c 212 if(en && cb_rx_pending)
donatien 9:c9e9817c398c 213 {
donatien 9:c9e9817c398c 214 cb_rx_pending = false;
donatien 9:c9e9817c398c 215 rx_mtx.unlock();
donatien 9:c9e9817c398c 216 listener->readable(); //Process the interrupt that was raised
donatien 9:c9e9817c398c 217 }
donatien 9:c9e9817c398c 218 else
donatien 9:c9e9817c398c 219 {
donatien 9:c9e9817c398c 220 rx_mtx.unlock();
donatien 9:c9e9817c398c 221 }
donatien 9:c9e9817c398c 222 break;
donatien 9:c9e9817c398c 223 case TxIrq:
donatien 9:c9e9817c398c 224 tx_mtx.lock();
donatien 9:c9e9817c398c 225 cb_tx_en = en;
donatien 9:c9e9817c398c 226 if(en && cb_tx_pending)
donatien 9:c9e9817c398c 227 {
donatien 9:c9e9817c398c 228 cb_tx_pending = false;
donatien 9:c9e9817c398c 229 tx_mtx.unlock();
donatien 9:c9e9817c398c 230 listener->writeable(); //Process the interrupt that was raised
donatien 9:c9e9817c398c 231 }
donatien 9:c9e9817c398c 232 else
donatien 9:c9e9817c398c 233 {
donatien 9:c9e9817c398c 234 tx_mtx.unlock();
donatien 9:c9e9817c398c 235 }
donatien 9:c9e9817c398c 236 break;
donatien 9:c9e9817c398c 237 }
donatien 9:c9e9817c398c 238 }
donatien 9:c9e9817c398c 239
donatien 9:c9e9817c398c 240
donatien 9:c9e9817c398c 241 void WANDongleSerialPort::connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp )
donatien 9:c9e9817c398c 242 {
donatien 9:c9e9817c398c 243 dev = pDev;
donatien 9:c9e9817c398c 244 bulk_in = pInEp;
donatien 9:c9e9817c398c 245 bulk_out = pOutEp;
donatien 9:c9e9817c398c 246 max_out_size = bulk_out->getSize();
donatien 9:c9e9817c398c 247 if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
donatien 9:c9e9817c398c 248 {
donatien 9:c9e9817c398c 249 max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
donatien 9:c9e9817c398c 250 }
donatien 9:c9e9817c398c 251 bulk_in->attach(this, &WANDongleSerialPort::rxHandler);
donatien 9:c9e9817c398c 252 bulk_out->attach(this, &WANDongleSerialPort::txHandler);
donatien 9:c9e9817c398c 253 readPacket(); //Start receiving data
donatien 9:c9e9817c398c 254 }
donatien 9:c9e9817c398c 255
donatien 9:c9e9817c398c 256 void WANDongleSerialPort::disconnect( )
donatien 9:c9e9817c398c 257 {
donatien 9:c9e9817c398c 258 reset();
donatien 9:c9e9817c398c 259 }
donatien 9:c9e9817c398c 260
donatien 9:c9e9817c398c 261 //Private methods
donatien 9:c9e9817c398c 262
donatien 9:c9e9817c398c 263
donatien 9:c9e9817c398c 264 void WANDongleSerialPort::rxHandler()
donatien 9:c9e9817c398c 265 {
donatien 9:c9e9817c398c 266 if (((USBEndpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
donatien 9:c9e9817c398c 267 {
donatien 9:c9e9817c398c 268 buf_in_read_pos = 0;
donatien 9:c9e9817c398c 269 buf_in_len = ((USBEndpoint *) bulk_in)->getLengthTransferred(); //Update length
donatien 9:c9e9817c398c 270 //lock_rx.unlock();
donatien 9:c9e9817c398c 271 rx_mtx.lock();
donatien 9:c9e9817c398c 272 lock_rx = false; //Transmission complete
donatien 9:c9e9817c398c 273 if(cb_rx_en)
donatien 9:c9e9817c398c 274 {
donatien 9:c9e9817c398c 275 rx_mtx.unlock();
donatien 9:c9e9817c398c 276 listener->readable(); //Call handler from the IRQ context
donatien 9:c9e9817c398c 277 //readPacket() should be called by the handler subsequently once the buffer has been emptied
donatien 9:c9e9817c398c 278 }
donatien 9:c9e9817c398c 279 else
donatien 9:c9e9817c398c 280 {
donatien 9:c9e9817c398c 281 cb_rx_pending = true; //Queue the callback
donatien 9:c9e9817c398c 282 rx_mtx.unlock();
donatien 9:c9e9817c398c 283 }
donatien 9:c9e9817c398c 284
donatien 9:c9e9817c398c 285 }
donatien 9:c9e9817c398c 286 else //Error, try reading again
donatien 9:c9e9817c398c 287 {
donatien 9:c9e9817c398c 288 //lock_rx.unlock();
donatien 9:c9e9817c398c 289 readPacket();
donatien 9:c9e9817c398c 290 }
donatien 9:c9e9817c398c 291 }
donatien 9:c9e9817c398c 292
donatien 9:c9e9817c398c 293 void WANDongleSerialPort::txHandler()
donatien 9:c9e9817c398c 294 {
donatien 9:c9e9817c398c 295 if (((USBEndpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success
donatien 9:c9e9817c398c 296 {
donatien 9:c9e9817c398c 297 tx_mtx.lock();
donatien 9:c9e9817c398c 298 buf_out_len = 0; //Reset length
donatien 9:c9e9817c398c 299 lock_tx = false; //Transmission complete
donatien 9:c9e9817c398c 300 //lock_tx.unlock();
donatien 9:c9e9817c398c 301 if(cb_tx_en)
donatien 9:c9e9817c398c 302 {
donatien 9:c9e9817c398c 303 tx_mtx.unlock();
donatien 9:c9e9817c398c 304 listener->writeable(); //Call handler from the IRQ context
donatien 9:c9e9817c398c 305 //writePacket() should be called by the handler subsequently once the buffer has been filled
donatien 9:c9e9817c398c 306 }
donatien 9:c9e9817c398c 307 else
donatien 9:c9e9817c398c 308 {
donatien 9:c9e9817c398c 309 cb_tx_pending = true; //Queue the callback
donatien 9:c9e9817c398c 310 tx_mtx.unlock();
donatien 9:c9e9817c398c 311 }
donatien 9:c9e9817c398c 312 }
donatien 9:c9e9817c398c 313 else //Error, try reading again
donatien 9:c9e9817c398c 314 {
donatien 9:c9e9817c398c 315 //lock_tx.unlock();
donatien 9:c9e9817c398c 316 writePacket();
donatien 9:c9e9817c398c 317 }
donatien 9:c9e9817c398c 318 }