#include <osmocore/utils.h>
#include <osmocore/gsm48.h>
+#include <osmocore/talloc.h>
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/networks.h>
#include <osmocom/bb/mobile/gps.h>
#include <osmocom/vty/telnet_interface.h>
+void *l23_ctx;
+
int mncc_call(struct osmocom_ms *ms, char *number);
int mncc_hangup(struct osmocom_ms *ms);
int mncc_answer(struct osmocom_ms *ms);
int mncc_hold(struct osmocom_ms *ms);
int mncc_retrieve(struct osmocom_ms *ms, int number);
+int mncc_dtmf(struct osmocom_ms *ms, char *dtmf);
extern struct llist_head ms_list;
extern struct llist_head active_connections;
}
}
+int vty_check_number(struct vty *vty, const char *number)
+{
+ int i;
+
+ for (i = 0; i < strlen(number); i++) {
+ /* allow international notation with + */
+ if (i == 0 && number[i] == '+')
+ continue;
+ if (!(number[i] >= '0' && number[i] <= '9')
+ && number[i] != '*'
+ && number[i] != '#'
+ && !(number[i] >= 'a' && number[i] <= 'c')) {
+ vty_out(vty, "Invalid digit '%c' of number!%s",
+ number[i], VTY_NEWLINE);
+ return -EINVAL;
+ }
+ }
+ if (number[0] == '\0' || (number[0] == '+' && number[1] == '\0')) {
+ vty_out(vty, "Given number has no digits!%s", VTY_NEWLINE);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
int vty_reading = 0;
static void vty_restart(struct vty *vty)
else
vty_out(vty, " manual network selection: %s%s",
plmn_m_state_names[ms->plmn.state], VTY_NEWLINE);
- vty_out(vty, " cell selection: %s%s",
- cs_state_names[ms->cellsel.state], VTY_NEWLINE);
+ vty_out(vty, " cell selection: %s",
+ cs_state_names[ms->cellsel.state]);
+ if (ms->rrlayer.state == GSM48_RR_ST_IDLE && ms->cellsel.selected)
+ vty_out(vty, " (ARFCN %d)", ms->cellsel.sel_arfcn);
+ vty_out(vty, "%s", VTY_NEWLINE);
vty_out(vty, " radio ressource layer: %s%s",
gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE);
vty_out(vty, " mobility management layer: %s",
{
struct osmocom_ms *ms;
struct gsm_settings *set;
- int i;
+ struct gsm_settings_abbrev *abbrev;
+ char *number;
ms = get_ms(argv[0], vty);
if (!ms)
return CMD_WARNING;
}
- if (!strcmp(argv[1], "emergency"))
- mncc_call(ms, (char *)argv[1]);
- else switch (argv[1][0]) {
- case 'a':
+ number = (char *)argv[1];
+ if (!strcmp(number, "emergency"))
+ mncc_call(ms, number);
+ else if (!strcmp(number, "answer"))
mncc_answer(ms);
- break;
- case 'h':
- if (argv[1][1] == 'a')
- mncc_hangup(ms);
- else
- mncc_hold(ms);
- break;
- default:
- for (i = 0; i < strlen(argv[1]); i++) {
- /* allow international notation with + */
- if (i == 0 && argv[1][i] == '+')
- continue;
- if (!(argv[1][i] >= '0' && argv[1][i] <= '9')
- && argv[1][i] != '*'
- && argv[1][i] != '#'
- && !(argv[1][i] >= 'a' && argv[1][i] <= 'c')) {
- vty_out(vty, "Invalid digit '%c'%s", argv[1][i],
+ else if (!strcmp(number, "hangup"))
+ mncc_hangup(ms);
+ else if (!strcmp(number, "hold"))
+ mncc_hold(ms);
+ else {
+ llist_for_each_entry(abbrev, &set->abbrev, list) {
+ if (!strcmp(number, abbrev->abbrev)) {
+ number = abbrev->number;
+ vty_out(vty, "Dialing number '%s'%s", number,
VTY_NEWLINE);
- return CMD_WARNING;
+ break;
}
}
- mncc_call(ms, (char *)argv[1]);
+ if (vty_check_number(vty, number))
+ return CMD_WARNING;
+ mncc_call(ms, number);
}
return CMD_SUCCESS;
return CMD_SUCCESS;
}
+DEFUN(call_dtmf, call_dtmf_cmd, "call MS_NAME dtmf DIGITS",
+ "Make a call\nName of MS (see \"show ms\")\n"
+ "One or more DTMF digits to transmit")
+{
+ struct osmocom_ms *ms;
+ struct gsm_settings *set;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+ set = &ms->settings;
+
+ if (!set->cc_dtmf) {
+ vty_out(vty, "DTMF not supported, please enable!%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ mncc_dtmf(ms, (char *)argv[1]);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(network_show, network_show_cmd, "network show MS_NAME",
"Network ...\nShow results of network search (again)\n"
"Name of MS (see \"show ms\")")
{
struct gsm_settings *set = &ms->settings;
struct gsm_support *sup = &ms->support;
+ struct gsm_settings_abbrev *abbrev;
vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE);
switch(set->sim_type) {
else
vty_out(vty, " no codec half-speed%s", VTY_NEWLINE);
}
+ if (llist_empty(&set->abbrev))
+ vty_out(vty, " no abbrev%s", VTY_NEWLINE);
+ else {
+ llist_for_each_entry(abbrev, &set->abbrev, list)
+ vty_out(vty, " abbrev %s %s%s%s%s", abbrev->abbrev,
+ abbrev->number, (abbrev->name[0]) ? " " : "",
+ abbrev->name, VTY_NEWLINE);
+ }
vty_out(vty, " support%s", VTY_NEWLINE);
SUP_WRITE(sms_ptp, "sms");
SUP_WRITE(a5_1, "a5/1");
return CMD_SUCCESS;
}
+DEFUN(cfg_abbrev, cfg_ms_abbrev_cmd, "abbrev ABBREVIATION NUMBER [name]",
+ "Store given abbreviation number\n1-3 digits abbreviation\n"
+ "Number to store for the abbreviation "
+ "(Use digits '0123456789*#abc', and '+' to dial international)\n"
+ "Name of the abbreviation")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+ struct gsm_settings_abbrev *abbrev;
+ int i;
+
+ llist_for_each_entry(abbrev, &set->abbrev, list) {
+ if (!strcmp(argv[0], abbrev->abbrev)) {
+ vty_out(vty, "Given abbreviation '%s' already stored, "
+ "delete first!%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ if (strlen(argv[0]) >= sizeof(abbrev->abbrev)) {
+ vty_out(vty, "Given abbreviation too long%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ for (i = 0; i < strlen(argv[0]); i++) {
+ if (argv[0][i] < '0' || argv[0][i] > '9') {
+ vty_out(vty, "Given abbreviation must have digits "
+ "0..9 only!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ if (vty_check_number(vty, argv[1]))
+ return CMD_WARNING;
+
+ abbrev = talloc_zero(l23_ctx, struct gsm_settings_abbrev);
+ if (!abbrev) {
+ vty_out(vty, "No Memory!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ llist_add_tail(&abbrev->list, &set->abbrev);
+ strncpy(abbrev->abbrev, argv[0], sizeof(abbrev->abbrev) - 1);
+ strncpy(abbrev->number, argv[1], sizeof(abbrev->number) - 1);
+ if (argc >= 3)
+ strncpy(abbrev->name, argv[2], sizeof(abbrev->name) - 1);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_abbrev, cfg_ms_no_abbrev_cmd, "no abbrev [abbreviation]",
+ NO_STR "Remove given abbreviation number or all numbers\n"
+ "Abbreviation number to remove")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+ struct gsm_settings_abbrev *abbrev, *abbrev2;
+ uint8_t deleted = 0;
+
+ llist_for_each_entry_safe(abbrev, abbrev2, &set->abbrev, list) {
+ if (argc < 1 || !strcmp(argv[0], abbrev->abbrev)) {
+ llist_del(&abbrev->list);
+ deleted = 1;
+ }
+ }
+
+ if (argc >= 1 && !deleted) {
+ vty_out(vty, "Given abbreviation '%s' not found!%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
static int config_write_dummy(struct vty *vty)
{
return CMD_SUCCESS;
return CMD_SUCCESS; \
}
+#define SET_EN(cfg, cfg_cmd, item, cmd, desc, restart) \
+DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
+{ \
+ struct osmocom_ms *ms = vty->index; \
+ struct gsm_settings *set = &ms->settings; \
+ if (restart) \
+ vty_restart(vty); \
+ set->item = 1; \
+ return CMD_SUCCESS; \
+}
+
+#define SET_DI(cfg, cfg_cmd, item, cmd, desc, restart) \
+DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
+{ \
+ struct osmocom_ms *ms = vty->index; \
+ struct gsm_settings *set = &ms->settings; \
+ if (restart) \
+ vty_restart(vty); \
+ set->item = 0; \
+ return CMD_SUCCESS; \
+}
+
+SET_EN(cfg_ms_sup_dtmf, cfg_ms_sup_dtmf_cmd, cc_dtmf, "dtmf", "DTMF", 0);
+SET_DI(cfg_ms_sup_no_dtmf, cfg_ms_sup_no_dtmf_cmd, cc_dtmf, "dtmf", "DTMF", 0);
SUP_EN(cfg_ms_sup_sms, cfg_ms_sup_sms_cmd, sms_ptp, "sms", "SMS", 0);
SUP_DI(cfg_ms_sup_no_sms, cfg_ms_sup_no_sms_cmd, sms_ptp, "sms", "SMS", 0);
SUP_EN(cfg_ms_sup_a5_1, cfg_ms_sup_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
install_element(ENABLE_NODE, &network_select_cmd);
install_element(ENABLE_NODE, &call_cmd);
install_element(ENABLE_NODE, &call_retr_cmd);
+ install_element(ENABLE_NODE, &call_dtmf_cmd);
install_element(CONFIG_NODE, &cfg_gps_device_cmd);
install_element(CONFIG_NODE, &cfg_gps_baud_cmd);
install_element(MS_NODE, &cfg_ms_codec_half_cmd);
install_element(MS_NODE, &cfg_ms_codec_half_pref_cmd);
install_element(MS_NODE, &cfg_ms_no_codec_half_cmd);
+ install_element(MS_NODE, &cfg_ms_abbrev_cmd);
+ install_element(MS_NODE, &cfg_ms_no_abbrev_cmd);
install_element(MS_NODE, &cfg_ms_testsim_cmd);
install_element(MS_NODE, &cfg_ms_support_cmd);
install_node(&support_node, config_write_dummy);
install_default(SUPPORT_NODE);
install_element(SUPPORT_NODE, &ournode_exit_cmd);
install_element(SUPPORT_NODE, &ournode_end_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_dtmf_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_no_dtmf_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_sms_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_no_sms_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_a5_1_cmd);