Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: VodafoneUSBModem_bleedingedge2
Fork of USBHostWANDongle_bleedingedge by
Revision 2:a8b2d0cd9bbd, committed 2012-06-26
- Comitter:
- donatien
- Date:
- Tue Jun 26 13:43:54 2012 +0000
- Parent:
- 1:49df46e3295c
- Child:
- 3:4394986752db
- Commit message:
- Test with multiple interfaces
Changed in this revision
--- a/USB3GModule/WANDongle.cpp Fri May 25 09:31:41 2012 +0000
+++ b/USB3GModule/WANDongle.cpp Tue Jun 26 13:43:54 2012 +0000
@@ -26,15 +26,9 @@
#include "rtos.h"
#include "WANDongle.h"
-
-//TODO refactor
+#include "WANDongleInitializer.h"
-//Huawei K3770 (Vodafone)
-uint8_t vodafone_k3770_switch_packet[] = {
- 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0, 0, 0, 0, 0x11, 0x06, 0x20, 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-WANDongle::WANDongle() : cb_tx_en(false), cb_rx_en(false), listener(NULL)
+WANDongle::WANDongle() : cb_tx_en(false), cb_rx_en(false), listener(NULL), m_serialCount(0)
{
host = USBHost::getHostInst();
init();
@@ -59,385 +53,69 @@
host->lock();
- for (int i = 0; i < MAX_DEVICE_NB; i++) {
- if ((dev = host->getDevice(i)) != NULL) {
-
+ for (int i = 0; i < MAX_DEVICE_NB; i++)
+ {
+ if ((dev = host->getDevice(i)) != NULL)
+ {
DBG("Found one device, reset it");
host->resetDevice(dev);
DBG("Enumerate");
host->enumerate(dev);
-
- //Vodafone K3770
- if ((dev->getVid() == 0x12D1) && (dev->getPid() == 0x14D1)) {
+
+ WANDongleInitializer* initializer = getInitializers();
+
+ while(initializer++)
+ {
+ if ((dev->getVid() == initializer->getSerialVid()) && (dev->getPid() == initializer->getSerialPid()))
+ {
+ host->registerDriver(dev, 0, this, &WANDongle::init);
+ m_serialCount = initializer->getSerialPortCount();
+ for(int j = 0; j < m_serialCount; j++)
+ {
+ m_serial[j].connect( initializer->getEp(dev, j, false), initializer->getEp(dev, j, true) );
+ }
+ dev_connected = true;
+ host->unlock();
+ return true;
+ }
+ else if ((dev->getVid() == initializer->getMSDVid()) && (dev->getPid() == initializer->getMSDPid()))
+ {
DBG("Vodafone K3370 dongle detected in MSD mode");
-
- for (int j = 0; j < dev->getNbInterface(); j++) {
-
- if (dev->getInterface(j)->intf_class == MSD_CLASS) {
-
- if ( (bulk_out = dev->getEndpoint(j, BULK_ENDPOINT, OUT)) != NULL ) {
-
- DBG("MSD descriptor found on device %p, intf %d, will now try to switch into serial mode", (void *)dev, j);
-
- host->bulkWrite(dev, (Endpoint *)bulk_out, vodafone_k3770_switch_packet, 31);
-
- DBG("Switch packet sent");
- host->unlock();
-
-
- Thread::wait(500); //Not in a thread
-
- //Not wait for the dongle to reconnect
- while (1) {
-
- if (found) {
- break;
- }
-
- Thread::wait(100);
-
- host->lock();
-
-
- for (int i = 0; i < MAX_DEVICE_NB; i++) {
- if ((dev = host->getDevice(i)) != NULL) {
- host->resetDevice(dev);
- host->enumerate(dev);
-
- DBG("Found one device with vid: %04x pid: %04x", dev->getVid(), dev->getPid());
-
- //Vodafone K3770
- if ((dev->getVid() == 0x12D1) && (dev->getPid() == 0x14C9)) {
- DBG("Switched successfully");
- found = true;
- break;
- }
- }
- }
-
- host->unlock();
-
- }
- host->lock();
-
- if (fetchEndpoints()) {
- DBG("ep: %p, %p\r\n", bulk_in, bulk_out);
- max_out_size = bulk_out->getSize();
- if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
- {
- max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
- }
- host->unlock();
- return true;
- }
- host->unlock();
- }
- }
+ //Try to switch
+ if( initializer->switchMode() )
+ {
+ DBG("Switched OK");
+ host->unlock();
+ return false; //Will be connected on a next iteration
}
- } else if ((dev->getVid() == 0x12D1) && (dev->getPid() == 0x14C9)) {
- if (fetchEndpoints()) {
- DBG("ep: %p, %p\r\n", bulk_in, bulk_out);
- max_out_size = bulk_out->getSize();
- if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
- {
- max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
- }
+ else
+ {
+ ERR("Could not switch mode");
host->unlock();
- return true;
+ return false;
}
- }
- }
- }
+ }
+ } //while()
+ } //if()
+ } //for()
host->unlock();
- bulk_in = NULL;
- bulk_out = NULL;
- dev_connected = false;
return false;
}
-int WANDongle::readPacket()
-{
- rx_mtx.lock();
- if(lock_rx)
- {
- ERR("Fail");
- rx_mtx.unlock();
- return -1;
- }
-
- lock_rx = true; //Receiving
- rx_mtx.unlock();
-// DBG("readPacket");
- //lock_rx.lock();
- host->lock();
- USB_TYPE res = host->bulkRead(dev, (Endpoint *)bulk_in, buf_in, ((Endpoint *)bulk_in)->getSize(), false); //Queue transfer
- if(res != USB_TYPE_PROCESSING)
- {
- host->unlock();
- //lock_rx.unlock();
- ERR("host->bulkRead() returned %d", res);
- Thread::wait(100);
- return -1;
- }
- host->unlock();
- return 0;
-}
-
-int WANDongle::writePacket()
+IUSBHostSerial* WANDongle::getSerial(int index)
{
- tx_mtx.lock();
- if(lock_tx)
- {
- ERR("Fail");
- tx_mtx.unlock();
- return -1;
- }
-
- lock_tx = true; //Transmitting
- tx_mtx.unlock();
-// DBG("writePacket");
-
- //lock_tx.lock();
- host->lock();
- USB_TYPE res = host->bulkWrite(dev, (Endpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
- if(res != USB_TYPE_PROCESSING)
- {
- host->unlock();
- //lock_tx.unlock();
- ERR("host->bulkWrite() returned %d", res);
- Thread::wait(100);
- return -1;
- }
- host->unlock();
- return 0;
-}
-
-int WANDongle::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
- {
- ERR("CAN'T WRITE!");
- }
- tx_mtx.unlock();
- return c;
+ return m_serial[index];
}
-int WANDongle::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
- {
- ERR("CAN'T READ!");
- }
- rx_mtx.unlock();
- return c;
-}
-
-int WANDongle::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 WANDongle::writeable()
+int WANDongle::getSerialCount()
{
- 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 WANDongle::attach(IUSBHostSerialListener* pListener)
-{
- if(pListener == NULL)
- {
- setupIrq(false, RxIrq);
- setupIrq(false, TxIrq);
- }
- listener = pListener;
- if(pListener != NULL)
- {
- setupIrq(true, RxIrq);
- setupIrq(true, TxIrq);
- }
-}
-
-void WANDongle::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;
- }
+ return m_serialCount;
}
//Private methods
-
void WANDongle::init()
{
dev_connected = false;
-
- bulk_in = NULL;
- bulk_out = NULL;
-
- buf_out_len = 0;
- lock_tx = false;
- cb_tx_en = false;
- cb_tx_pending = false;
-
- buf_in_len = 0;
- buf_in_read_pos = 0;
- lock_rx = false;
- cb_rx_en = false;
- cb_rx_pending = false;
-
-}
-
-bool WANDongle::fetchEndpoints()
-{
- bulk_in = dev->getEndpoint(0, BULK_ENDPOINT, IN);
- bulk_out = dev->getEndpoint(0, BULK_ENDPOINT, OUT);
- if ((bulk_in != NULL) && (bulk_out != NULL))
- {
-
- DBG("SERIAL FOUND on device %p, intf %d, bulk_in: %p, bulk_out: %p\r\n",
- (void *)dev, 0, (void *)bulk_in, (void *)bulk_out);
-
- bulk_in->attach(this, &WANDongle::rxHandler);
- bulk_out->attach(this, &WANDongle::txHandler);
- host->lock();
- host->registerDriver(dev, 0, this, &WANDongle::init);
- host->unlock();
- dev_connected = true;
-
- readPacket(); //Start receiving data
-
- return true;
- }
- return false;
}
-void WANDongle::rxHandler()
-{
- if (((Endpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
- {
- buf_in_read_pos = 0;
- buf_in_len = ((Endpoint *) 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();
- readPacket();
- }
-}
-
-void WANDongle::txHandler()
-{
- if (((Endpoint *) 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();
- }
-}
--- a/USB3GModule/WANDongle.h Fri May 25 09:31:41 2012 +0000
+++ b/USB3GModule/WANDongle.h Tue Jun 26 13:43:54 2012 +0000
@@ -28,10 +28,12 @@
#define WANDONGLE_MAX_OUTEP_SIZE 64
#define WANDONGLE_MAX_INEP_SIZE 64
+#define WANDONGLE_MAX_SERIAL_PORTS 2
+
/** A class to use a WAN (3G/LTE) access dongle
*
*/
-class WANDongle : public IUSBHostSerial {
+class WANDongle {
public:
/*
* Constructor
@@ -53,88 +55,19 @@
* * @return true if connection was successful
*/
bool tryConnect();
-
- /*
- * Get a char from the dongle's serial interface
- */
- virtual int getc();
-
- /*
- * Put a char to the dongle's serial interface
- */
- virtual int putc(int c);
- //void test();
-
- /*
- * Read a packet from the dongle's serial interface, to be called after multiple getc() calls
- */
- virtual int readPacket();
-
- /*
- * Write a packet to the dongle's serial interface, to be called after multiple putc() calls
- */
- virtual int writePacket();
-
- /**
- * Check the number of bytes available.
- *
- * @returns the number of bytes available
- */
- virtual int readable();
-
- /**
- * Check the free space in output.
- *
- * @returns the number of bytes available
- */
- virtual int writeable();
-
- /**
- * Attach a handler to call when a packet is received / when a packet has been transmitted.
- *
- * @param pListener instance of the listener deriving from the IUSBHostSerialListener
- */
- virtual void attach(IUSBHostSerialListener* pListener);
-
- /**
- * Enable or disable readable/writeable callbacks
- */
- virtual void setupIrq(bool en, IrqType irq = RxIrq);
-
+ IUSBHostSerial* getSerial(int index);
+ int getSerialCount();
protected:
- Endpoint * bulk_in;
- Endpoint * bulk_out;
USBHost * host;
USBDeviceConnected * dev;
bool dev_connected;
- uint8_t buf_out[WANDONGLE_MAX_OUTEP_SIZE];
- volatile uint32_t buf_out_len;
- uint32_t max_out_size;
- volatile bool lock_tx;
- //Mutex lock_tx;
- volatile bool cb_tx_en;
- volatile bool cb_tx_pending;
- Mutex tx_mtx;
-
- uint8_t buf_in[WANDONGLE_MAX_INEP_SIZE];
- volatile uint32_t buf_in_len;
- volatile uint32_t buf_in_read_pos;
- volatile bool lock_rx;
- //Mutex lock_rx;
- volatile bool cb_rx_en;
- volatile bool cb_rx_pending;
- Mutex rx_mtx;
+ void init();
- IUSBHostSerialListener* listener;
-
- void init();
- void rxHandler();
- void txHandler();
- bool fetchEndpoints();
-
+ WANDongleSerialPort m_serial[WANDONGLE_MAX_SERIAL_PORTS];
+ int m_serialCount;
};
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USB3GModule/WANDongleInitializer.cpp Tue Jun 26 13:43:54 2012 +0000
@@ -0,0 +1,85 @@
+/* Copyright (c) 2010-2011 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.
+*/
+
+#define __DEBUG__ 4 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "WANDongleInitializer.cpp"
+#endif
+
+#include "dbg.h"
+
+#include <cstdint>
+using std::uint16_t;
+
+#include "WANDongleInitializer.h"
+
+WANDongleInitializer::WANDongleInitializer(USBHost* pHost) : m_pHost(pHost)
+{
+
+}
+
+WANDongleInitializer[] WANDongleInitializer::getInitializers()
+{
+ static VodafoneK3770Initializer vodafoneK3770;
+ const static WANDongleInitializer list[] = { &vodafoneK3770, NULL };
+ return list;
+}
+
+//Huawei K3770 (Vodafone)
+const static uint8_t vodafone_k3770_switch_packet[] = {
+ 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0, 0, 0, 0, 0x11, 0x06, 0x20, 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+VodafoneK3770Initializer::VodafoneK3770Initializer(USBHost* pHost) : WANDongleInitializer(pHost)
+{
+
+}
+
+uint16_t VodafoneK3770Initializer::getMSDVid() { return 0x12D1; }
+uint16_t VodafoneK3770Initializer::getMSDPid() { return 0x14D1; }
+
+uint16_t VodafoneK3770Initializer::getSerialVid() { return 0x12D1; }
+uint16_t VodafoneK3770Initializer::getSerialPid() { return 0x14C9; }
+
+bool VodafoneK3770Initializer::switchMode(USBDeviceConnected* pDev)
+{
+ for (int i = 0; i < pDev->getNbInterface(); i++)
+ {
+ if (pDev->getInterface(j)->intf_class == MSD_CLASS)
+ {
+ Endpoint* pEp = pDev->getEndpoint(i, BULK_ENDPOINT, OUT);
+ if ( pEp != NULL )
+ {
+ DBG("MSD descriptor found on device %p, intf %d, will now try to switch into serial mode", (void *)pDev, i);
+ m_pHost->bulkWrite(pDev, pEp, vodafone_k3770_switch_packet, 31);
+ return true;
+ }
+ }
+ return false;
+}
+
+Endpoint* VodafoneK3770Initializer::getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx)
+{
+ return dev->getEndpoint(0, BULK_ENDPOINT, tx?OUT:IN, serialPortNumber);
+}
+
+int VodafoneK3770Initializer::getSerialPortCount()
+{
+ return 3;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USB3GModule/WANDongleInitializer.h Tue Jun 26 13:43:54 2012 +0000
@@ -0,0 +1,68 @@
+/* Copyright (c) 2010-2011 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.
+*/
+
+#ifndef WANDONGLEINITIALIZER_H
+#define WANDONGLEINITIALIZER_H
+
+#include <cstdint>
+using std::uint16_t;
+using std::uint32_t;
+
+#include "USBHost.h"
+
+class WANDongleInitializer
+{
+protected:
+ WANDongleInitializer(USBHost* pHost);
+ USBHost* m_pHost;
+
+public:
+ virtual uint16_t getMSDVid() = 0;
+ virtual uint16_t getMSDPid() = 0;
+
+ virtual uint16_t getSerialVid() = 0;
+ virtual uint16_t getSerialPid() = 0;
+
+ virtual bool switchMode(USBDeviceConnected* pDev) = 0;
+
+ virtual Endpoint* getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx) = 0;
+
+ virtual int getSerialPortCount() = 0;
+
+ static WANDongleInitializer[] getInitializers();
+};
+
+class VodafoneK3770Initializer : public WANDongleInitializer
+{
+public:
+ VodafoneK3770Initializer();
+
+ virtual uint16_t getMSDVid();
+ virtual uint16_t getMSDPid();
+
+ virtual uint16_t getSerialVid();
+ virtual uint16_t getSerialPid();
+
+ virtual bool switchMode(USBDeviceConnected* pDev);
+
+ virtual Endpoint* getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx);
+
+ virtual int getSerialPortCount() = 0;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USB3GModule/WANDongleSerialPort.cpp Tue Jun 26 13:43:54 2012 +0000
@@ -0,0 +1,317 @@
+/* Copyright (c) 2010-2011 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.
+*/
+
+#define __DEBUG__ 4 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "WANDongleSerialPort.cpp"
+#endif
+
+#include "dbg.h"
+#include <cstdint>
+#include "rtos.h"
+
+#include "WANDongleSerialPort.h"
+
+WANDongleSerialPort::WANDongleSerialPort() : cb_tx_en(false), cb_rx_en(false)
+{
+ reset();
+}
+
+void WANDongleSerialPort::init(USBHost* pHost)
+{
+ host = pHost;
+}
+
+void WANDongleSerialPort::reset()
+{
+ 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;
+}
+
+int WANDongleSerialPort::readPacket()
+{
+ rx_mtx.lock();
+ if(lock_rx)
+ {
+ ERR("Fail");
+ rx_mtx.unlock();
+ return -1;
+ }
+
+ lock_rx = true; //Receiving
+ rx_mtx.unlock();
+// DBG("readPacket");
+ //lock_rx.lock();
+ host->lock();
+ USB_TYPE res = host->bulkRead(dev, (Endpoint *)bulk_in, buf_in, ((Endpoint *)bulk_in)->getSize(), false); //Queue transfer
+ if(res != USB_TYPE_PROCESSING)
+ {
+ host->unlock();
+ //lock_rx.unlock();
+ ERR("host->bulkRead() returned %d", res);
+ Thread::wait(100);
+ return -1;
+ }
+ host->unlock();
+ return 0;
+}
+
+int WANDongleSerialPort::writePacket()
+{
+ tx_mtx.lock();
+ if(lock_tx)
+ {
+ ERR("Fail");
+ tx_mtx.unlock();
+ return -1;
+ }
+
+ lock_tx = true; //Transmitting
+ tx_mtx.unlock();
+// DBG("writePacket");
+
+ //lock_tx.lock();
+ host->lock();
+ USB_TYPE res = host->bulkWrite(dev, (Endpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
+ if(res != USB_TYPE_PROCESSING)
+ {
+ host->unlock();
+ //lock_tx.unlock();
+ ERR("host->bulkWrite() returned %d", res);
+ Thread::wait(100);
+ return -1;
+ }
+ host->unlock();
+ 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
+ {
+ 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
+ {
+ 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( Endpoint* pInEp, Endpoint* pOutEp )
+{
+ 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 (((Endpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
+ {
+ buf_in_read_pos = 0;
+ buf_in_len = ((Endpoint *) 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();
+ readPacket();
+ }
+}
+
+void WANDongleSerialPort::txHandler()
+{
+ if (((Endpoint *) 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USB3GModule/WANDongleSerialPort.h Tue Jun 26 13:43:54 2012 +0000
@@ -0,0 +1,125 @@
+/* Copyright (c) 2010-2011 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.
+*/
+
+#ifndef WANDONGLESERIALPORT_H
+#define WANDONGLESERIALPORT_H
+
+#include "USBHost.h"
+#include "IUSBHostSerial.h"
+
+#include "rtos.h"
+
+
+#define WANDONGLE_MAX_OUTEP_SIZE 64
+#define WANDONGLE_MAX_INEP_SIZE 64
+
+/** A class to use a WAN (3G/LTE) access dongle
+ *
+ */
+class WANDongle : public IUSBHostSerial {
+public:
+ /*
+ * Constructor
+ *
+ */
+ WANDongleSerialPort( );
+
+ void init(USBHost* pHost);
+
+ void connect( Endpoint* pInEp, Endpoint* pOutEp );
+
+ void disconnect( );
+
+ /*
+ * Get a char from the dongle's serial interface
+ */
+ virtual int getc();
+
+ /*
+ * Put a char to the dongle's serial interface
+ */
+ virtual int putc(int c);
+
+ /*
+ * Read a packet from the dongle's serial interface, to be called after multiple getc() calls
+ */
+ virtual int readPacket();
+
+ /*
+ * Write a packet to the dongle's serial interface, to be called after multiple putc() calls
+ */
+ virtual int writePacket();
+
+ /**
+ * Check the number of bytes available.
+ *
+ * @returns the number of bytes available
+ */
+ virtual int readable();
+
+ /**
+ * Check the free space in output.
+ *
+ * @returns the number of bytes available
+ */
+ virtual int writeable();
+
+ /**
+ * Attach a handler to call when a packet is received / when a packet has been transmitted.
+ *
+ * @param pListener instance of the listener deriving from the IUSBHostSerialListener
+ */
+ virtual void attach(IUSBHostSerialListener* pListener);
+
+ /**
+ * Enable or disable readable/writeable callbacks
+ */
+ virtual void setupIrq(bool en, IrqType irq = RxIrq);
+
+
+protected:
+ Endpoint * bulk_in;
+ Endpoint * bulk_out;
+ USBHost * host;
+
+ uint8_t buf_out[WANDONGLE_MAX_OUTEP_SIZE];
+ volatile uint32_t buf_out_len;
+ uint32_t max_out_size;
+ volatile bool lock_tx;
+ volatile bool cb_tx_en;
+ volatile bool cb_tx_pending;
+ Mutex tx_mtx;
+
+ uint8_t buf_in[WANDONGLE_MAX_INEP_SIZE];
+ volatile uint32_t buf_in_len;
+ volatile uint32_t buf_in_read_pos;
+ volatile bool lock_rx;
+ volatile bool cb_rx_en;
+ volatile bool cb_rx_pending;
+ Mutex rx_mtx;
+
+ IUSBHostSerialListener* listener;
+
+ void reset();
+
+ void rxHandler();
+ void txHandler();
+
+};
+
+#endif
--- a/USBHost/USBDeviceConnected.cpp Fri May 25 09:31:41 2012 +0000
+++ b/USBHost/USBDeviceConnected.cpp Tue Jun 26 13:43:54 2012 +0000
@@ -95,13 +95,20 @@
-Endpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) {
+Endpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index) {
if (intf_nb >= MAX_INTF) {
return NULL;
}
for (int i = 0; i < MAX_ENDPOINT_PER_INTERFACE; i++) {
if ((intf[intf_nb].ep[i]->getType() == type) && (intf[intf_nb].ep[i]->getDir() == dir)) {
- return intf[intf_nb].ep[i];
+ if(index)
+ {
+ index--;
+ }
+ else
+ {
+ return intf[intf_nb].ep[i];
+ }
}
}
return NULL;
--- a/USBHost/USBDeviceConnected.h Fri May 25 09:31:41 2012 +0000
+++ b/USBHost/USBDeviceConnected.h Tue Jun 26 13:43:54 2012 +0000
@@ -55,11 +55,13 @@
/*
* Retrieve an endpoint by its TYPE and DIRECTION
*
+ * @param intf_nb the interface on which to lookup the endpoint
* @param type type of the endpoint looked for
* @param direction of the endpoint looked for
+ * @param index the index of the endpoint whitin the interface
* @returns pointer on the endpoint if found, NULL otherwise
*/
- Endpoint * getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir);
+ Endpoint * getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index = 0);
/*
* Retrieve an endpoint by its index
