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.
Dependencies: Socket USBHostWANDongle lwip-sys lwip
Fork of VodafoneUSBModem by
Diff: contrib/vodafone/if/VodafoneK3770.cpp
- Revision:
- 0:3b2f052c333b
diff -r 000000000000 -r 3b2f052c333b contrib/vodafone/if/VodafoneK3770.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/vodafone/if/VodafoneK3770.cpp Thu May 24 16:40:40 2012 +0000
@@ -0,0 +1,474 @@
+/* VodafoneK3770.cpp */
+/*
+Copyright (C) 2012 ARM Limited.
+
+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
+#ifndef __MODULE__
+#define __MODULE__ "VodafoneK3770.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "VodafoneK3770.h"
+
+VodafoneK3770::VodafoneK3770() : m_dongle(),
+m_stream(m_dongle), m_at(&m_stream),
+m_ppp(&m_stream), m_sms(&m_at), m_ussd(&m_at),
+m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false)
+{
+
+}
+
+class CREGProcessor : public IATCommandsProcessor
+{
+public:
+ CREGProcessor() : status(STATUS_REGISTERING)
+ {
+
+ }
+ enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED };
+ REGISTERING_STATUS getStatus()
+ {
+ return status;
+ }
+private:
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+ {
+ int r;
+ if( sscanf(line, "+CREG: %*d,%d", &r) == 1 )
+ {
+ switch(r)
+ {
+ case 1:
+ case 5:
+ status = STATUS_OK;
+ break;
+ case 0:
+ case 2:
+ status = STATUS_REGISTERING;
+ break;
+ case 3:
+ default:
+ status = STATUS_FAILED;
+ break;
+ }
+ }
+ return OK;
+ }
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+ {
+ return OK;
+ }
+ volatile REGISTERING_STATUS status;
+};
+
+class COPSProcessor : public IATCommandsProcessor
+{
+public:
+ COPSProcessor() : valid(false)
+ {
+ network[0] = '\0';
+ apn[0] = '\0';
+ bearer[0] = '\0';
+ }
+ char* getNetwork()
+ {
+ return network;
+ }
+ char* getAPN()
+ {
+ return apn;
+ }
+ char* getBearer()
+ {
+ return bearer;
+ }
+ bool isValid()
+ {
+ return valid;
+ }
+private:
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+ {
+ int networkId;
+ int bearerId;
+ int s = sscanf(line, "+COPS: %*d,%*d,\"%d\",%d", &networkId, &bearerId);
+ if( s == 2 )
+ {
+ switch(networkId)
+ {
+ case 23415:
+ strcpy(network, "Vodafone UK");
+ strcpy(apn, "pp.vodafone.co.uk");
+ valid = true;
+ break;
+ case 20810:
+ strcpy(network, "SFR FR");
+ strcpy(apn, "websfr");
+ valid = true;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ return OK;
+ }
+ switch(bearerId)
+ {
+ case 0: strcpy(bearer, "GSM"); break;
+ case 1: strcpy(bearer, "GSM Compact"); break;
+ case 2: strcpy(bearer, "UTRAN"); break;
+ case 3: strcpy(bearer, "GSM w/EGPRS"); break;
+ case 4: strcpy(bearer, "UTRAN w/HSDPA"); break;
+ case 5: strcpy(bearer, "UTRAN w/HSUPA"); break;
+ case 6: strcpy(bearer, "UTRAN w/HSDPA and HSUPA"); break;
+ case 7: strcpy(bearer, "E-UTRAN"); break;
+
+ default:
+ break;
+ }
+ return OK;
+ }
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+ {
+ return OK;
+ }
+ char network[24];
+ char bearer[24];
+ char apn[24];
+ volatile bool valid;
+};
+
+
+int VodafoneK3770::connect(const char* apn, const char* user, const char* password)
+{
+ if( !m_ipInit )
+ {
+ m_ipInit = true;
+ m_ppp.init();
+ }
+ m_ppp.setup(user, password);
+
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ m_smsInit = false; //SMS status reset
+ m_ussdInit = false; //USSD status reset
+
+ ATCommandsInterface::ATResult result;
+
+#if 0
+ //Get network info & select corresponding APN
+ COPSProcessor copsProcessor;
+ DBG("Get network info & select APN from DB");
+ ret = m_at.execute("AT+COPS=,2;+COPS?", &copsProcessor, &result); //Configure to get operator's info in numeric code & get operator's id
+ DBG("Result of command: Err code=%d", ret);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+
+ if(!copsProcessor.isValid())
+ {
+ WARN("Connected to an unknown network, try to connect with default parameters");
+ DBG("Connected with %s", copsProcessor.getBearer());
+ }
+ else
+ {
+ DBG("Connected to %s with %s", copsProcessor.getNetwork(), copsProcessor.getBearer());
+ char cmd[48];
+ sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", copsProcessor.getAPN());
+ ret = m_at.executeSimple(cmd, &result);
+ DBG("Result of command: Err code=%d", ret);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+ DBG("APN set to %s", copsProcessor.getAPN());
+ }
+ #else
+ if(apn != NULL)
+ {
+ char cmd[48];
+ sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+ ret = m_at.executeSimple(cmd, &result);
+ DBG("Result of command: Err code=%d", ret);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+ DBG("APN set to %s", apn);
+ }
+ #endif
+
+
+ //Connect
+ DBG("Connecting");
+ ret = m_at.executeSimple("ATDT *99#", &result);
+ DBG("Result of command: Err code=%d", ret);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+ m_at.close(); // Closing AT parser
+ m_atOpen = false; //Will need to be reinitialized afterwards
+
+ DBG("AT Parser closed");
+ if( (ret!=NET_MOREINFO) || (result.result != ATCommandsInterface::ATResult::AT_CONNECT))
+ {
+ ERR("Could not connect");
+ return ret; //Could not connect
+ }
+ DBG("Connecting PPP");
+
+ ret = m_ppp.connect();
+ DBG("Result of connect: Err code=%d", ret);
+ return ret;
+}
+
+
+int VodafoneK3770::disconnect()
+{
+ DBG("Disconnecting from PPP");
+ int ret = m_ppp.disconnect();
+ if(ret)
+ {
+ ERR("Disconnect returned %d, still trying to disconnect", ret);
+ }
+
+ //Ugly but leave dongle time to recover
+ Thread::wait(500);
+
+ ATCommandsInterface::ATResult result;
+ DBG("Starting AT thread");
+ ret = m_at.open();
+ if(ret)
+ {
+ return ret;
+ }
+
+ DBG("Trying to hangup");
+
+#if 0 //Does not appear to work
+ int tries = 10;
+ do
+ {
+ ret = m_at.executeSimple("+++", &result, 1000);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ } while(tries-- && ret);
+ if(!ret)
+ {
+ ret = m_at.executeSimple("ATH", &result);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ }
+#endif
+
+ //Reinit AT parser
+ ret = m_at.init();
+ DBG("Result of command: Err code=%d\n", ret);
+ if(ret)
+ {
+ m_at.close(); // Closing AT parser
+ DBG("AT Parser closed, could not complete disconnection");
+ return NET_TIMEOUT;
+ }
+
+ m_at.close(); // Closing AT parser
+ DBG("AT Parser closed");
+ return OK;
+}
+
+int VodafoneK3770::sendSM(const char* number, const char* message)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.send(number, message);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int VodafoneK3770::getSM(char* number, char* message, size_t maxLength)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.get(number, message, maxLength);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int VodafoneK3770::getSMCount(size_t* pCount)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.getCount(pCount);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int VodafoneK3770::sendUSSD(const char* command, char* result, size_t maxLength)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_ussdInit)
+ {
+ ret = m_ussd.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_ussdInit = true;
+ }
+
+ ret = m_ussd.send(command, result, maxLength);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+ATCommandsInterface* VodafoneK3770::getATCommandsInterface()
+{
+ return &m_at;
+}
+
+int VodafoneK3770::init()
+{
+ if( !m_dongleConnected )
+ {
+ m_dongleConnected = true;
+ while( !m_dongle.connected() )
+ {
+ m_dongle.tryConnect();
+ Thread::wait(10);
+ }
+ }
+
+ if(m_atOpen)
+ {
+ return OK;
+ }
+
+ DBG("Starting AT thread if needed");
+ int ret = m_at.open();
+ if(ret)
+ {
+ return ret;
+ }
+
+ DBG("Sending initialisation commands");
+ ret = m_at.init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ DBG("Configuring unsolicited result codes support properly");
+ //Configuring port
+ ret = m_at.executeSimple("AT^CURC=0;^PORTSEL=1", NULL); //Huawei-specific, not 3GPP-compliant
+ if(ret != OK)
+ {
+ return NET_PROTOCOL;
+ }
+
+ ATCommandsInterface::ATResult result;
+
+ //Wait for network registration
+ CREGProcessor cregProcessor;
+ do
+ {
+ DBG("Waiting for network registration");
+ ret = m_at.execute("AT+CREG?", &cregProcessor, &result);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING)
+ {
+ Thread::wait(3000);
+ }
+ } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING);
+ if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED)
+ {
+ ERR("Registration denied");
+ return NET_AUTH;
+ }
+
+ m_atOpen = true;
+
+ return OK;
+}
+
+
+
