wps/WapPush.cpp
#include "WapPush.h"
#include "wbxml2\wbxml.h"
#define ASCII(x) ((x >= 0 && x <= 9) ? x += '0' : x += 'A' - 0x0A)
#define MESSAGE_DELIVERED 0
#define MODEM_NETWORK_ERROR 1
#define FORMAT_ERROR 2
#define ARG_ERROR 3
#define CMDLINE_ERROR 4
#define PIN_ERROR 5
#define SERVICE_ERROR 6
#define MODEM_ERROR 7
#define NETWORK_ERROR 8
#define MODEM_NOT_FOUND_ERROR 9
#define MODEM_NOT_ATTACHED_ERROR 10
#define MSG_TOO_LONG_ERROR 11
WapPush::WapPush() : m_bCOMOpen(FALSE), m_pcWbXml(NULL), m_pcAsciiXml(NULL), m_bStandardSms(FALSE) {
ZeroMemory(cBCDNumber, sizeof(cBCDNumber));
}
WapPush::~WapPush() {
Close();
if (m_pcWbXml != NULL)
wbxml_free(m_pcWbXml);
if (m_pcAsciiXml != NULL)
delete[] m_pcAsciiXml;
}
BOOL WapPush::AutoDiscover() {
WCHAR wPort[6];
for (UINT i = 1; i < 30; i++) {
wsprintf(wPort, L"COM%d", i);
//wprintf(L"[DEBUG] checking port: COM%d\n", i);
if (SetPort(wPort) == FALSE) {
wprintf(L"[DEBUG] Port seems invalid\n");
continue;
}
if (Open() == FALSE) {
wprintf(L"[DEBUG] Port cannot be opened\n");
continue;
}
if (isZadako() || isSierra() || isUnknownButValid()) {
Close();
SetPort(wPort);
wprintf(L"[INFO] Suitable modem identified on port: %s\n", wPort);
return TRUE;
}
wprintf(L"[DEBUG] Modem found is not suitable for this message category\n");
Close();
}
wprintf(L"[ERROR] Unable to autodiscover a suitable modem\n");
wprintf(L"[INFO] Please remind: if you're using a Zadako Modem, the \"AirCard Watcher\" utility MUST be _running_)\n");
wprintf(L"[INFO] Please remind: if you're using a Sierra Modem, the \"Sierra Wireless Discovery Tool\" MUST be *closed*)\n");
return FALSE;
}
// Ritorna la porta sui cui si trova uno dei nostri modem o -1 se non la trova
INT WapPush::GetAutoDiscovered() {
WCHAR wPort[6];
for (UINT i = 1; i < 50; i++) {
wsprintf(wPort, L"COM%d", i);
if (SetPort(wPort) == FALSE) {
continue;
}
if (Open() == FALSE) {
continue;
}
if (isZadako() || isSierra() || isUnknownButValid()) {
Close();
return (INT)i;
}
il
Close();
}
return -1;
}
// Zadako
// AT+CGMI -> Sierra Wireless
// AT+CGMM -> MC8755 o MC8775
// MC8790 -> Non di HT ma usato da CNI
BOOL WapPush::isZadako() {
string response;
response = SendCommandAndGet("AT+CGMI\r");
// REMOVE
wprintf(L"[DEBUG] Manufacturer: %S\n", response.c_str());
if (response.find("Sierra Wireless") == string::npos) {
//wprintf(L"[DEBUG] Not Zadako a, response: %S\n", response.c_str());
return FALSE;
}
response = SendCommandAndGet("AT+CGMM\r");
// REMOVE
wprintf(L"[DEBUG] Chipset: %S\n", response.c_str());
if (response.find("MC8755") == string::npos && response.find("MC8775") == string::npos && response.find("MC8790") == string::npos) {
//wprintf(L"[DEBUG] Not Zadako b, response: %S\n", response.c_str());
return FALSE;
}
return TRUE;
}
// Unknown model
// AT+CGMI -> ZTE INCORPORATED
// AT+CGMM -> MF626
// MF626 -> Non di HT ma usato da UZC
BOOL WapPush::isUnknownButValid() {
return FALSE;
string response;
response = SendCommandAndGet("AT+CGMI\r");
// REMOVE
wprintf(L"[DEBUG] Manufacturer: %S\n", response.c_str());
if (response.find("ZTE INCORPORATED") == string::npos) {
//wprintf(L"[DEBUG] Not Zadako a, response: %S\n", response.c_str());
return FALSE;
}
response = SendCommandAndGet("AT+CGMM\r");
// REMOVE
wprintf(L"[DEBUG] Chipset: %S\n", response.c_str());
if (response.find("MF626") == string::npos) {
//wprintf(L"[DEBUG] Not Zadako b, response: %S\n", response.c_str());
return FALSE;
}
return TRUE;
}
// Sierra Wireless
// AT+CGMI -> WAVECOM
// AT+CGMR -> FXT001 o FXT003
BOOL WapPush::isSierra() {
string response;
response = SendCommandAndGet("AT+CGMI\r");
// REMOVE
wprintf(L"[DEBUG] Manufacturer: %S\n", response.c_str());
if (response.find("WAVECOM") == string::npos) {
//wprintf(L"[DEBUG] Not Sierra a, response: %S\n", response.c_str());
return FALSE;
}
response = SendCommandAndGet("AT+CGMR\r");
// REMOVE
wprintf(L"[DEBUG] Chipset: %S\n", response.c_str());
if (response.find("FXT001") == string::npos && response.find("FXT003") == string::npos) {
//wprintf(L"[DEBUG] Not Sierra b, response: %S\n", response.c_str());
return FALSE;
}
return TRUE;
}
BOOL WapPush::Open() {
if (strPort.empty()) {
wprintf(L"[ERROR] No COM port set\n");
m_bCOMOpen = FALSE;
return FALSE;
}
if (m_bCOMOpen)
return TRUE;
if (serialObj.Open(strPort)) {
m_bCOMOpen = TRUE;
return TRUE;
}
m_bCOMOpen = FALSE;
return FALSE;
}
BOOL WapPush::Close() {
if (m_bCOMOpen == FALSE)
return TRUE;
if (serialObj.Close()) {
m_bCOMOpen = FALSE;
return TRUE;
}
m_bCOMOpen = TRUE;
return FALSE;
}
BOOL WapPush::SetPort(PWCHAR pwPort) {
if (pwPort == NULL) {
wprintf(L"[INFO] Port missing, autodiscovering...\n");
return FALSE;
}
if (wcslen(pwPort) < 4 || wcslen(pwPort) > 6) {
wprintf(L"[ERROR] Invalid port format, should be: COM1, COM3, COM12 etc...\n");
return FALSE;
}
if (m_bCOMOpen && strPort.empty() == FALSE) {
// Convert to uppercase
transform(strPort.begin(), strPort.end(), strPort.begin(), ptr_fun(toupper));
}
if (m_bCOMOpen && strPort.empty() == FALSE && strPort.compare(pwPort)) {
wprintf(L"[INFO] Port changed, closing old connection...\n");
Close();
}
strPort = pwPort;
// Convert to uppercase
transform(strPort.begin(), strPort.end(), strPort.begin(), ptr_fun(toupper));
return TRUE;
}
BOOL WapPush::SetPIN(PWCHAR pwPin) {
if (pwPin == NULL) {
strPin.clear();
return TRUE;
}
strPin = pwPin;
return TRUE;
}
BOOL WapPush::SetNumber(PWCHAR pwNumber) {
UINT i;
if (pwNumber == NULL || wcslen(pwNumber) > 15 || wcslen(pwNumber) < 10) {
wprintf(L"[ERROR] Phone number format is invalid or missing\n");
return FALSE;
}
strNumber = pwNumber;
wprintf(L"[INFO] Phone number set to: %s\n", pwNumber);
// We have to convert it in BCD format
if (wcslen(pwNumber) & 1) {
// Odd number, padding required
sprintf_s(cBCDNumber, sizeof(cBCDNumber), "%SF", pwNumber);
} else {
sprintf_s(cBCDNumber, sizeof(cBCDNumber), "%S", pwNumber);
}
for (i = 0; i < strlen(cBCDNumber) - 1; i += 2) {
CHAR tmp;
tmp = cBCDNumber[i];
cBCDNumber[i] = cBCDNumber[i + 1];
cBCDNumber[i + 1] = tmp;
}
return TRUE;
}
BOOL WapPush::SetLink(PWCHAR pwLink) {
if (pwLink == NULL) {
wprintf(L"[ERROR] HTTP Link format is invalid or missing\n");
return FALSE;
}
strLink = pwLink;
return TRUE;
}
// Text can be NULL
BOOL WapPush::SetText(PWCHAR pwText) {
if (pwText == NULL) {
strText = L"";
} else {
strText = pwText;
}
return TRUE;
}
BOOL WapPush::SetService(PWCHAR pwService) {
if (pwService == NULL) {
wprintf(L"[ERROR] Service format is invalid or missing\n");
return FALSE;
}
strService = pwService;
// Convert to lowercase
transform(strService.begin(), strService.end(), strService.begin(), ptr_fun(tolower));
// Enforce type ("si" or "sl" or "sms")
if (strService.compare(L"si") && strService.compare(L"sl") && strService.compare(L"sms")) {
wprintf(L"[ERROR] Service format is invalid\n");
return FALSE;
}
if (!strService.compare(L"sms")) {
this->m_bStandardSms = TRUE;
}
return TRUE;
}
BOOL WapPush::SetPriority(PWCHAR pwPriority) {
if (pwPriority == NULL) {
wprintf(L"[ERROR] Priority format is invalid or missing\n");
return FALSE;
}
strPriority = pwPriority;
// Convert to lowercase
transform(strPriority.begin(), strPriority.end(), strPriority.begin(), ptr_fun(tolower));
// Enforce type
if (strService.empty() == FALSE) {
// We have service-type set (SI)
if (!strService.compare(L"si")) {
// signal-none, signal-low, signal-medium, signal-high, delete
if (strPriority.compare(L"signal-none") && strPriority.compare(L"signal-low") &&
strPriority.compare(L"signal-medium") && strPriority.compare(L"signal-high") &&
strPriority.compare(L"delete")) {
wprintf(L"[ERROR] Chosen priority is not compatible with type SI\n");
return FALSE;
}
} else if (!strService.compare(L"sl")) { // SL
// execute-low, execute-high, cache
if (strPriority.compare(L"execute-low") && strPriority.compare(L"execute-high") &&
strPriority.compare(L"cache")) {
wprintf(L"[ERROR] Chosen priority is not compatible with type SL\n");
return FALSE;
}
} else if (!strService.compare(L"sms")) { // SMS
} else {
wprintf(L"[ERROR] Service format is invalid\n");
return FALSE;
}
} else {
// Service not set, we have to check all types
if (strPriority.compare(L"signal-none") && strPriority.compare(L"signal-low") &&
strPriority.compare(L"signal-medium") && strPriority.compare(L"signal-high") &&
strPriority.compare(L"delete") && strPriority.compare(L"execute-low") &&
strPriority.compare(L"execute-high") && strPriority.compare(L"cache")) {
wprintf(L"[ERROR] Chosen priority type is invalid\n");
return FALSE;
}
}
return TRUE;
}
BOOL WapPush::SetDate(PWCHAR pwDate) {
if (!strService.compare(L"si") && (pwDate == NULL || wcslen(pwDate) == 0)) {
wprintf(L"[ERROR] Creation date is mandatory for service type \"si\"\n");
return FALSE;
}
if (pwDate == NULL)
strDate = L"";
else
strDate = pwDate;
return TRUE;
}
BOOL WapPush::SendMessage(PWCHAR pwPort, PWCHAR pwPIN, PWCHAR pwNumber, PWCHAR pwText,
PWCHAR pwService, PWCHAR pwPriority, PWCHAR pwLink, PWCHAR pwDate) {
CHAR *pcMsg = NULL;
if (SetPort(pwPort) == FALSE) {
if (AutoDiscover() == FALSE) {
return MODEM_NOT_FOUND_ERROR;
}
}
if (SetNumber(pwNumber) == FALSE)
return ARG_ERROR;
if (SetPIN(pwPIN) == FALSE)
return PIN_ERROR;
if (SetText(pwText) == FALSE)
return ARG_ERROR;
if (SetService(pwService) == FALSE)
return SERVICE_ERROR;
INT msgLen = 0;
if (pwText)
msgLen += wcslen(pwText);
if (pwLink)
msgLen += wcslen(pwLink);
if (msgLen > 76) {
wprintf(L"[ERROR] Total text length: %d\n", msgLen);
return MSG_TOO_LONG_ERROR;
}
// Attach, just in case
SendCommand("AT+CGATT=1\r");
string resp = SendCommandAndGet("AT+CGATT?\r");
// If we are not attached, return error
if (resp.find("0") != string::npos) {
wprintf(L"[WARNING] Modem is not attached to GPRS network\n");
wprintf(L"[NOTICE] Trying to attach to the network...\n");
Sleep(3000);
resp = SendCommandAndGet("AT+CGATT?\r");
if (resp.find("0") != string::npos) {
wprintf(L"[ERROR] Giving up, modem is not attached to GRPS network\n");
return MODEM_NOT_ATTACHED_ERROR;
}
wprintf(L"[NOTICE] Interface now ready\n");
}
if (this->m_bStandardSms == FALSE) {
if (SetPriority(pwPriority) == FALSE)
return ARG_ERROR;
if (SetDate(pwDate) == FALSE)
return ARG_ERROR;
if (SetLink(pwLink) == FALSE)
return ARG_ERROR;
// Let's build a "standard" message (XML to WBXML to ASCII)
if (BuildWBXML() == FALSE) {
return FORMAT_ERROR;
}
wprintf(L"[INFO] WBXML Built\n");
} else { // Send the SMS
// AT+CMGS="pwNumber"\r\npwMsg\x1A
int cmdLen = strlen("AT+CMGS=\"+") + strNumber.length() + strlen("\"\r\n") + strText.length() + strlen("\x1A");
pcMsg = new(std::nothrow) CHAR[cmdLen + 1];
if (pcMsg == NULL) {
wprintf(L"[ERROR] Cannot allocate memory for final message\n");
return ARG_ERROR;
}
ZeroMemory(pcMsg, cmdLen + 1);
// Enter text mode
if (SendCommandAndCheck("AT+CMGF=1\r\n", "OK") <= 0) {
wprintf(L"[ERROR] Cannot enter TEXT mode\n");
// "Reset" commandline
SendCommand("\x1A");
return MODEM_ERROR;
}
// AT+CMGS=XX
sprintf_s(pcMsg, cmdLen + 1, "AT+CMGS=\"+%S\"\r\n", strNumber.c_str());
if (SendCommandAndCheck(pcMsg, ">") <= 0) {
wprintf(L"[ERROR] Wrong answer from GSM modem\n");
wprintf(L"[INFO] Please remind: if you're using a Zadako Modem, the \"AirCard Watcher\" utility MUST be _running_)\n");
wprintf(L"[INFO] Please remind: if you're using a Sierra Modem, the \"Sierra Wireless Discovery Tool\" MUST be *closed*)\n");
delete[] pcMsg;
return NETWORK_ERROR;
}
sprintf_s(pcMsg, cmdLen + 1, "%S\x1A", strText.c_str());
// Response is a bit variable, so we ignore it
if (SendCommandAndCheck(pcMsg, "OK") <= 0) {
//wprintf(L"[ERROR] Wrong answer from GSM modem after text\n");
//delete[] pcMsg;
//return FALSE;
}
delete[] pcMsg;
return MESSAGE_DELIVERED;
}
// Let's add: GSM 03.40 Header, UDHI Length, WDP Layer and WSP Layer
if (AddGSMHeaders() == FALSE) {
return ARG_ERROR;
}
wprintf(L"[INFO] Final message created\n");
// Now we can try to send it: let's enter in PDU mode
if (SendCommandAndCheck("AT+CMGF=0\r\n", "OK") <= 0) {
wprintf(L"[ERROR] Cannot enter PDU mode\n");
// "Reset" commandline
SendCommand("\x1A");
return MODEM_ERROR;
}
wprintf(L"[INFO] PDU mode set\n");
// Better to enable error mode
if (SendCommandAndCheck("AT+CMEE=1\r\n", "OK") < 0) {
wprintf(L"[WARNING] Cannot enable ERROR mode\n");
}
wprintf(L"[INFO] Sending message...\n");
// Let's tell the modem we want to send an SMS
pcMsg = new(std::nothrow) CHAR[m_uAsciiXmlLen + 1 + 1];
if (pcMsg == NULL) {
wprintf(L"[ERROR] Cannot allocate memory for final message\n");
return MODEM_NETWORK_ERROR;
}
if ((m_uAsciiXmlLen >> 1) - 1 > 153) {
wprintf(L"[ERROR] Message too long to be sent\n");
delete[] pcMsg;
return FORMAT_ERROR;
}
// AT+CMGS=XX
sprintf_s(pcMsg, m_uAsciiXmlLen + 2, "AT+CMGS=%d\r", (m_uAsciiXmlLen >> 1) - 1);
if (SendCommandAndCheck(pcMsg, ">") <= 0) {
wprintf(L"[ERROR] Wrong answer from GSM modem\n");
delete[] pcMsg;
return NETWORK_ERROR;
}
// Actual payload 0055....
sprintf_s(pcMsg, m_uAsciiXmlLen + 2, "%s\x1A", m_pcAsciiXml);
// Let's set a higher timeout for message sending
serialObj.SetComReadWaitTime(5000);
if (SendCommandAndCheck(pcMsg, "OK") <= 0) {
wprintf(L"[ERROR] Cannot send message\n");
wprintf(L"[INFO] Please remind: if you're using a Zadako Modem, the \"AirCard Watcher\" utility MUST be _running_)\n");
wprintf(L"[INFO] Please remind: if you're using a Sierra Modem, the \"Sierra Wireless Discovery Tool\" MUST be *closed*)\n");
// Modem reset
pcMsg[0] = 0x1A;
pcMsg[1] = 0;
SendCommand(pcMsg);
serialObj.SetComReadWaitTime(200);
delete[] pcMsg;
return MODEM_NETWORK_ERROR;
}
wprintf(L"[INFO] Message delivered\n");
delete[] pcMsg;
serialObj.SetComReadWaitTime(200);
return MESSAGE_DELIVERED;
}
INT WapPush::SendMessage(PWCHAR pwPort, PWCHAR pwPIN, PWCHAR pwNumber, PCHAR pcXml) {
wprintf(L"[ERROR] NOT IMPLEMENTED\n");
return FALSE;
}
// Text (optional) and Link must be already set at this point
BOOL WapPush::BuildWBXML() {
CHAR *xml_exp = NULL;
UINT xml_len = 0;
WBXMLGenWBXMLParams params;
WBXMLError ret = WBXML_OK;
/*
* - Service Loading
* Possible signals:
* execute-low, execute-high, cache
*/
CHAR xml_sl[] =
"<?xml version=\"1.0\"?>"
"<!DOCTYPE sl PUBLIC \"-//WAPFORUM//DTD SL 1.0//EN\" \"http://www.wapforum.org/DTD/sl.dtd\">"
"<sl href=\"%S\" action=\"%S\" />"; // Link - Priority
/*
* - Service Indication
* Possible signals:
* signal-none, signal-low, signal-medium, signal-high, delete
*/
CHAR xml_si[] =
"<?xml version=\"1.0\"?>"
"<!DOCTYPE si PUBLIC \"-//WAPFORUM//DTD SI 1.0//EN\" \"http://www.wapforum.org/DTD/si.dtd\">"
"<si>"
"<indication href=\"%S\" action=\"%S\" created=\"%SZ\" si-id=\"1101\">" // Link - Priority - Date
"%S" // Text
"</indication>"
"</si>";
if (strNumber.empty()) {
wprintf(L"[ERROR] Number not set cannot build XML\n");
return FALSE;
}
if (strLink.empty()) {
wprintf(L"[ERROR] Link not set, cannot build XML\n");
return FALSE;
}
if (strService.empty()) {
wprintf(L"[ERROR] Service not set, cannot build XML\n");
return FALSE;
}
if (strPriority.empty()) {
wprintf(L"[ERROR] Priority not set, cannot build XML\n");
return FALSE;
}
if (strDate.empty() && !strService.compare(L"si")) {
wprintf(L"[ERROR] Creation date not set, cannot build XML\n");
return FALSE;
}
// SI Xml
if (!strService.compare(L"sl")) {
xml_len = strlen(xml_sl) + strLink.size() + strPriority.size() + 1;
xml_exp = new(std::nothrow) CHAR[xml_len];
if (xml_exp == NULL) {
wprintf(L"[ERROR] Cannot allocate memory for XML\n");
return FALSE;
}
sprintf_s(xml_exp, xml_len, xml_sl, strLink.c_str(), strPriority.c_str());
} else if (!strService.compare(L"si")) { // SL Xml
xml_len = strlen(xml_si) + strLink.size() + strPriority.size() + strDate.size() + strText.size() + 1;
xml_exp = new(std::nothrow) CHAR[xml_len];
if (xml_exp == NULL) {
wprintf(L"[ERROR] Cannot allocate memory for XML\n");
return FALSE;
}
sprintf_s(xml_exp, xml_len, xml_si, strLink.c_str(), strPriority.c_str(), strDate.c_str(), strText.c_str());
} else {
wprintf(L"[ERROR] Unknown service type\n");
return FALSE;
}
xml_len = strlen(xml_exp);
params.wbxml_version = WBXML_VERSION_13;
params.use_strtbl = TRUE;
params.keep_ignorable_ws = FALSE;
if (m_pcWbXml != NULL) {
wbxml_free(m_pcWbXml);
m_pcWbXml = NULL;
m_uWbXmlLen = 0;
}
ret = wbxml_conv_xml2wbxml_withlen((PUCHAR)xml_exp, xml_len, (UCHAR **)&m_pcWbXml, &m_uWbXmlLen, ¶ms);
delete[] xml_exp;
if (ret != WBXML_OK) {
wprintf(L"[ERROR] %s\n", wbxml_errors_string(ret));
return FALSE;
}
if (WBXMLToAscii() == FALSE) {
wprintf(L"[ERROR] Error converting WBXML to ASCII\n");
return FALSE;
}
return TRUE;
}
BOOL WapPush::AddGSMHeaders() {
// Service Loading
CHAR cHeaders_sl[] =
"0041000%X91%s0004%02X" // --> GSM 03.40 Header (length and number in BCD), payload length
"0B" // --> UDHI Length
"05040B84C0020003F00101" // --> WDP Layer
"0A060403B081EA" // --> WSP Layer
"%s"; // --> WBXML Message
// Service Indication
CHAR cHeaders_si[] =
"0055010%X91%s00F5A7%02X" // --> GSM 03.40 Header (length and number in BCD), payload length
"06" // --> UDHI Length
"05040B8423F0" // --> WDP Layer
"01060403AE81EA" // --> WSP Layer
"%s"; // --> WBXML Message
CHAR *pcMsg;
UINT uHeaderLen;
UINT uPayloadLen;
if (!strService.compare(L"sl")) {
uHeaderLen = strlen(cHeaders_sl) + 1 + 15 + strlen(m_pcAsciiXml) + 1;
} else if (!strService.compare(L"si")) {
uHeaderLen = strlen(cHeaders_si) + 1 + 15 + strlen(m_pcAsciiXml) + 1;
} else {
wprintf(L"[ERROR] Unknown service type\n");
return FALSE;
}
pcMsg = new(std::nothrow) CHAR[uHeaderLen];
ZeroMemory(pcMsg, uHeaderLen);
if (pcMsg == NULL) {
wprintf(L"[ERROR] Error allocating memory for GSM headers\n");
return FALSE;
}
// Calculate payload length
if (!strService.compare(L"sl")) {
// Service Loading
uPayloadLen = strlen("0B") + strlen("05040B84C0020003F00101") + strlen("0A060403B081EA") +
strlen(m_pcAsciiXml);
uPayloadLen >>= 1;
sprintf_s(pcMsg, uHeaderLen, cHeaders_sl, strNumber.size(), cBCDNumber, uPayloadLen, m_pcAsciiXml);
} else {
// Service Indication
uPayloadLen = strlen("06") + strlen("05040B8423F0") + strlen("01060403AE81EA") + strlen(m_pcAsciiXml);
uPayloadLen >>= 1;
sprintf_s(pcMsg, uHeaderLen, cHeaders_si, strNumber.size(), cBCDNumber, uPayloadLen, m_pcAsciiXml);
}
uHeaderLen--; // Real length
// Clean-up old ASCII-XML and replace it with the expanded one
delete[] m_pcAsciiXml;
m_pcAsciiXml = pcMsg;
m_uAsciiXmlLen = strlen(m_pcAsciiXml);
return TRUE;
}
BOOL WapPush::WBXMLToAscii() {
UINT i, j;
if (m_pcWbXml == NULL || m_uWbXmlLen == 0) {
wprintf(L"[ERROR] There is no WBXML to convert\n");
return FALSE;
}
if (m_pcAsciiXml != NULL) {
delete[] m_pcAsciiXml;
m_pcAsciiXml = NULL;
m_uAsciiXmlLen = 0;
}
m_uAsciiXmlLen = m_uWbXmlLen * 2 + 1;
m_pcAsciiXml = new(std::nothrow) CHAR[m_uAsciiXmlLen];
if (m_pcAsciiXml == NULL) {
wprintf(L"[ERROR] Error allocating WBXML-ASCII array\n");
return FALSE;
}
m_uAsciiXmlLen--; // Real length
m_pcAsciiXml[m_uAsciiXmlLen] = 0;
// Hex to ASCII
for (i = 0, j = 0; i < m_uWbXmlLen; i++, j += 2) {
CHAR tmp = (m_pcWbXml[i] & 0xF0) >> 4;
m_pcAsciiXml[j] = ASCII(tmp);
tmp = m_pcWbXml[i] & 0x0F;
m_pcAsciiXml[j + 1] = ASCII(tmp);
}
// Cleanup of m_cWbXML buffer
if (m_pcWbXml != NULL) {
wbxml_free(m_pcWbXml);
m_pcWbXml = NULL;
m_uWbXmlLen = 0;
}
return TRUE;
}
BOOL WapPush::CheckModem(PWCHAR pwPort, PWCHAR pwPIN) {
INT iCheck;
if (SetPort(pwPort) == FALSE)
return FALSE;
if (SetPIN(pwPIN) == FALSE)
return FALSE;
// Check AT
iCheck = SendCommandAndCheck("AT\r", "OK\r");
if (iCheck == 0) {
wprintf(L"[ERROR] Cannot send command to GSM modem\n");
return FALSE;
}
if (iCheck < 0) {
wprintf(L"[ERROR] AT interface is not ready\n");
return FALSE;
}
wprintf(L"[CHECK] AT interface is ready\n");
// Let's see if we need a PIN
iCheck = SendCommandAndCheck("AT+CPIN?\r", "READY");
if (iCheck == 0) {
wprintf(L"[ERROR] Cannot send command to GSM modem\n");
return FALSE;
}
// In case we insert the provided PIN
if (iCheck < 0) {
wprintf(L"[INFO] A PIN code is required to operate the SIM card\n");
if (strPin.empty()) {
wprintf(L"[ERROR] No PIN has been provided, exiting...\n");
}
char cPinBuf[30];
sprintf_s(cPinBuf, 30, "AT+CPIN=\"%S\"\r", strPin.c_str());
iCheck = SendCommandAndCheck(cPinBuf, "OK");
if (iCheck < 0) {
wprintf(L"[ERROR] Wrong PIN used\n");
return FALSE;
}
if (iCheck == 0) {
wprintf(L"[ERROR] Error sending PIN\n");
return FALSE;
}
} else {
wprintf(L"[INFO] No PIN code required to operate SIM card\n");
}
SendCommandAndCheck("AT+CPIN?\r", "waiting response"); // PIN status
SendCommandAndCheck("AT+CREG?\r", "waiting response"); // Network registration status
SendCommandAndCheck("AT+CSQ\r", "waiting response"); // Signal strength
SendCommandAndCheck("AT+CGMM\r", "waiting response"); // Producer identification
SendCommandAndCheck("AT+CGMI\r", "waiting response"); // Model identification
SendCommandAndCheck("AT+CGMR\r", "waiting response"); // Revision information
SendCommandAndCheck("AT+CGSN\r", "waiting response"); // Serial number
SendCommandAndCheck("AT+CIMI\r", "waiting response"); // IMSI
SendCommandAndCheck("AT+CCID\r", "waiting response"); // SIM EF-CCID
SendCommandAndCheck("AT+GCAP\r", "waiting response"); // Device capabilities
SendCommandAndCheck("AT+CPAS\r", "waiting response"); // Mobile equipment activity status
SendCommandAndCheck("AT+CGCLASS?\r", "waiting response"); // GPRS mobile class
SendCommandAndCheck("AT+CGATT?\r", "waiting response"); // MT attachment status
SendCommandAndCheck("AT+CSCA?\r", "waiting response"); // SMSC number
// Let's check to see if we have a SMSC number set
iCheck = SendCommandAndCheck("AT+CSCA?\r", "+CSCA: ");
if (iCheck < 0) {
wprintf(L"[ERROR] SMSC found...\n");
return FALSE;
}
if (iCheck == 0) {
wprintf(L"[ERROR] Error checking for carrier\n");
return FALSE;
}
wprintf(L"[INFO] SMSC number correctly set\n");
return TRUE;
}
BOOL WapPush::CheckCOM(PWCHAR pwPort) {
INT iCheck;
if (SetPort(pwPort) == FALSE)
return FALSE;
if (m_bCOMOpen)
return TRUE;
iCheck = SendCommandAndCheck("AT\r", "OK\r");
if (iCheck == 0) {
wprintf(L"[ERROR] Cannot send command to GSM modem\n");
return FALSE;
}
if (iCheck < 0) {
wprintf(L"[ERROR] AT interface is not ready\n");
return FALSE;
}
wprintf(L"[CHECK] AT interface is ready\n");
return TRUE;
}
INT WapPush::SendCommandAndCheck(PCHAR pcCommand, PCHAR pcCheck) {
#define READBUF_SIZE 1024
INT iWritten = 0, iRead = 0, iCommLen, iCheckLen;
BYTE *pBuff = NULL;
if (m_bCOMOpen == FALSE) {
if (Open() == FALSE)
return FALSE;
}
if (pcCommand == NULL || pcCheck == NULL) {
wprintf(L"[ERROR] Command or Check incorrectly set\n");
return FALSE;
}
iCommLen = strlen(pcCommand);
iCheckLen = strlen(pcCheck);
if (iCommLen == 0 || iCheckLen == 0) {
wprintf(L"[ERROR] Command or Check cannot have 0 length\n");
return FALSE;
}
iWritten = serialObj.Write((PBYTE)pcCommand, iCommLen);
if (iWritten < 0) {
wprintf(L"[ERROR] Command not sent\n");
return FALSE;
}
pBuff = new(std::nothrow) BYTE[READBUF_SIZE];
if (pBuff == NULL) {
wprintf(L"[ERROR] Cannot allocate memory for receiving buffer\n");
return FALSE;
}
ZeroMemory(pBuff, READBUF_SIZE);
iRead = serialObj.Read(pBuff, READBUF_SIZE);
if (iRead < 0) {
wprintf(L"[ERROR] Cannot read response\n");
delete[] pBuff;
return FALSE;
}
pBuff[READBUF_SIZE - 1] = 0;
// Checking response
if (strstr((PCHAR)pBuff, pcCheck) == NULL) {
wprintf(L"[WARNING] Response received: %S\n", pBuff);
delete[] pBuff;
return -1;
}
delete[] pBuff;
return TRUE;
}
string WapPush::SendCommandAndGet(PCHAR pcCommand) {
#define READBUF_SIZE 1024
INT iWritten = 0, iRead = 0, iCommLen;
BYTE *pBuff = NULL;
string response = "";
if (m_bCOMOpen == FALSE) {
if (Open() == FALSE)
return response;
}
if (pcCommand == NULL) {
wprintf(L"[ERROR] Command or Check incorrectly set\n");
return response;
}
iCommLen = strlen(pcCommand);
if (iCommLen == 0) {
wprintf(L"[ERROR] Command or Check cannot have 0 length\n");
return response;
}
iWritten = serialObj.Write((PBYTE)pcCommand, iCommLen);
if (iWritten < 0) {
wprintf(L"[ERROR] Command not sent\n");
return response;
}
pBuff = new(std::nothrow) BYTE[READBUF_SIZE];
if (pBuff == NULL) {
wprintf(L"[ERROR] Cannot allocate memory for receiving buffer\n");
return response;
}
ZeroMemory(pBuff, READBUF_SIZE);
iRead = serialObj.Read(pBuff, READBUF_SIZE);
if (iRead < 0) {
wprintf(L"[ERROR] Cannot read response\n");
delete[] pBuff;
return response;
}
pBuff[READBUF_SIZE - 1] = 0;
response = (CHAR *)pBuff;
delete[] pBuff;
return response;
}
INT WapPush::SendCommand(PCHAR pcCommand) {
INT iWritten = 0, iCommLen;
if (m_bCOMOpen == FALSE) {
if (Open() == FALSE)
return FALSE;
}
if (pcCommand == NULL) {
wprintf(L"[ERROR] Command or Check incorrectly set\n");
return FALSE;
}
iCommLen = strlen(pcCommand);
if (iCommLen == 0) {
wprintf(L"[ERROR] Command or Check cannot have 0 length\n");
return FALSE;
}
iWritten = serialObj.Write((PBYTE)pcCommand, iCommLen);
if (iWritten < 0) {
wprintf(L"[ERROR] Command not sent\n");
return FALSE;
}
return TRUE;
}