USB Host WAN Dongle library

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Revision:
2:a8b2d0cd9bbd
Parent:
1:49df46e3295c
Child:
3:4394986752db
--- 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();
-  }
-}