asterisk-chan-dongle/cli.c

896 lines
26 KiB
C
Raw Normal View History

2023-05-25 08:30:27 +00:00
/*
Copyright (C) 2009 - 2010
Artem Makhutov <artem@makhutov.org>
http://www.makhutov.org
Dmitry Vagin <dmitry2004@yandex.ru>
bg <bg_one@mail.ru>
*/
#include "ast_config.h"
#include <asterisk.h>
#include <asterisk/cli.h> /* struct ast_cli_entry; struct ast_cli_args */
#include <asterisk/callerid.h> /* ast_describe_caller_presentation() */
#include "ast_compat.h" /* asterisk compatibility fixes */
#include "cli.h"
#include "chan_dongle.h" /* devices */
#include "helpers.h" /* ITEMS_OF() send_ccwa_set() send_reset() send_sms() send_ussd() */
#include "pdiscovery.h" /* pdiscovery_list_begin() pdiscovery_list_next() pdiscovery_list_end() */
#include "error.h"
static const char * restate2str_msg(restate_time_t when);
static char* complete_device (const char* word, int state)
{
struct pvt* pvt;
char* res = NULL;
int which = 0;
int wordlen = strlen (word);
AST_RWLIST_RDLOCK (&gpublic->devices);
AST_RWLIST_TRAVERSE (&gpublic->devices, pvt, entry)
{
if (!strncasecmp (PVT_ID(pvt), word, wordlen) && ++which > state)
{
res = ast_strdup (PVT_ID(pvt));
break;
}
}
AST_RWLIST_UNLOCK (&gpublic->devices);
return res;
}
static char* cli_show_devices (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
struct pvt* pvt;
#define FORMAT1 "%-12.12s %-5.5s %-10.10s %-4.4s %-4.4s %-7.7s %-14.14s %-10.10s %-17.17s %-16.16s %-16.16s %-14.14s\n"
#define FORMAT2 "%-12.12s %-5d %-10.10s %-4d %-4d %-7d %-14.14s %-10.10s %-17.17s %-16.16s %-16.16s %-14.14s\n"
switch (cmd)
{
case CLI_INIT:
e->command = "dongle show devices";
e->usage = "Usage: dongle show devices\n"
" Shows the state of Dongle devices.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
{
return CLI_SHOWUSAGE;
}
ast_cli (a->fd, FORMAT1, "ID", "Group", "State", "RSSI", "Mode", "Submode", "Provider Name", "Model", "Firmware", "IMEI", "IMSI", "Number");
AST_RWLIST_RDLOCK (&gpublic->devices);
AST_RWLIST_TRAVERSE (&gpublic->devices, pvt, entry)
{
ast_mutex_lock (&pvt->lock);
ast_cli (a->fd, FORMAT2,
PVT_ID(pvt),
CONF_SHARED(pvt, group),
pvt_str_state(pvt),
pvt->rssi,
pvt->linkmode,
pvt->linksubmode,
pvt->provider_name,
pvt->model,
pvt->firmware,
pvt->imei,
pvt->imsi,
pvt->subscriber_number
);
ast_mutex_unlock (&pvt->lock);
}
AST_RWLIST_UNLOCK (&gpublic->devices);
#undef FORMAT1
#undef FORMAT2
return CLI_SUCCESS;
}
static char* cli_show_device_settings (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
struct pvt* pvt;
switch (cmd)
{
case CLI_INIT:
e->command = "dongle show device settings";
e->usage = "Usage: dongle show device settings <device>\n"
" Shows the settings of Dongle device.\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 4)
{
return complete_device (a->word, a->n);
}
return NULL;
}
if (a->argc != 5)
{
return CLI_SHOWUSAGE;
}
pvt = find_device (a->argv[4]);
if (pvt)
{
ast_cli (a->fd, "------------- Settings ------------\n");
ast_cli (a->fd, " Device : %s\n", PVT_ID(pvt));
ast_cli (a->fd, " Audio : %s\n", CONF_UNIQ(pvt, audio_tty));
ast_cli (a->fd, " Data : %s\n", CONF_UNIQ(pvt, data_tty));
ast_cli (a->fd, " IMEI : %s\n", CONF_UNIQ(pvt, imei));
ast_cli (a->fd, " IMSI : %s\n", CONF_UNIQ(pvt, imsi));
ast_cli (a->fd, " Channel Language : %s\n", CONF_SHARED(pvt, language));
ast_cli (a->fd, " Context : %s\n", CONF_SHARED(pvt, context));
ast_cli (a->fd, " Exten : %s\n", CONF_SHARED(pvt, exten));
ast_cli (a->fd, " Group : %d\n", CONF_SHARED(pvt, group));
ast_cli (a->fd, " RX gain : %d\n", CONF_SHARED(pvt, rxgain));
ast_cli (a->fd, " TX gain : %d\n", CONF_SHARED(pvt, txgain));
ast_cli (a->fd, " U2Diag : %d\n", CONF_SHARED(pvt, u2diag));
ast_cli (a->fd, " Use CallingPres : %s\n", CONF_SHARED(pvt, usecallingpres) ? "Yes" : "No");
ast_cli (a->fd, " Default CallingPres : %s\n", CONF_SHARED(pvt, callingpres) < 0 ? "<Not set>" : ast_describe_caller_presentation (CONF_SHARED(pvt, callingpres)));
ast_cli (a->fd, " Auto delete SMS : %s\n", CONF_SHARED(pvt, autodeletesms) ? "Yes" : "No");
ast_cli (a->fd, " Disable SMS : %s\n", CONF_SHARED(pvt, disablesms) ? "Yes" : "No");
ast_cli (a->fd, " Reset Dongle : %s\n", CONF_SHARED(pvt, resetdongle) ? "Yes" : "No");
ast_cli (a->fd, " Call Waiting : %s\n", dc_cw_setting2str(CONF_SHARED(pvt, callwaiting)));
ast_cli (a->fd, " DTMF : %s\n", dc_dtmf_setting2str(CONF_SHARED(pvt, dtmf)));
ast_cli (a->fd, " Minimal DTMF Gap : %d\n", CONF_SHARED(pvt, mindtmfgap));
ast_cli (a->fd, " Minimal DTMF Duration : %d\n", CONF_SHARED(pvt, mindtmfduration));
ast_cli (a->fd, " Minimal DTMF Interval : %d\n", CONF_SHARED(pvt, mindtmfinterval));
ast_cli (a->fd, " Initial device state : %s\n\n", dev_state2str(CONF_SHARED(pvt, initstate)));
ast_mutex_unlock (&pvt->lock);
}
else
{
ast_cli (a->fd, "Device %s not found\n", a->argv[4]);
}
return CLI_SUCCESS;
}
static char* cli_show_device_state (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
struct pvt* pvt;
struct ast_str * statebuf;
char buf[40];
switch (cmd)
{
case CLI_INIT:
e->command = "dongle show device state";
e->usage = "Usage: dongle show device state <device>\n"
" Shows the state of Dongle device.\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 4)
{
return complete_device (a->word, a->n);
}
return NULL;
}
if (a->argc != 5)
{
return CLI_SHOWUSAGE;
}
pvt = find_device (a->argv[4]);
if (pvt)
{
statebuf = pvt_str_state_ex(pvt);
ast_cli (a->fd, "-------------- Status -------------\n");
ast_cli (a->fd, " Device : %s\n", PVT_ID(pvt));
ast_cli (a->fd, " State : %s\n", ast_str_buffer(statebuf));
ast_cli (a->fd, " Audio : %s\n", PVT_STATE(pvt, audio_tty));
ast_cli (a->fd, " Data : %s\n", PVT_STATE(pvt, data_tty));
ast_cli (a->fd, " Voice : %s\n", (pvt->has_voice) ? "Yes" : "No");
ast_cli (a->fd, " SMS : %s\n", (pvt->has_sms) ? "Yes" : "No");
ast_cli (a->fd, " Manufacturer : %s\n", pvt->manufacturer);
ast_cli (a->fd, " Model : %s\n", pvt->model);
ast_cli (a->fd, " Firmware : %s\n", pvt->firmware);
ast_cli (a->fd, " IMEI : %s\n", pvt->imei);
ast_cli (a->fd, " IMSI : %s\n", pvt->imsi);
ast_cli (a->fd, " GSM Registration Status : %s\n", GSM_regstate2str(pvt->gsm_reg_status));
ast_cli (a->fd, " RSSI : %d, %s\n", pvt->rssi, rssi2dBm(pvt->rssi, buf, sizeof(buf)));
ast_cli (a->fd, " Mode : %s\n", sys_mode2str(pvt->linkmode));
ast_cli (a->fd, " Submode : %s\n", sys_submode2str(pvt->linksubmode));
ast_cli (a->fd, " Provider Name : %s\n", pvt->provider_name);
ast_cli (a->fd, " Location area code : %s\n", pvt->location_area_code);
ast_cli (a->fd, " Cell ID : %s\n", pvt->cell_id);
ast_cli (a->fd, " Subscriber Number : %s\n", pvt->subscriber_number);
ast_cli (a->fd, " SMS Service Center : %s\n", pvt->sms_scenter);
ast_cli (a->fd, " Tasks in queue : %u\n", PVT_STATE(pvt, at_tasks));
ast_cli (a->fd, " Commands in queue : %u\n", PVT_STATE(pvt, at_cmds));
ast_cli (a->fd, " Call Waiting : %s\n", pvt->has_call_waiting ? "Enabled" : "Disabled" );
ast_cli (a->fd, " Current device state : %s\n", dev_state2str(pvt->current_state) );
ast_cli (a->fd, " Desired device state : %s\n", dev_state2str(pvt->desired_state) );
ast_cli (a->fd, " When change state : %s\n", restate2str_msg(pvt->restart_time) );
ast_cli (a->fd, " Calls/Channels : %u\n", PVT_STATE(pvt, chansno));
ast_cli (a->fd, " Active : %u\n", PVT_STATE(pvt, chan_count[CALL_STATE_ACTIVE]));
ast_cli (a->fd, " Held : %u\n", PVT_STATE(pvt, chan_count[CALL_STATE_ONHOLD]));
ast_cli (a->fd, " Dialing : %u\n", PVT_STATE(pvt, chan_count[CALL_STATE_DIALING]));
ast_cli (a->fd, " Alerting : %u\n", PVT_STATE(pvt, chan_count[CALL_STATE_ALERTING]));
ast_cli (a->fd, " Incoming : %u\n", PVT_STATE(pvt, chan_count[CALL_STATE_INCOMING]));
ast_cli (a->fd, " Waiting : %u\n", PVT_STATE(pvt, chan_count[CALL_STATE_WAITING]));
ast_cli (a->fd, " Releasing : %u\n", PVT_STATE(pvt, chan_count[CALL_STATE_RELEASED]));
ast_cli (a->fd, " Initializing : %u\n\n", PVT_STATE(pvt, chan_count[CALL_STATE_INIT]));
/* TODO: show call waiting network setting and local config value */
ast_mutex_unlock (&pvt->lock);
ast_free(statebuf);
}
else
{
ast_cli (a->fd, "Device %s not found\n", a->argv[4]);
}
return CLI_SUCCESS;
}
#/* */
static int32_t getACD(uint32_t calls, uint32_t duration)
{
int32_t acd;
if(calls) {
acd = duration / calls;
} else {
acd = -1;
}
return acd;
}
#/* */
static int32_t getASR(uint32_t total, uint32_t handled)
{
int32_t asr;
if(total) {
asr = handled * 100 / total;
} else {
asr = -1;
}
return asr;
}
static char* cli_show_device_statistics (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
struct pvt * pvt;
switch (cmd)
{
case CLI_INIT:
e->command = "dongle show device statistics";
e->usage = "Usage: dongle show device statistics <device>\n"
" Shows the statistics of Dongle device.\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 4)
{
return complete_device (a->word, a->n);
}
return NULL;
}
if (a->argc != 5)
{
return CLI_SHOWUSAGE;
}
pvt = find_device (a->argv[4]);
if (pvt)
{
ast_cli (a->fd, "-------------- Statistics -------------\n");
ast_cli (a->fd, " Device : %s\n", PVT_ID(pvt));
ast_cli (a->fd, " Queue tasks : %u\n", PVT_STAT(pvt, at_tasks));
ast_cli (a->fd, " Queue commands : %u\n", PVT_STAT(pvt, at_cmds));
ast_cli (a->fd, " Responses : %u\n", PVT_STAT(pvt, at_responses));
ast_cli (a->fd, " Bytes of read responses : %u\n", PVT_STAT(pvt, d_read_bytes));
ast_cli (a->fd, " Bytes of written commands : %u\n", PVT_STAT(pvt, d_write_bytes));
ast_cli (a->fd, " Bytes of read audio : %llu\n", (unsigned long long int)PVT_STAT(pvt, a_read_bytes));
ast_cli (a->fd, " Bytes of written audio : %llu\n", (unsigned long long int)PVT_STAT(pvt, a_write_bytes));
ast_cli (a->fd, " Readed frames : %u\n", PVT_STAT(pvt, read_frames));
ast_cli (a->fd, " Readed short frames : %u\n", PVT_STAT(pvt, read_sframes));
ast_cli (a->fd, " Wrote frames : %u\n", PVT_STAT(pvt, write_frames));
ast_cli (a->fd, " Wrote short frames : %u\n", PVT_STAT(pvt, write_tframes));
ast_cli (a->fd, " Wrote silence frames : %u\n", PVT_STAT(pvt, write_sframes));
ast_cli (a->fd, " Write buffer overflow bytes : %llu\n", (unsigned long long int)PVT_STAT(pvt, write_rb_overflow_bytes));
ast_cli (a->fd, " Write buffer overflow count : %u\n", PVT_STAT(pvt, write_rb_overflow));
ast_cli (a->fd, " Incoming calls : %u\n", PVT_STAT(pvt, in_calls));
ast_cli (a->fd, " Waiting calls : %u\n", PVT_STAT(pvt, cw_calls));
ast_cli (a->fd, " Handled input calls : %u\n", PVT_STAT(pvt, in_calls_handled));
ast_cli (a->fd, " Fails to PBX run : %u\n", PVT_STAT(pvt, in_pbx_fails));
ast_cli (a->fd, " Attempts to outgoing calls : %u\n", PVT_STAT(pvt, out_calls));
ast_cli (a->fd, " Answered outgoing calls : %u\n", PVT_STAT(pvt, calls_answered[CALL_DIR_OUTGOING]));
ast_cli (a->fd, " Answered incoming calls : %u\n", PVT_STAT(pvt, calls_answered[CALL_DIR_INCOMING]));
ast_cli (a->fd, " Seconds of outgoing calls : %u\n", PVT_STAT(pvt, calls_duration[CALL_DIR_OUTGOING]));
ast_cli (a->fd, " Seconds of incoming calls : %u\n", PVT_STAT(pvt, calls_duration[CALL_DIR_INCOMING]));
ast_cli (a->fd, " ACD for incoming calls : %d\n", getACD(PVT_STAT(pvt, calls_answered[CALL_DIR_INCOMING]), PVT_STAT(pvt, calls_duration[CALL_DIR_INCOMING])));
ast_cli (a->fd, " ACD for outgoing calls : %d\n", getACD(PVT_STAT(pvt, calls_answered[CALL_DIR_OUTGOING]), PVT_STAT(pvt, calls_duration[CALL_DIR_OUTGOING])));
/*
ast_cli (a->fd, " ACD : %d\n",
getACD(
PVT_STAT(pvt, calls_answered[CALL_DIR_OUTGOING])
+ PVT_STAT(pvt, calls_answered[CALL_DIR_INCOMING]),
PVT_STAT(pvt, calls_duration[CALL_DIR_OUTGOING])
+ PVT_STAT(pvt, calls_duration[CALL_DIR_INCOMING])
)
);
*/
ast_cli (a->fd, " ASR for incoming calls : %d\n", getASR(PVT_STAT(pvt, in_calls) + PVT_STAT(pvt, cw_calls), PVT_STAT(pvt, calls_answered[CALL_DIR_INCOMING])) );
ast_cli (a->fd, " ASR for outgoing calls : %d\n\n", getASR(PVT_STAT(pvt, out_calls), PVT_STAT(pvt, calls_answered[CALL_DIR_OUTGOING])));
/*
ast_cli (a->fd, " ASR : %d\n\n",
getASR(
PVT_STAT(pvt, out_calls)
+ PVT_STAT(pvt, in_calls)
+ PVT_STAT(pvt, cw_calls),
PVT_STAT(pvt, calls_answered[CALL_DIR_OUTGOING])
+ PVT_STAT(pvt, calls_answered[CALL_DIR_INCOMING])
)
);
*/
ast_mutex_unlock (&pvt->lock);
}
else
{
ast_cli (a->fd, "Device %s not found\n", a->argv[4]);
}
return CLI_SUCCESS;
}
static char* cli_show_version (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
switch (cmd)
{
case CLI_INIT:
e->command = "dongle show version";
e->usage = "Usage: dongle show version\n"
" Shows the version of module.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
{
return CLI_SHOWUSAGE;
}
ast_cli (a->fd, "\n%s: %s, Version %s, Revision %s\nProject Home: %s\nBug Reporting: %s\n\n", AST_MODULE, MODULE_DESCRIPTION, MODULE_VERSION, PACKAGE_REVISION, MODULE_URL, MODULE_BUGREPORT);
return CLI_SUCCESS;
}
static char* cli_cmd (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
switch (cmd)
{
case CLI_INIT:
e->command = "dongle cmd";
e->usage = "Usage: dongle cmd <device> <command>\n"
" Send <command> to the rfcomm port on the device\n"
" with the specified <device>.\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 2)
{
return complete_device (a->word, a->n);
}
return NULL;
}
if (a->argc != 4)
{
return CLI_SHOWUSAGE;
}
int res = send_at_command(a->argv[2], a->argv[3]);
ast_cli (a->fd, "[%s] '%s' %s\n", a->argv[2], a->argv[3], res < 0 ? error2str(chan_dongle_err) : "AT command queued");
return CLI_SUCCESS;
}
static char* cli_ussd (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
switch (cmd)
{
case CLI_INIT:
e->command = "dongle ussd";
e->usage =
"Usage: dongle ussd <device> <command>\n"
" Send ussd <command> to the dongle\n"
" with the specified <device>.\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 2)
{
return complete_device (a->word, a->n);
}
return NULL;
}
if (a->argc != 4)
{
return CLI_SHOWUSAGE;
}
int res = send_ussd(a->argv[2], a->argv[3]);
ast_cli(a->fd, "[%s] %s\n", a->argv[2], res < 0 ? error2str(chan_dongle_err) : "USSD queued for send");
return CLI_SUCCESS;
}
static char* cli_sms (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
struct ast_str * buf;
int i;
switch (cmd)
{
case CLI_INIT:
e->command = "dongle sms";
e->usage =
"Usage: dongle sms <device> <number> <message>\n"
" Send a SMS to <number> with the <message> from <device>\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 2)
{
return complete_device (a->word, a->n);
}
return NULL;
}
if (a->argc < 5)
{
return CLI_SHOWUSAGE;
}
buf = ast_str_create (160 * 255);
for (i = 4; i < a->argc; i++)
{
if (i < (a->argc - 1))
{
ast_str_append (&buf, 0, "%s ", a->argv[i]);
}
else
{
ast_str_append (&buf, 0, "%s", a->argv[i]);
}
}
int res = send_sms(a->argv[2], a->argv[3], ast_str_buffer(buf), 0, "1", "UNKNOWN", 8);
ast_free (buf);
ast_cli(a->fd, "[%s] %s\n", a->argv[2], res < 0 ? error2str(chan_dongle_err) : "SMS queued for send");
return CLI_SUCCESS;
}
#if ASTERISK_VERSION_NUM >= 10800 /* 1.8+ */
typedef const char * const * ast_cli_complete2_t;
#else /* 1.8- */
typedef char * const * ast_cli_complete2_t;
#endif /* ^1.8- */
static char* cli_ccwa_set (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
static const char * const choices[] = { "enable", "disable", NULL };
call_waiting_t enable;
switch (cmd)
{
case CLI_INIT:
e->command = "dongle callwaiting";
e->usage =
"Usage: dongle callwaiting disable|enable <device>\n"
" Disable/Enable Call-Waiting on <device>\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 2)
{
return ast_cli_complete(a->word, (ast_cli_complete2_t)choices, a->n);
}
if (a->pos == 3)
{
return complete_device (a->word, a->n);
}
return NULL;
}
if (a->argc < 4)
{
return CLI_SHOWUSAGE;
}
if (strcasecmp("disable", a->argv[2]) == 0)
enable = CALL_WAITING_DISALLOWED;
else if (strcasecmp("enable", a->argv[2]) == 0)
enable = CALL_WAITING_ALLOWED;
else
return CLI_SHOWUSAGE;
int res = send_ccwa_set(a->argv[3], enable);
ast_cli(a->fd, "[%s] %s\n", a->argv[3], res < 0 ? error2str(chan_dongle_err) : "Call-Waiting commands queued for execute");
return CLI_SUCCESS;
}
static char* cli_reset (struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
switch (cmd)
{
case CLI_INIT:
e->command = "dongle reset";
e->usage =
"Usage: dongle reset <device>\n"
" Reset dongle <device>\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 2)
{
return complete_device (a->word, a->n);
}
return NULL;
}
if (a->argc != 3)
{
return CLI_SHOWUSAGE;
}
int res = send_reset(a->argv[2]);
ast_cli(a->fd, "[%s] %s\n", a->argv[2], res < 0 ? error2str(chan_dongle_err) : "Reset command queued for execute");
return CLI_SUCCESS;
}
static const char * const a_choices[] = { "now", "gracefully", "when", NULL };
static const char * const a_choices2[] = { "convenient", NULL };
static const char * restate2str_msg(restate_time_t when)
{
static const char * const choices[] = { "now", "gracefully", "when convenient" };
return enum2str(when, choices, ITEMS_OF(choices));
}
#/* */
static char* cli_restart_event(struct ast_cli_entry* e, int cmd, struct ast_cli_args* a, dev_state_t event)
{
static char * const cmds[] = {
"dongle stop",
"dongle restart",
"dongle remove",
};
static const char * const usage[] = {
"Usage: dongle stop < now | gracefully | when convenient > <device>\n"
" Stop dongle <device>\n",
"Usage: dongle restart < now | gracefully | when convenient > <device>\n"
" Restart dongle <device>\n",
"Usage: dongle remove < now | gracefully | when convenient > <device>\n"
" Remove dongle <device>\n",
};
const char * device = NULL;
int res;
int i;
switch (cmd)
{
case CLI_INIT:
e->command = cmds[event];
e->usage = usage[event];
return NULL;
case CLI_GENERATE:
switch(a->pos)
{
case 2:
return ast_cli_complete(a->word, (ast_cli_complete2_t)a_choices, a->n);
case 3:
if(strcasecmp(a->argv[2], "when") == 0)
return ast_cli_complete(a->word, (ast_cli_complete2_t)a_choices2, a->n);
return complete_device(a->word, a->n);
break;
case 4:
if(strcasecmp(a->argv[2], "when") == 0 && strcasecmp(a->argv[3], "convenient") == 0)
return complete_device(a->word, a->n);
}
return NULL;
}
if(a->argc != 4 && a->argc != 5)
{
return CLI_SHOWUSAGE;
}
for(i = 0; a_choices[i]; i++)
{
if(strcasecmp(a->argv[2], a_choices[i]) == 0)
{
if(i == RESTATE_TIME_CONVENIENT)
{
if(a->argc == 5 && strcasecmp(a->argv[3], a_choices2[0]) == 0)
{
device = a->argv[4];
}
}
else if(a->argc == 4)
{
device = a->argv[3];
}
if(device)
{
res = schedule_restart_event(event, i, device);
ast_cli(a->fd, "[%s] %s\n", device, res < 0 ? error2str(chan_dongle_err) : dev_state2str_msg(event));
return CLI_SUCCESS;
}
break;
}
}
return CLI_SHOWUSAGE;
}
#/* */
static char* cli_stop(struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
return cli_restart_event(e, cmd, a, DEV_STATE_STOPPED);
}
#/* */
static char* cli_restart(struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
return cli_restart_event(e, cmd, a, DEV_STATE_RESTARTED);
}
#/* */
static char * cli_remove(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
return cli_restart_event(e, cmd, a, DEV_STATE_REMOVED);
}
#/* */
static char* cli_start(struct ast_cli_entry* e, int cmd, struct ast_cli_args* a)
{
switch (cmd)
{
case CLI_INIT:
e->command = "dongle start";
e->usage = "Usage: dongle start <device>\n"
" Start dongle <device>\n";
return NULL;
case CLI_GENERATE:
if(a->pos == 2)
return complete_device(a->word, a->n);
return NULL;
}
if (a->argc != 3)
{
return CLI_SHOWUSAGE;
}
int res = schedule_restart_event(DEV_STATE_STARTED, RESTATE_TIME_NOW, a->argv[2]);
ast_cli(a->fd, "[%s] %s\n", a->argv[2], res < 0 ? error2str(chan_dongle_err) : dev_state2str_msg(DEV_STATE_STARTED));
return CLI_SUCCESS;
}
static char * cli_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int ok = 0;
int i;
switch (cmd)
{
case CLI_INIT:
e->command = "dongle reload";
e->usage = "Usage: dongle reload < now | gracefully | when convenient >\n"
" Reloads the chan_dongle configuration\n";
return NULL;
case CLI_GENERATE:
switch(a->pos)
{
case 2:
return ast_cli_complete(a->word, (ast_cli_complete2_t)a_choices, a->n);
case 3:
if(strcasecmp(a->argv[2], "when") == 0)
return ast_cli_complete(a->word, (ast_cli_complete2_t)a_choices2, a->n);
}
return NULL;
}
if (a->argc != 3 && a->argc != 4)
{
return CLI_SHOWUSAGE;
}
for(i = 0; a_choices[i]; i++)
{
if(strcasecmp(a->argv[2], a_choices[i]) == 0)
{
if(i == RESTATE_TIME_CONVENIENT)
{
if(a->argc == 4 && strcasecmp(a->argv[3], a_choices2[0]) == 0)
{
ok = 1;
}
}
else if(a->argc == 3)
{
ok = 1;
}
if(ok)
{
pvt_reload(i);
return CLI_SUCCESS;
}
break;
}
}
return CLI_SHOWUSAGE;
}
#/* */
static char * cli_discovery(struct ast_cli_entry * e, int cmd, struct ast_cli_args * a)
{
const struct pdiscovery_cache_item * item;
const struct pdiscovery_result * res;
struct pvt * pvt;
const char * imei;
const char * imsi;
int imeilen;
int imsilen;
switch (cmd) {
case CLI_INIT:
e->command = "dongle discovery";
e->usage = "Usage: dongle discovery\n"
" Discovery devices and create config\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 2) {
return CLI_SHOWUSAGE;
}
AST_RWLIST_RDLOCK(&gpublic->devices);
for(res = pdiscovery_list_begin(&item); res; res = pdiscovery_list_next(&item)) {
AST_RWLIST_TRAVERSE (&gpublic->devices, pvt, entry) {
if(strcmp(PVT_STATE(pvt, data_tty), res->ports.ports[INTERFACE_TYPE_DATA]) == 0) {
break;
}
}
if(pvt) {
/*
ast_cli(a->fd, "; existing device\n");
ast_cli(a->fd, "[%s](defaults)\n", PVT_ID(pvt));
if(CONF_UNIQ(pvt, audio_tty)[0])
ast_cli(a->fd, "audio=%s\n", CONF_UNIQ(pvt, audio_tty));
else
ast_cli(a->fd, ";audio=%s\n", PVT_STATE(pvt, audio_tty));
if(CONF_UNIQ(pvt, data_tty)[0])
ast_cli(a->fd, "data=%s\n", CONF_UNIQ(pvt, data_tty));
else
ast_cli(a->fd, ";data=%s\n", PVT_STATE(pvt, data_tty));
if(CONF_UNIQ(pvt, imei)[0])
ast_cli(a->fd, "imei=%s\n", CONF_UNIQ(pvt, imei));
else
ast_cli(a->fd, ";imei=%s\n", pvt->imei);
if(CONF_UNIQ(pvt, imsi)[0])
ast_cli(a->fd, "imsi=%s\n\n", CONF_UNIQ(pvt, imsi));
else
ast_cli(a->fd, ";imsi=%s\n\n", pvt->imsi);
*/
} else {
imei = S_OR(res->imei, "");
imsi = S_OR(res->imsi, "");
imeilen = strlen(imei);
imsilen = strlen(imsi);
ast_cli(a->fd, "; discovered device\n");
ast_cli(a->fd, "[dc_%s_%s](defaults)\n", imei + imeilen - MIN(imeilen,4), imsi + imsilen - MIN(imsilen,4));
ast_cli(a->fd, ";audio=%s\n", res->ports.ports[INTERFACE_TYPE_VOICE]);
ast_cli(a->fd, ";data=%s\n", res->ports.ports[INTERFACE_TYPE_DATA]);
ast_cli(a->fd, "imei=%s\n", imei);
ast_cli(a->fd, "imsi=%s\n\n", imsi);
}
}
pdiscovery_list_end();
AST_RWLIST_UNLOCK(&gpublic->devices);
return CLI_SUCCESS;
}
static struct ast_cli_entry cli[] = {
AST_CLI_DEFINE (cli_show_devices, "Show Dongle devices state"),
AST_CLI_DEFINE (cli_show_device_settings,"Show Dongle device settings"),
AST_CLI_DEFINE (cli_show_device_state, "Show Dongle device state"),
AST_CLI_DEFINE (cli_show_device_statistics,"Show Dongle device statistics"),
AST_CLI_DEFINE (cli_show_version, "Show module version"),
AST_CLI_DEFINE (cli_cmd, "Send commands to port for debugging"),
AST_CLI_DEFINE (cli_ussd, "Send USSD commands to the dongle"),
AST_CLI_DEFINE (cli_sms, "Send SMS from the dongle"),
AST_CLI_DEFINE (cli_ccwa_set, "Enable/Disable Call-Waiting on the dongle"),
AST_CLI_DEFINE (cli_reset, "Reset dongle now"),
AST_CLI_DEFINE (cli_stop, "Stop dongle"),
AST_CLI_DEFINE (cli_restart, "Restart dongle"),
AST_CLI_DEFINE (cli_remove, "Remove dongle"),
AST_CLI_DEFINE (cli_reload, "Reload dongle"),
AST_CLI_DEFINE (cli_start, "Start dongle"),
AST_CLI_DEFINE (cli_discovery, "Discovery devices and create config"),
};
#/* */
EXPORT_DEF void cli_register()
{
ast_cli_register_multiple (cli, ITEMS_OF(cli));
}
#/* */
EXPORT_DEF void cli_unregister()
{
ast_cli_unregister_multiple (cli, ITEMS_OF(cli));
}
/*
static char * ast_str_truncate2(struct ast_str *buf, ssize_t len)
{
if (len < 0) {
buf->__AST_STR_USED += ((ssize_t) abs(len)) > ((ssize_t) buf->__AST_STR_USED) ? (ssize_t)-buf->__AST_STR_USED : (ssize_t)len;
} else {
buf->__AST_STR_USED = len;
}
buf->__AST_STR_STR[buf->__AST_STR_USED] = '\0';
return buf->__AST_STR_STR;
}
*/