X-TOUCH to djay bridge

Dependencies:   mbed mbed-rtos FATFileSystem

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 #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 */