USB Host WAN Dongle library

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WANDongleSerialPort.cpp Source File

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 #define __DEBUG__ 0
00020 #ifndef __MODULE__
00021 #define __MODULE__ "WANDongleSerialPort.cpp"
00022 #endif
00023 
00024 #include "core/dbg.h"
00025 #include <cstdint>
00026 #include "rtos.h"
00027 
00028 #include "WANDongleSerialPort.h"
00029 
00030 WANDongleSerialPort::WANDongleSerialPort() : cb_tx_en(false), cb_rx_en(false), listener(NULL)
00031 {
00032   reset();
00033 }
00034 
00035 void WANDongleSerialPort::init(USBHost* pHost)
00036 {
00037   host = pHost;
00038 }
00039 
00040 void WANDongleSerialPort::reset()
00041 {
00042   tx_mtx.lock();
00043   rx_mtx.lock();
00044 
00045   bulk_in = NULL;
00046   bulk_out = NULL;
00047 
00048   buf_out_len = 0;
00049   max_out_size = 0;
00050   lock_tx = false;
00051   cb_tx_pending = false;
00052 
00053   buf_in_len = 0;
00054   buf_in_read_pos = 0;
00055   lock_rx = false;
00056   cb_rx_pending = false;
00057   
00058   tx_mtx.unlock();
00059   rx_mtx.unlock();
00060 }
00061 
00062 int WANDongleSerialPort::readPacket()
00063 {
00064   DBG("Read packet on %p", this);
00065   rx_mtx.lock();
00066   if(lock_rx)
00067   {
00068     ERR("Fail");
00069     rx_mtx.unlock();
00070     return -1;
00071   }
00072   
00073   if( bulk_in == NULL )
00074   {
00075     WARN("Port is disconnected");
00076     rx_mtx.unlock();
00077     return -1;
00078   }
00079 
00080   lock_rx = true; //Receiving
00081   rx_mtx.unlock();
00082 //  DBG("readPacket");
00083   //lock_rx.lock();
00084   host->lock();
00085   USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer
00086   if(res != USB_TYPE_PROCESSING)
00087   {
00088     host->unlock();
00089     //lock_rx.unlock();
00090     ERR("host->bulkRead() returned %d", res);
00091     Thread::wait(100);
00092     return -1;
00093   }
00094   host->unlock();
00095   return 0;
00096 }
00097 
00098 int WANDongleSerialPort::writePacket()
00099 {
00100   tx_mtx.lock();
00101   if(lock_tx)
00102   {
00103     ERR("Fail");
00104     tx_mtx.unlock();
00105     return -1;
00106   }
00107   
00108   if( bulk_out == NULL )
00109   {
00110     WARN("Port is disconnected");
00111     tx_mtx.unlock();
00112     return -1;
00113   }
00114 
00115   lock_tx = true; //Transmitting
00116   tx_mtx.unlock();
00117 //  DBG("writePacket");
00118 
00119   //lock_tx.lock();
00120   host->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     host->unlock();
00125     //lock_tx.unlock();
00126     ERR("host->bulkWrite() returned %d", res);
00127     Thread::wait(100);
00128     return -1;
00129   }
00130   host->unlock();
00131   return 0;
00132 }
00133 
00134 int WANDongleSerialPort::putc(int c)
00135 {
00136   tx_mtx.lock();
00137   if(!lock_tx)
00138   {
00139     if(buf_out_len < max_out_size)
00140     {
00141       buf_out[buf_out_len] = (uint8_t)c;
00142       buf_out_len++;
00143     }
00144   }
00145   else
00146   {
00147     ERR("CAN'T WRITE!");
00148   }
00149   tx_mtx.unlock();
00150   return c;
00151 }
00152 
00153 int WANDongleSerialPort::getc()
00154 {
00155   rx_mtx.lock();
00156   int c = 0;
00157   if(!lock_rx)
00158   {
00159     if(buf_in_read_pos < buf_in_len)
00160     {
00161       c = (int)buf_in[buf_in_read_pos];
00162       buf_in_read_pos++;
00163     }
00164   }
00165   else
00166   {
00167     ERR("CAN'T READ!");
00168   }
00169   rx_mtx.unlock();
00170   return c;
00171 }
00172 
00173 int WANDongleSerialPort::readable()
00174 {
00175   rx_mtx.lock();
00176   if (lock_rx)
00177   {
00178     rx_mtx.unlock();
00179     return 0;
00180   }
00181 
00182  /* if( !lock_rx.trylock() )
00183   {
00184     return 0;
00185   }*/
00186   int res = buf_in_len - buf_in_read_pos;
00187   //lock_rx.unlock();
00188   rx_mtx.unlock();
00189   return res;
00190 }
00191 
00192 int WANDongleSerialPort::writeable()
00193 {
00194   tx_mtx.lock();
00195   if (lock_tx)
00196   {
00197     tx_mtx.unlock();
00198     return 0;
00199   }
00200 
00201   /*if( !lock_tx.trylock() )
00202   {
00203     return 0;
00204   }*/
00205   int res = max_out_size - buf_out_len;
00206   tx_mtx.unlock();
00207  //lock_tx.unlock();
00208   return res;
00209 }
00210 
00211 void WANDongleSerialPort::attach(IUSBHostSerialListener* pListener)
00212 {
00213   if(pListener == NULL)
00214   {
00215     setupIrq(false, RxIrq);
00216     setupIrq(false, TxIrq);
00217   }
00218   listener = pListener;
00219   if(pListener != NULL)
00220   {
00221     setupIrq(true, RxIrq);
00222     setupIrq(true, TxIrq);
00223   }
00224 }
00225 
00226 void WANDongleSerialPort::setupIrq(bool en, IrqType irq /*= RxIrq*/)
00227 {
00228   switch(irq)
00229   {
00230   case RxIrq:
00231     rx_mtx.lock();
00232     cb_rx_en = en;
00233     if(en && cb_rx_pending)
00234     {
00235       cb_rx_pending = false;
00236       rx_mtx.unlock();
00237       listener->readable(); //Process the interrupt that was raised
00238     }
00239     else
00240     {
00241       rx_mtx.unlock();
00242     }
00243     break;
00244   case TxIrq:
00245     tx_mtx.lock();
00246     cb_tx_en = en;
00247     if(en && cb_tx_pending)
00248     {
00249       cb_tx_pending = false;
00250       tx_mtx.unlock();
00251       listener->writeable(); //Process the interrupt that was raised
00252     }
00253     else
00254     {
00255       tx_mtx.unlock();
00256     }
00257     break;
00258   }
00259 }
00260 
00261 
00262 void WANDongleSerialPort::connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp )
00263 {
00264   dev = pDev;
00265   bulk_in = pInEp;
00266   bulk_out = pOutEp;
00267   max_out_size = bulk_out->getSize();
00268   if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
00269   {
00270     max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
00271   }
00272   bulk_in->attach(this, &WANDongleSerialPort::rxHandler);
00273   bulk_out->attach(this, &WANDongleSerialPort::txHandler);
00274   readPacket(); //Start receiving data
00275 }
00276 
00277 void WANDongleSerialPort::disconnect( )
00278 {
00279     reset();
00280 }
00281 
00282 //Private methods
00283 
00284 
00285 void WANDongleSerialPort::rxHandler()
00286 {
00287   if (((USBEndpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
00288   {
00289     buf_in_read_pos = 0;
00290     buf_in_len = ((USBEndpoint *) bulk_in)->getLengthTransferred(); //Update length
00291     //lock_rx.unlock();
00292     rx_mtx.lock();
00293     lock_rx = false; //Transmission complete
00294     if(cb_rx_en)
00295     {
00296       rx_mtx.unlock();
00297       listener->readable(); //Call handler from the IRQ context
00298       //readPacket() should be called by the handler subsequently once the buffer has been emptied
00299     }
00300     else
00301     {
00302       cb_rx_pending = true; //Queue the callback
00303       rx_mtx.unlock();
00304     }
00305 
00306   }
00307   else //Error, try reading again
00308   {
00309     //lock_rx.unlock();
00310     DBG("Trying again");
00311     readPacket();
00312   }
00313 }
00314 
00315 void WANDongleSerialPort::txHandler()
00316 {
00317   if (((USBEndpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success
00318   {
00319     tx_mtx.lock();
00320     buf_out_len = 0; //Reset length
00321     lock_tx = false; //Transmission complete
00322     //lock_tx.unlock();
00323     if(cb_tx_en)
00324     {
00325       tx_mtx.unlock();
00326       listener->writeable(); //Call handler from the IRQ context
00327       //writePacket() should be called by the handler subsequently once the buffer has been filled
00328     }
00329     else
00330     {
00331       cb_tx_pending = true; //Queue the callback
00332       tx_mtx.unlock();
00333     }
00334   }
00335   else //Error, try reading again
00336   {
00337     //lock_tx.unlock();
00338     writePacket();
00339   }
00340 }