Commit 2283ec95 authored by Rob Swindell's avatar Rob Swindell 💬
Browse files

Add "Caller ID" support, enabled with AT#CID=1 or AT+VCID=1

Also controlled via [modem] CallerID key in svdm.ini fiile.
Reports the connected IP address between the first and second RING result.
Required a fix to reset the ringcount to 0 upon new connection.

Simplified the AT command parsing logic a bit.
parent ccb4d7dd
......@@ -122,7 +122,6 @@ void usage(const char* progname)
exit(EXIT_SUCCESS);
}
const char* supported_cmds = "ADEHIMOQSVXZ&";
const char* string_cmds = "D";
#define MAX_SAVES 20
struct modem {
......@@ -141,6 +140,7 @@ struct modem {
bool numeric_mode;
bool offhook;
bool online; // false means "command mode"
bool caller_id;
bool ringing;
ulong ringcount;
ulong auto_answer;
......@@ -214,17 +214,27 @@ const char* response_str[] = {
"CONNECT 9600"
};
char* response(struct modem* modem, enum modem_response code)
char* verbal_response(struct modem* modem, const char* response)
{
static char str[128];
safe_snprintf(str, sizeof(str), "%c%c%s%c%c", modem->cr, modem->lf, response, modem->cr, modem->lf);
return str;
}
char* numeric_response(struct modem* modem, int code)
{
static char str[128];
safe_snprintf(str, sizeof(str), "%u%c", code, modem->cr);
return str;
}
char* response(struct modem* modem, enum modem_response code)
{
if(modem->quiet)
return "";
if(modem->numeric_mode)
safe_snprintf(str, sizeof(str), "%u%c", code, modem->cr);
else
safe_snprintf(str, sizeof(str), "%c%c%s%c%c", modem->cr, modem->lf, response_str[code], modem->cr, modem->lf);
return str;
return numeric_response(modem, code);
return verbal_response(modem, response_str[code]);
}
char* ok(struct modem* modem)
......@@ -288,6 +298,7 @@ const char* iniKeyESC = "ESC";
const char* iniKeyExtResults = "ExtResults";
const char* iniKeyDialWait = "DialWait";
const char* iniKeyGuardTime = "GuardTime";
const char* iniKeyCallerID = "CallerID";
void init(struct modem* modem)
{
......@@ -297,6 +308,7 @@ void init(struct modem* modem)
modem->echo_off = !iniGetBool(ini, section, iniKeyEcho, TRUE);
modem->quiet = iniGetBool(ini, section, iniKeyQuiet, FALSE);
modem->numeric_mode = iniGetBool(ini, section, iniKeyNumeric, FALSE);
modem->caller_id = iniGetBool(ini, section, iniKeyCallerID, FALSE);
modem->cr = (char)iniGetInteger(ini, section, iniKeyCR, '\r');
modem->lf = (char)iniGetInteger(ini, section, iniKeyLF, '\n');
modem->bs = (char)iniGetInteger(ini, section, iniKeyBS, '\b');
......@@ -315,6 +327,7 @@ bool write_cfg(struct modem* modem)
iniSetBool(&ini, section, iniKeyEcho, !modem->echo_off, style);
iniSetBool(&ini, section, iniKeyQuiet, modem->quiet, style);
iniSetBool(&ini, section, iniKeyNumeric, modem->numeric_mode, style);
iniSetBool(&ini, section, iniKeyCallerID, modem->caller_id, style);
iniSetInteger(&ini, section, iniKeyCR, modem->cr, style);
iniSetInteger(&ini, section, iniKeyLF, modem->lf, style);
iniSetInteger(&ini, section, iniKeyBS, modem->bs, style);
......@@ -718,12 +731,9 @@ char* atmodem_exec(struct modem* modem)
for(char* p = modem->buf; *p != '\0';) {
char ch = toupper(*p);
p++;
if(strchr(supported_cmds, ch) == NULL)
return error(modem);
if(strchr(string_cmds, ch) == NULL) {
if(ch == '&') {
ch = toupper(*p);
ulong val = strtoul(p + 1, &p, 10); // unused
ulong val = strtoul(p + 1, &p, 10);
switch(ch) {
case 'W':
resp = write_cfg(modem) ? ok(modem) : error(modem);
......@@ -750,11 +760,41 @@ char* atmodem_exec(struct modem* modem)
}
continue;
}
// Caller ID control
if(ch == '#' || ch == '+') {
if(ch == '+' && toupper(*p) == 'V')
p++;
if(stricmp(p, "CID?") == 0) {
safe_snprintf(respbuf, sizeof(respbuf), "%c%u%c%c%s"
,modem->lf, modem->caller_id, modem->cr, modem->lf, ok(modem));
return respbuf;
}
if(stricmp(p, "CID=?") == 0) {
safe_snprintf(respbuf, sizeof(respbuf), "%c0,1%c%c%s"
,modem->lf, modem->cr, modem->lf, ok(modem));
return respbuf;
}
if(strnicmp(p, "CID=", 4) == 0) {
modem->caller_id = strtoul(p + 4, &p, 10);
continue;
}
return error(modem);
}
// Numeric argument commands
ulong val = strtoul(p, &p, 10);
ulong val = 0;
if(strchr(string_cmds, ch) == NULL)
val = strtoul(p, &p, 10);
switch(ch) {
case 'A':
return answer(modem);
case 'D':
if(sock != INVALID_SOCKET) {
dprintf("Can't dial: Already connected");
return error(modem);
}
if(*p == 'T' /* tone */|| *p == 'P' /* pulse */)
p++;
return dial(modem, p);
case 'E':
modem->echo_off = !val;
break;
......@@ -875,19 +915,9 @@ char* atmodem_exec(struct modem* modem)
case 'Z':
init(modem);
break;
}
} else { // string argument commands
switch(ch) {
case 'D':
if(sock != INVALID_SOCKET) {
dprintf("Can't dial: Already connected");
default:
return error(modem);
}
if(*p == 'T' /* tone */|| *p == 'P' /* pulse */)
p++;
return dial(modem, p);
}
}
}
return resp;
}
......@@ -988,8 +1018,10 @@ void listen_thread(void* arg)
}
sock = newsock;
addr = newaddr;
if(!modem->offhook && !modem->online)
if(!modem->offhook && !modem->online) {
modem->ringing = true;
modem->ringcount = 0;
}
}
}
}
......@@ -1324,6 +1356,11 @@ int main(int argc, char** argv)
vdd_writestr(&wrslot, response(&modem, RING));
lastring = now;
modem.ringcount++;
if(modem.ringcount == 1 && modem.caller_id) {
char str[256];
SAFEPRINTF(str, "NMBR = %s", inet_addrtop(&addr, tmp, sizeof(tmp)));
vdd_writestr(&wrslot, verbal_response(&modem, str));
}
if(modem.auto_answer > 0 && modem.ringcount >= modem.auto_answer) {
vdd_writestr(&wrslot, answer(&modem));
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment