aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_dect.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_dect.c')
-rw-r--r--channels/chan_dect.c330
1 files changed, 159 insertions, 171 deletions
diff --git a/channels/chan_dect.c b/channels/chan_dect.c
index d870f785d..737074ef5 100644
--- a/channels/chan_dect.c
+++ b/channels/chan_dect.c
@@ -74,6 +74,7 @@ struct dect_pt {
AST_LIST_ENTRY(dect_pt) list;
char name[64];
char fullname[64];
+ char ipei[DECT_IPEI_STRING_LEN + 1];
struct dect_ipui ipui;
struct dect_tpui tpui;
@@ -257,6 +258,118 @@ static struct dect_pt *dect_pt_get_by_ipui(const struct dect_ipui *ipui)
return NULL;
}
+static struct dect_pt *dect_init_portable(const char *name)
+{
+ struct dect_pt *pt;
+
+ pt = ast_calloc(1, sizeof(*pt));
+ if (pt == NULL)
+ return NULL;
+
+ if (name != NULL) {
+ ast_copy_string(pt->name, name, sizeof(pt->name));
+ snprintf(pt->fullname, sizeof(pt->fullname), "DECT/%s", pt->name);
+ }
+
+ ast_string_field_init(pt, 512);
+ ast_string_field_set(pt, context, dect_cfg.context);
+ ast_string_field_set(pt, regexten, "");
+ ast_string_field_set(pt, language, dect_cfg.language);
+ ast_string_field_set(pt, cid_num, "");
+ ast_string_field_set(pt, cid_name, "");
+ ast_string_field_set(pt, ring_pattern, "0");
+
+ AST_LIST_INSERT_TAIL(&dect_pt_list, pt, list);
+ return pt;
+}
+
+static int dect_alloc_extension(unsigned int *exten)
+{
+ const struct dect_pt *pt;
+ uint32_t bitmap[1024];
+ unsigned int pext;
+
+ memset(bitmap, 0, sizeof(bitmap));
+ AST_LIST_TRAVERSE(&dect_pt_list, pt, list) {
+ pext = strtoul(pt->regexten, NULL, 0);
+ if (pext < dect_cfg.regexten_base ||
+ pext >= 8 * sizeof(bitmap))
+ continue;
+ pext -= dect_cfg.regexten_base;
+
+ bitmap[pext / 32] |= 1 << (pext % 32);
+ }
+
+ for (pext = 0; pext < 8 * sizeof(bitmap); pext++) {
+ if (!(bitmap[pext / 32] & (1 << (pext % 32)))) {
+ *exten = dect_cfg.regexten_base + pext;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void dect_register_extension(const struct dect_pt *pt, bool onoff)
+{
+ struct pbx_find_info q = { .stacklen = 0 };
+ char *ext, *extenp, *context;
+ char exten[256];
+
+ if (ast_strlen_zero(dect_cfg.regcontext))
+ return;
+
+ ast_copy_string(exten, S_OR(pt->regexten, pt->name), sizeof(exten));
+ extenp = exten;
+ while ((ext = strsep(&extenp, "&")) != NULL) {
+ context = strchr(ext, '@');
+ if (context != NULL) {
+ *context++ = '\0';
+ if (!ast_context_find(context)) {
+ ast_log(LOG_WARNING, "Context %s for PT %s does not exist",
+ context, pt->name);
+ continue;
+ }
+ } else
+ context = dect_cfg.regcontext;
+
+ if (onoff) {
+ if (!ast_exists_extension(NULL, context, ext, 1, NULL)) {
+ ast_add_extension(context, 1, ext, 1, NULL, NULL, "Dial",
+ (char *)pt->fullname, NULL, "DECT");
+ }
+ } else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1,
+ NULL, "", E_MATCH)) {
+ ast_context_remove_extension(context, ext, 1, NULL);
+ }
+ }
+}
+
+static void dect_init_tpui(struct dect_tpui *tpui, unsigned int exten)
+{
+ tpui->ia.digits[0] = exten > 10000 ? exten / 10000 % 10 : 0xb;
+ tpui->ia.digits[1] = exten > 1000 ? exten / 1000 % 10 : 0xb;
+ tpui->ia.digits[2] = exten > 100 ? exten / 100 % 10 : 0xb;
+ tpui->ia.digits[3] = exten > 10 ? exten / 10 % 10 : 0xb;
+ tpui->ia.digits[4] = exten > 1 ? exten / 1 % 10 : 0xb;
+}
+
+static void dect_pt_set_extension(struct dect_pt *pt, unsigned int exten)
+{
+ ast_string_field_build(pt, cid_num, "%u", exten);
+ ast_string_field_build(pt, regexten, "%u", exten);
+ dect_init_tpui(&pt->tpui, exten);
+}
+
+static void dect_pt_set_ipui(struct dect_pt *pt, const struct dect_ipui *ipui)
+{
+ pt->ipui = *ipui;
+ dect_format_ipei_string(&ipui->pun.n.ipei, pt->ipei);
+}
+
+/*
+ * Database functions
+ */
static uint64_t dect_parse_num(const char *str)
{
uint64_t num;
@@ -274,14 +387,14 @@ static void dect_parse_base64(const char *str, uint8_t *dst, unsigned int size)
static void dect_db_remove(const struct dect_pt *pt)
{
- ast_db_deltree("dect", pt->name);
+ ast_db_deltree("dect", pt->ipei);
}
static int dect_db_put(const struct dect_pt *pt, const char *key, const char *value)
{
char ptkey[256];
- snprintf(ptkey, sizeof(ptkey), "%s/%s", pt->name, key);
+ snprintf(ptkey, sizeof(ptkey), "%s/%s", pt->ipei, key);
return ast_db_put("dect", ptkey, value);
}
@@ -343,7 +456,8 @@ static int dect_db_parse_codec_list(struct dect_pt *pt, const char *key,
if (tmp == NULL)
return -1;
strncpy(num, tmp + 1, sizeof(num));
- sscanf(num, "%u", &i);
+ if (sscanf(num, "%u", &i) != 1)
+ return -1;
if (!strncmp(key, "codec_", strlen("codec_")))
cl->entry[i].codec = dect_parse_num(val);
@@ -360,7 +474,7 @@ static int dect_db_parse_codec_list(struct dect_pt *pt, const char *key,
static void dect_db_store_codec_list(const struct dect_pt *pt)
{
- struct dect_ie_codec_list *cl = pt->codec_list;
+ const struct dect_ie_codec_list *cl = pt->codec_list;
unsigned int i;
for (i = 0; i < cl->num; i++) {
@@ -374,44 +488,44 @@ static void dect_db_store_codec_list(const struct dect_pt *pt)
static int dect_db_parse_termcap(struct dect_pt *pt, const char *key,
const char *val)
{
- struct dect_ie_terminal_capability *tcap;
+ struct dect_ie_terminal_capability *tc;
if (strncmp(key, "capabilities/", strlen("capabilities/")))
return -1;
key += strlen("capabilities/");
- tcap = pt->terminal_capability;
- if (tcap == NULL) {
- pt->terminal_capability = (void *)dect_ie_alloc(dh, sizeof(*tcap));
- tcap = pt->terminal_capability;
+ tc = pt->terminal_capability;
+ if (tc == NULL) {
+ pt->terminal_capability = (void *)dect_ie_alloc(dh, sizeof(*tc));
+ tc = pt->terminal_capability;
}
if (!strcmp(key, "tone_capabilities"))
- tcap->tone = dect_parse_num(val);
+ tc->tone = dect_parse_num(val);
else if (!strcmp(key, "echo_parameters"))
- tcap->echo = dect_parse_num(val);
+ tc->echo = dect_parse_num(val);
else if (!strcmp(key, "noise_rejection"))
- tcap->noise_rejection = dect_parse_num(val);
+ tc->noise_rejection = dect_parse_num(val);
else if (!strcmp(key, "volume_ctrl"))
- tcap->volume_ctrl = dect_parse_num(val);
+ tc->volume_ctrl = dect_parse_num(val);
else if (!strcmp(key, "slot_capabilities"))
- tcap->slot = dect_parse_num(val);
+ tc->slot = dect_parse_num(val);
else if (!strcmp(key, "display_capabilities"))
- tcap->display = dect_parse_num(val);
+ tc->display = dect_parse_num(val);
else if (!strcmp(key, "display_memory"))
- tcap->display_memory = dect_parse_num(val);
+ tc->display_memory = dect_parse_num(val);
else if (!strcmp(key, "display_lines"))
- tcap->display_lines = dect_parse_num(val);
+ tc->display_lines = dect_parse_num(val);
else if (!strcmp(key, "display_columns"))
- tcap->display_columns = dect_parse_num(val);
+ tc->display_columns = dect_parse_num(val);
else if (!strcmp(key, "display_control"))
- tcap->display_control = dect_parse_num(val);
+ tc->display_control = dect_parse_num(val);
else if (!strcmp(key, "display_charsets"))
- tcap->display_charsets = dect_parse_num(val);
+ tc->display_charsets = dect_parse_num(val);
else if (!strcmp(key, "scrolling"))
- tcap->scrolling = dect_parse_num(val);
+ tc->scrolling = dect_parse_num(val);
else if (!strcmp(key, "profile_indicator"))
- tcap->profile_indicator = dect_parse_num(val);
+ tc->profile_indicator = dect_parse_num(val);
else
return -1;
return 0;
@@ -419,7 +533,7 @@ static int dect_db_parse_termcap(struct dect_pt *pt, const char *key,
static void dect_db_store_termcap(const struct dect_pt *pt)
{
- struct dect_ie_terminal_capability *tc = pt->terminal_capability;
+ const struct dect_ie_terminal_capability *tc = pt->terminal_capability;
dect_db_put_num(pt, "capabilities/tone_capabilities", tc->tone);
dect_db_put_num(pt, "capabilities/echo_parameters", tc->echo);
@@ -439,12 +553,11 @@ static void dect_db_store_termcap(const struct dect_pt *pt)
static int dect_db_parse_global(struct dect_pt *pt, const char *key,
const char *val)
{
- if (!strcmp(key, "ipei")) {
- if (!dect_parse_ipei_string(&pt->ipui.pun.n.ipei, val))
- return -1;
- pt->ipui.put = DECT_IPUI_N;
+ if (!strcmp(key, "name")) {
+ ast_copy_string(pt->name, val, sizeof(pt->name));
+ snprintf(pt->fullname, sizeof(pt->fullname), "DECT/%s", pt->name);
} else if (!strcmp(key, "regexten"))
- ast_string_field_set(pt, regexten, val);
+ dect_pt_set_extension(pt, strtoul(val, NULL, 0));
else if (!strcmp(key, "context"))
ast_string_field_set(pt, context, val);
else if (!strcmp(key, "language"))
@@ -464,10 +577,7 @@ static int dect_db_parse_global(struct dect_pt *pt, const char *key,
static void dect_db_store_portable(const struct dect_pt *pt)
{
- char buf[DECT_IPEI_STRING_LEN + 1];
-
- dect_format_ipei_string(&pt->ipui.pun.n.ipei, buf);
- dect_db_put(pt, "ipei", buf);
+ dect_db_put(pt, "name", pt->name);
dect_db_put(pt, "regexten", pt->regexten);
dect_db_put(pt, "context", pt->context);
dect_db_put(pt, "language", pt->language);
@@ -477,121 +587,6 @@ static void dect_db_store_portable(const struct dect_pt *pt)
dect_db_put_base64(pt, "uak", pt->uak, sizeof(pt->uak));
}
-static void dect_init_tpui(struct dect_tpui *tpui, unsigned int exten)
-{
- tpui->ia.digits[0] = exten > 10000 ? exten / 10000 % 10 : 0xb;
- tpui->ia.digits[1] = exten > 1000 ? exten / 1000 % 10 : 0xb;
- tpui->ia.digits[2] = exten > 100 ? exten / 100 % 10 : 0xb;
- tpui->ia.digits[3] = exten > 10 ? exten / 10 % 10 : 0xb;
- tpui->ia.digits[4] = exten > 1 ? exten / 1 % 10 : 0xb;
-}
-
-static struct dect_pt *dect_init_portable(const char *name,
- const struct ast_variable *v)
-{
- struct dect_pt *pt;
-
- pt = ast_calloc(1, sizeof(*pt));
- if (pt == NULL)
- return NULL;
- ast_copy_string(pt->name, name, sizeof(pt->name));
- snprintf(pt->fullname, sizeof(pt->fullname), "DECT/%s", pt->name);
-
- ast_string_field_init(pt, 512);
- ast_string_field_set(pt, context, dect_cfg.context);
- ast_string_field_set(pt, regexten, "");
- ast_string_field_set(pt, language, dect_cfg.language);
- ast_string_field_set(pt, cid_num, "");
- ast_string_field_set(pt, cid_name, "");
- ast_string_field_set(pt, ring_pattern, "0");
- pt->ipui.put = DECT_IPUI_N;
-
- for (; v != NULL; v = v->next) {
- if (!strcasecmp(v->name, "emc")) {
- pt->ipui.pun.n.ipei.emc = strtoul(v->value, NULL, 16);
- } else if (!strcasecmp(v->name, "psn")) {
- pt->ipui.pun.n.ipei.psn = strtoul(v->value, NULL, 16);
- } else if (!strcasecmp(v->name, "context")) {
- ast_string_field_set(pt, context, v->value);
- } else if (!strcasecmp(v->name, "regexten")) {
- ast_string_field_set(pt, regexten, v->value);
- } else if (!strcasecmp(v->name, "language")) {
- ast_string_field_set(pt, language, v->value);
- } else if (!strcasecmp(v->name, "cid_number")) {
- ast_string_field_set(pt, cid_num, v->value);
- } else if (!strcasecmp(v->name, "cid_name")) {
- ast_string_field_set(pt, cid_name, v->value);
- } else if (!strcasecmp(v->name, "ring_pattern")) {
- ast_string_field_set(pt, ring_pattern, v->value);
- }
- }
-
- AST_LIST_INSERT_TAIL(&dect_pt_list, pt, list);
- return pt;
-}
-
-static int dect_alloc_extension(unsigned int *exten)
-{
- const struct dect_pt *pt;
- uint32_t bitmap[1024];
- unsigned int pext;
-
- memset(bitmap, 0, sizeof(bitmap));
- AST_LIST_TRAVERSE(&dect_pt_list, pt, list) {
- pext = strtoul(pt->regexten, NULL, 0);
- if (pext < dect_cfg.regexten_base ||
- pext >= 8 * sizeof(bitmap))
- continue;
- pext -= dect_cfg.regexten_base;
-
- bitmap[pext / 32] |= 1 << (pext % 32);
- }
-
- for (pext = 0; pext < 8 * sizeof(bitmap); pext++) {
- if (!(bitmap[pext / 32] & (1 << (pext % 32)))) {
- *exten = dect_cfg.regexten_base + pext;
- return 1;
- }
- }
-
- return 0;
-}
-
-static void dect_register_extension(const struct dect_pt *pt, bool onoff)
-{
- struct pbx_find_info q = { .stacklen = 0 };
- char *ext, *extenp, *context;
- char exten[256];
-
- if (ast_strlen_zero(dect_cfg.regcontext))
- return;
-
- ast_copy_string(exten, S_OR(pt->regexten, pt->name), sizeof(exten));
- extenp = exten;
- while ((ext = strsep(&extenp, "&")) != NULL) {
- context = strchr(ext, '@');
- if (context != NULL) {
- *context++ = '\0';
- if (!ast_context_find(context)) {
- ast_log(LOG_WARNING, "Context %s for PT %s does not exist",
- context, pt->name);
- continue;
- }
- } else
- context = dect_cfg.regcontext;
-
- if (onoff) {
- if (!ast_exists_extension(NULL, context, ext, 1, NULL)) {
- ast_add_extension(context, 1, ext, 1, NULL, NULL, "Dial",
- (char *)pt->fullname, NULL, "DECT");
- }
- } else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1,
- NULL, "", E_MATCH)) {
- ast_context_remove_extension(context, ext, 1, NULL);
- }
- }
-}
-
static int dect_init_call(struct dect_pvt *pvt, enum ast_channel_state state,
const char *exten)
{
@@ -1499,17 +1494,14 @@ static void dect_mm_access_rights_auth_cfm(struct dect_pvt *pvt, bool success,
}
snprintf(name, sizeof(name), "DECT-PT-%u", exten);
- pt = dect_init_portable(name, NULL);
+ pt = dect_init_portable(name);
if (pt == NULL) {
dect_mm_access_rights_reject(mme, DECT_REJECT_INSUFFICIENT_MEMORY);
return;
}
- ast_string_field_build(pt, cid_num, "%u", exten);
- ast_string_field_build(pt, regexten, "%u", exten);
-
- memcpy(&pt->ipui, &param->portable_identity->ipui, sizeof(pt->ipui));
- dect_init_tpui(&pt->tpui, exten);
+ dect_pt_set_ipui(pt, &param->portable_identity->ipui);
+ dect_pt_set_extension(pt, exten);
}
if (dect_mm_access_rights_res(dh, mme, true, &reply) < 0)
@@ -1792,16 +1784,6 @@ static int dect_load_config(void)
}
}
- /* Phone configuration */
- cat = NULL;
- while ((cat = ast_category_browse(cfg, cat)) != NULL) {
- if (!strcasecmp(cat, "general"))
- continue;
- pt = dect_init_portable(cat, ast_variable_browse(cfg, cat));
- if (pt == NULL)
- return AST_MODULE_LOAD_DECLINE;
- dect_register_extension(pt, true);
- }
return 0;
}
@@ -1879,7 +1861,6 @@ static char *dect_cli_show_portable(struct ast_cli_entry *e, int cmd,
{
struct dect_pt *pt;
char cidbuf[256], codbuf[256];
- char ipeibuf[DECT_IPEI_STRING_LEN + 1];
switch (cmd) {
case CLI_INIT:
@@ -1901,12 +1882,11 @@ static char *dect_cli_show_portable(struct ast_cli_entry *e, int cmd,
return CLI_FAILURE;
}
- dect_format_ipei_string(&pt->ipui.pun.n.ipei, ipeibuf);
ast_callerid_merge(cidbuf, sizeof(cidbuf), pt->cid_name, pt->cid_num,
"<unspecified>");
dect_codecs_merge(codbuf, sizeof(codbuf), pt);
- ast_cli(a->fd, "IPEI: %s\n", ipeibuf);
+ ast_cli(a->fd, "IPEI: %s\n", pt->ipei);
ast_cli(a->fd, "Extension: %s\n", pt->regexten);
ast_cli(a->fd, "Context: %s\n", pt->context);
ast_cli(a->fd, "Language: %s\n", pt->language);
@@ -2115,15 +2095,19 @@ static void dect_io_thread_stop(void)
static int dect_db_read(void)
{
struct ast_db_entry *dbt, *dbe;
+ struct dect_ipui ipui;
struct dect_pt *pt;
const char *key, *val;
- char *tmp, name[64];
+ char *tmp, ipei[64];
+
+ memset(&ipui, 0, sizeof(ipui));
+ ipui.put = DECT_IPUI_N;
dbt = ast_db_gettree("dect", NULL);
for (dbe = dbt; dbe != NULL; dbe = dbe->next) {
key = dbe->key + strlen("/dect/");
- strncpy(name, key, sizeof(name));
- tmp = strchr(name, '/');
+ strncpy(ipei, key, sizeof(ipei));
+ tmp = strchr(ipei, '/');
if (tmp == NULL)
continue;
@@ -2131,11 +2115,15 @@ static int dect_db_read(void)
key = tmp + 1;
val = dbe->data;
- pt = dect_pt_get_by_name(name);
+ if (!dect_parse_ipei_string(&ipui.pun.n.ipei, ipei))
+ continue;
+
+ pt = dect_pt_get_by_ipui(&ipui);
if (pt == NULL) {
- pt = dect_init_portable(name, NULL);
+ pt = dect_init_portable(NULL);
if (pt == NULL)
return -1;
+ dect_pt_set_ipui(pt, &ipui);
}
if (dect_db_parse_global(pt, key, val) != 0 &&