| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- /* Copyright (c) 2010-2012 mbed.org, MIT License
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
- * and associated documentation files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or
- * substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
- * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- #include "USBHostConf.h"
- #ifdef USBHOST_3GMODULE
- #define __DEBUG__ 0
- #ifndef __MODULE__
- #define __MODULE__ "WANDongleSerialPort.cpp"
- #endif
- #include "dbg.h"
- #include <stdint.h>
- #include "rtos.h"
- #include "WANDongleSerialPort.h"
- WANDongleSerialPort::WANDongleSerialPort() : cb_tx_en(false), cb_rx_en(false), listener(NULL)
- {
- reset();
- }
- void WANDongleSerialPort::init(USBHost* pHost)
- {
- host = pHost;
- }
- void WANDongleSerialPort::reset()
- {
- tx_mtx.lock();
- rx_mtx.lock();
- bulk_in = NULL;
- bulk_out = NULL;
- buf_out_len = 0;
- max_out_size = 0;
- lock_tx = false;
- cb_tx_pending = false;
- buf_in_len = 0;
- buf_in_read_pos = 0;
- lock_rx = false;
- cb_rx_pending = false;
- tx_mtx.unlock();
- rx_mtx.unlock();
- }
- int WANDongleSerialPort::readPacket()
- {
- USB_DBG("Read packet on %p", this);
- rx_mtx.lock();
- if(lock_rx)
- {
- USB_ERR("Fail");
- rx_mtx.unlock();
- return -1;
- }
- if( bulk_in == NULL )
- {
- USB_WARN("Port is disconnected");
- rx_mtx.unlock();
- return -1;
- }
- lock_rx = true; //Receiving
- rx_mtx.unlock();
- // USB_DBG("readPacket");
- //lock_rx.lock();
- USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer
- if(res != USB_TYPE_PROCESSING)
- {
- //lock_rx.unlock();
- USB_ERR("host->bulkRead() returned %d", res);
- Thread::wait(100);
- return -1;
- }
- return 0;
- }
- int WANDongleSerialPort::writePacket()
- {
- tx_mtx.lock();
- if(lock_tx)
- {
- USB_ERR("Fail");
- tx_mtx.unlock();
- return -1;
- }
- if( bulk_out == NULL )
- {
- USB_WARN("Port is disconnected");
- tx_mtx.unlock();
- return -1;
- }
- lock_tx = true; //Transmitting
- tx_mtx.unlock();
- // USB_DBG("writePacket");
- //lock_tx.lock();
- USB_TYPE res = host->bulkWrite(dev, (USBEndpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
- if(res != USB_TYPE_PROCESSING)
- {
- //lock_tx.unlock();
- USB_ERR("host->bulkWrite() returned %d", res);
- Thread::wait(100);
- return -1;
- }
- return 0;
- }
- int WANDongleSerialPort::putc(int c)
- {
- tx_mtx.lock();
- if(!lock_tx)
- {
- if(buf_out_len < max_out_size)
- {
- buf_out[buf_out_len] = (uint8_t)c;
- buf_out_len++;
- }
- }
- else
- {
- USB_ERR("CAN'T WRITE!");
- }
- tx_mtx.unlock();
- return c;
- }
- int WANDongleSerialPort::getc()
- {
- rx_mtx.lock();
- int c = 0;
- if(!lock_rx)
- {
- if(buf_in_read_pos < buf_in_len)
- {
- c = (int)buf_in[buf_in_read_pos];
- buf_in_read_pos++;
- }
- }
- else
- {
- USB_ERR("CAN'T READ!");
- }
- rx_mtx.unlock();
- return c;
- }
- int WANDongleSerialPort::readable()
- {
- rx_mtx.lock();
- if (lock_rx)
- {
- rx_mtx.unlock();
- return 0;
- }
- /* if( !lock_rx.trylock() )
- {
- return 0;
- }*/
- int res = buf_in_len - buf_in_read_pos;
- //lock_rx.unlock();
- rx_mtx.unlock();
- return res;
- }
- int WANDongleSerialPort::writeable()
- {
- tx_mtx.lock();
- if (lock_tx)
- {
- tx_mtx.unlock();
- return 0;
- }
- /*if( !lock_tx.trylock() )
- {
- return 0;
- }*/
- int res = max_out_size - buf_out_len;
- tx_mtx.unlock();
- //lock_tx.unlock();
- return res;
- }
- void WANDongleSerialPort::attach(IUSBHostSerialListener* pListener)
- {
- if(pListener == NULL)
- {
- setupIrq(false, RxIrq);
- setupIrq(false, TxIrq);
- }
- listener = pListener;
- if(pListener != NULL)
- {
- setupIrq(true, RxIrq);
- setupIrq(true, TxIrq);
- }
- }
- void WANDongleSerialPort::setupIrq(bool en, IrqType irq /*= RxIrq*/)
- {
- switch(irq)
- {
- case RxIrq:
- rx_mtx.lock();
- cb_rx_en = en;
- if(en && cb_rx_pending)
- {
- cb_rx_pending = false;
- rx_mtx.unlock();
- listener->readable(); //Process the interrupt that was raised
- }
- else
- {
- rx_mtx.unlock();
- }
- break;
- case TxIrq:
- tx_mtx.lock();
- cb_tx_en = en;
- if(en && cb_tx_pending)
- {
- cb_tx_pending = false;
- tx_mtx.unlock();
- listener->writeable(); //Process the interrupt that was raised
- }
- else
- {
- tx_mtx.unlock();
- }
- break;
- }
- }
- void WANDongleSerialPort::connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp )
- {
- dev = pDev;
- bulk_in = pInEp;
- bulk_out = pOutEp;
- max_out_size = bulk_out->getSize();
- if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
- {
- max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
- }
- bulk_in->attach(this, &WANDongleSerialPort::rxHandler);
- bulk_out->attach(this, &WANDongleSerialPort::txHandler);
- readPacket(); //Start receiving data
- }
- void WANDongleSerialPort::disconnect( )
- {
- reset();
- }
- //Private methods
- void WANDongleSerialPort::rxHandler()
- {
- if (((USBEndpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
- {
- buf_in_read_pos = 0;
- buf_in_len = ((USBEndpoint *) bulk_in)->getLengthTransferred(); //Update length
- //lock_rx.unlock();
- rx_mtx.lock();
- lock_rx = false; //Transmission complete
- if(cb_rx_en)
- {
- rx_mtx.unlock();
- listener->readable(); //Call handler from the IRQ context
- //readPacket() should be called by the handler subsequently once the buffer has been emptied
- }
- else
- {
- cb_rx_pending = true; //Queue the callback
- rx_mtx.unlock();
- }
- }
- else //Error, try reading again
- {
- //lock_rx.unlock();
- USB_DBG("Trying again");
- readPacket();
- }
- }
- void WANDongleSerialPort::txHandler()
- {
- if (((USBEndpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success
- {
- tx_mtx.lock();
- buf_out_len = 0; //Reset length
- lock_tx = false; //Transmission complete
- //lock_tx.unlock();
- if(cb_tx_en)
- {
- tx_mtx.unlock();
- listener->writeable(); //Call handler from the IRQ context
- //writePacket() should be called by the handler subsequently once the buffer has been filled
- }
- else
- {
- cb_tx_pending = true; //Queue the callback
- tx_mtx.unlock();
- }
- }
- else //Error, try reading again
- {
- //lock_tx.unlock();
- writePacket();
- }
- }
- #endif /* USBHOST_3GMODULE */
|