summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Wedhorn <voip@facts.com.au>2013-01-25 05:49:54 +0000
committerDamien Wedhorn <voip@facts.com.au>2013-01-25 05:49:54 +0000
commite9446501c9176b6c05b4a59f88090250b7f04fea (patch)
treecc19c255f6e63f69a52612eb539eae19d5542c00
parent14a9fb761b9aa543d889af89c75026d41a23c787 (diff)
Add force dial keys to skinny.
Adds a dial softkey when the device is in DAFD. The softkey is greyed (unusable) until a possible dialplan match is entered. Code includes updating transmit_selectsoftkeys to allow the use of a button mask. Also add option to use # or * as a dial now button. Original patch by snuffy cleaned up by myself. Review: https://reviewboard.asterisk.org/r/2277/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@380057 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_skinny.c128
-rw-r--r--configs/skinny.conf.sample8
2 files changed, 108 insertions, 28 deletions
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 570bf2877..6a8b36483 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -202,6 +202,7 @@ static int keep_alive = 120;
static int auth_timeout = DEFAULT_AUTH_TIMEOUT;
static int auth_limit = DEFAULT_AUTH_LIMIT;
static int unauth_sessions = 0;
+static char immed_dialchar = '\0';
static char vmexten[AST_MAX_EXTENSION]; /* Voicemail pilot number */
static char used_context[AST_MAX_EXTENSION]; /* placeholder to check if context are already used in regcontext */
static char regcontext[AST_MAX_CONTEXT]; /* Context for auto-extension */
@@ -718,6 +719,31 @@ struct bksp_req_message {
#define SOFTKEY_GPICKUP 0x12
#define SOFTKEY_DND 0x13
#define SOFTKEY_IDIVERT 0x14
+#define SOFTKEY_FORCEDIAL 0x15
+
+#define KEYMASK_ALL 0xFFFFFFFF
+#define KEYMASK_NONE (1 << 0)
+#define KEYMASK_REDIAL (1 << 1)
+#define KEYMASK_NEWCALL (1 << 2)
+#define KEYMASK_HOLD (1 << 3)
+#define KEYMASK_TRNSFER (1 << 4)
+#define KEYMASK_CFWDALL (1 << 5)
+#define KEYMASK_CFWDBUSY (1 << 6)
+#define KEYMASK_CFWDNOANSWER (1 << 7)
+#define KEYMASK_BKSPC (1 << 8)
+#define KEYMASK_ENDCALL (1 << 9)
+#define KEYMASK_RESUME (1 << 10)
+#define KEYMASK_ANSWER (1 << 11)
+#define KEYMASK_INFO (1 << 12)
+#define KEYMASK_CONFRN (1 << 13)
+#define KEYMASK_PARK (1 << 14)
+#define KEYMASK_JOIN (1 << 15)
+#define KEYMASK_MEETME (1 << 16)
+#define KEYMASK_PICKUP (1 << 17)
+#define KEYMASK_GPICKUP (1 << 18)
+#define KEYMASK_DND (1 << 29)
+#define KEYMASK_IDIVERT (1 << 20)
+#define KEYMASK_FORCEDIAL (1 << 21)
static struct soft_key_template_definition soft_key_template_default[] = {
{ "\200\001", SOFTKEY_REDIAL },
@@ -740,6 +766,7 @@ static struct soft_key_template_definition soft_key_template_default[] = {
{ "\200\022", SOFTKEY_GPICKUP },
{ "\200\077", SOFTKEY_DND },
{ "\200\120", SOFTKEY_IDIVERT },
+ { "Dial", SOFTKEY_FORCEDIAL},
};
/* Localized message "codes" (in octal)
@@ -934,6 +961,7 @@ static const uint8_t soft_key_default_connwithtrans[] = {
static const uint8_t soft_key_default_dadfd[] = {
SOFTKEY_BKSPC,
SOFTKEY_ENDCALL,
+ SOFTKEY_FORCEDIAL,
};
static const uint8_t soft_key_default_connwithconf[] = {
@@ -2468,20 +2496,44 @@ static void transmit_stop_tone(struct skinny_device *d, int instance, int refere
transmit_response(d, req);
}
-static void transmit_selectsoftkeys(struct skinny_device *d, int instance, int callid, int softkey)
+static int keyset_translatebitmask(int keyset, int intmask)
+{
+ int extmask = 0;
+ int x, y;
+ const struct soft_key_definitions *softkeymode = soft_key_default_definitions;
+
+ for(x = 0; x < ARRAY_LEN(soft_key_default_definitions); x++) {
+ if (softkeymode[x].mode == keyset) {
+ const uint8_t *defaults = softkeymode[x].defaults;
+
+ for (y = 0; y < softkeymode[x].count; y++) {
+ if (intmask & (1 << (defaults[y]))) {
+ extmask |= (1 << ((y)));
+ }
+ }
+ break;
+ }
+ }
+
+ return extmask;
+}
+
+static void transmit_selectsoftkeys(struct skinny_device *d, int instance, int callid, int softkey, int mask)
{
struct skinny_req *req;
+ int newmask;
if (!(req = req_alloc(sizeof(struct select_soft_keys_message), SELECT_SOFT_KEYS_MESSAGE)))
return;
+ newmask = keyset_translatebitmask(softkey, mask);
req->data.selectsoftkey.instance = htolel(instance);
req->data.selectsoftkey.reference = htolel(callid);
req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
- req->data.selectsoftkey.validKeyMask = htolel(0xFFFFFFFF);
+ req->data.selectsoftkey.validKeyMask = htolel(newmask);
- SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting SELECT_SOFT_KEYS_MESSAGE to %s, inst %d, callid %d, softkey %d, mask 0xFFFFFFFF\n",
- d->name, instance, callid, softkey);
+ SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting SELECT_SOFT_KEYS_MESSAGE to %s, inst %d, callid %d, softkey %d, mask 0x%08x\n",
+ d->name, instance, callid, softkey, newmask);
transmit_response(d, req);
}
@@ -2864,6 +2916,7 @@ static void transmit_softkeysetres(struct skinny_device *d)
int i;
int x;
int y;
+ int keydefcount;
const struct soft_key_definitions *softkeymode = soft_key_default_definitions;
if (!(req = req_alloc(sizeof(struct soft_key_set_res_message), SOFT_KEY_SET_RES_MESSAGE)))
@@ -2871,10 +2924,11 @@ static void transmit_softkeysetres(struct skinny_device *d)
SKINNY_DEBUG(DEBUG_TEMPLATE, 3, "Creating Softkey Template\n");
+ keydefcount = ARRAY_LEN(soft_key_default_definitions);
req->data.softkeysets.softKeySetOffset = htolel(0);
- req->data.softkeysets.softKeySetCount = htolel(13);
- req->data.softkeysets.totalSoftKeySetCount = htolel(13);
- for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
+ req->data.softkeysets.softKeySetCount = htolel(keydefcount);
+ req->data.softkeysets.totalSoftKeySetCount = htolel(keydefcount);
+ for (x = 0; x < keydefcount; x++) {
const uint8_t *defaults = softkeymode->defaults;
/* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
This will have to do for now. */
@@ -2899,6 +2953,7 @@ static void transmit_softkeysetres(struct skinny_device *d)
static void transmit_softkeytemplateres(struct skinny_device *d)
{
struct skinny_req *req;
+
if (!(req = req_alloc(sizeof(struct soft_key_template_res_message), SOFT_KEY_TEMPLATE_RES_MESSAGE)))
return;
@@ -3070,11 +3125,11 @@ static int skinny_extensionstate_cb(char *context, char *exten, struct ast_state
case AST_EXTENSION_INUSE:
if (subline->sub && (subline->sub->substate == SKINNY_CONNECTED)) { /* Device has a real call */
transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED);
- transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED, KEYMASK_ALL);
transmit_displaypromptstatus(d, "Connected", 0, l->instance, subline->callid);
} else { /* Some other device has active call */
transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
- transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, KEYMASK_ALL);
transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
}
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
@@ -3083,14 +3138,14 @@ static int skinny_extensionstate_cb(char *context, char *exten, struct ast_state
break;
case AST_EXTENSION_ONHOLD:
transmit_callstate(d, l->instance, subline->callid, SKINNY_HOLD);
- transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLAHOLD);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLAHOLD, KEYMASK_ALL);
transmit_displaypromptstatus(d, "Hold", 0, l->instance, subline->callid);
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
transmit_activatecallplane(d, l);
break;
case AST_EXTENSION_NOT_INUSE:
transmit_callstate(d, l->instance, subline->callid, SKINNY_ONHOOK);
- transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_ONHOOK);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_ONHOOK, KEYMASK_ALL);
transmit_clearpromptmessage(d, l->instance, subline->callid);
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
transmit_activatecallplane(d, l);
@@ -4327,7 +4382,7 @@ static void skinny_dialer(struct skinny_subchannel *sub, int timedout)
struct skinny_device *d = l->device;
if (timedout || !ast_matchmore_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
- SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Force dialing '%s'\n", sub->callid, sub->exten);
+ SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Force dialing '%s' because of %s\n", sub->callid, sub->exten, (timedout ? "timeout" : "exactmatch"));
if (ast_exists_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
if (sub->substate == SUBSTATE_OFFHOOK) {
dialandactivatesub(sub, sub->exten);
@@ -4342,6 +4397,7 @@ static void skinny_dialer(struct skinny_subchannel *sub, int timedout)
} else {
SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Wait for more digits\n", sub->callid);
if (ast_exists_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_DADFD, KEYMASK_ALL);
sub->dialer_sched = skinny_sched_add(matchdigittimeout, skinny_dialer_cb, sub);
} else {
sub->dialer_sched = skinny_sched_add(gendigittimeout, skinny_dialer_cb, sub);
@@ -5075,7 +5131,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
if (subline->callid) {
transmit_stop_tone(d, l->instance, sub->callid);
transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
- transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, KEYMASK_ALL);
transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
}
@@ -5090,7 +5146,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
case SUBSTATE_CONNECTED:
transmit_activatecallplane(d, l);
transmit_stop_tone(d, l->instance, sub->callid);
- transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED, KEYMASK_ALL);
transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED);
if (!sub->rtp) {
start_rtp(sub);
@@ -5117,7 +5173,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
transmit_stopmediatransmission(d, sub);
transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
- transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, KEYMASK_ALL);
transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
sub->substate = SUBSTATE_HOLD;
@@ -5156,7 +5212,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
transmit_activatecallplane(d, l);
transmit_clear_display_message(d, l->instance, sub->callid);
transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK, KEYMASK_ALL);
transmit_displaypromptstatus(d, "Enter number", 0, l->instance, sub->callid);
sub->substate = SUBSTATE_OFFHOOK;
@@ -5214,7 +5270,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
transmit_stop_tone(d, l->instance, sub->callid);
transmit_clear_display_message(d, l->instance, sub->callid);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT, KEYMASK_ALL);
transmit_displaypromptstatus(d, "Dialing", 0, l->instance, sub->callid);
}
@@ -5261,7 +5317,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
break;
case SUBSTATE_RINGIN:
transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN, KEYMASK_ALL);
transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
send_callinfo(sub);
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
@@ -5281,7 +5337,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
case SUBSTATE_CALLWAIT:
transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
transmit_callstate(d, l->instance, sub->callid, SKINNY_CALLWAIT);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN, KEYMASK_ALL);
transmit_displaypromptstatus(d, "Callwaiting", 0, l->instance, sub->callid);
send_callinfo(sub);
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
@@ -5305,7 +5361,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
send_callinfo(sub);
transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED);
transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED, KEYMASK_ALL);
if (!sub->rtp) {
start_rtp(sub);
}
@@ -5384,7 +5440,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
transmit_callstate(d, l->instance, sub->callid, SKINNY_HOLD);
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD, KEYMASK_ALL);
sub->substate = SUBSTATE_HOLD;
break;
default:
@@ -5598,7 +5654,7 @@ static int handle_callforward_button(struct skinny_subchannel *sub, int cfwdtype
transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
transmit_clearpromptmessage(d, l->instance, sub->callid);
transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
- transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
+ transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK, KEYMASK_ALL);
transmit_activatecallplane(d, l);
transmit_displaynotify(d, "CFwd disabled", 10);
if (sub->owner && ast_channel_state(sub->owner) != AST_STATE_UP) {
@@ -5664,19 +5720,19 @@ static int handle_keypad_button_message(struct skinny_req *req, struct skinnyses
}
if ((sub->owner && ast_channel_state(sub->owner) < AST_STATE_UP)) {
- if (sub->dialer_sched && !skinny_sched_del(sub->dialer_sched, sub)) {
+ if (sub->dialer_sched && !skinny_sched_del(sub->dialer_sched, sub)) {
SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Got a digit and not timed out, so try dialing\n", sub->callid);
sub->dialer_sched = 0;
len = strlen(sub->exten);
if (len == 0) {
transmit_stop_tone(d, l->instance, sub->callid);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_DADFD);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_DADFD, KEYMASK_ALL&~KEYMASK_FORCEDIAL);
}
- if (len < sizeof(sub->exten) - 1) {
+ if (len < sizeof(sub->exten) - 1 && dgt != immed_dialchar) {
sub->exten[len] = dgt;
sub->exten[len + 1] = '\0';
}
- if (len == sizeof(sub->exten) - 1) {
+ if (len == sizeof(sub->exten) - 1 || dgt == immed_dialchar) {
skinny_dialer(sub, 1);
} else {
skinny_dialer(sub, 0);
@@ -6555,7 +6611,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
sub->exten[len-1] = '\0';
if (len == 1) {
transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK, KEYMASK_ALL);
}
transmit_backspace(d, l->instance, sub->callid);
}
@@ -6702,6 +6758,12 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
ast_channel_unref(c);
}
break;
+ case SOFTKEY_FORCEDIAL:
+ SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_FORCEDIAL from %s, inst %d, callref %d\n",
+ d->name, instance, callreference);
+ skinny_dialer(sub, 1);
+
+ break;
default:
SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_UNKNOWN(%d) from %s, inst %d, callref %d\n",
event, d->name, instance, callreference);
@@ -6814,7 +6876,7 @@ static int handle_message(struct skinny_req *req, struct skinnysession *s)
case SOFT_KEY_SET_REQ_MESSAGE:
SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFT_KEY_SET_REQ_MESSAGE from %s\n", d->name);
transmit_softkeysetres(d);
- transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
+ transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK, KEYMASK_ALL);
break;
case SOFT_KEY_EVENT_MESSAGE:
/* SKINNY_PACKETDEBUG handled in handle_soft_key_event_message */
@@ -7220,6 +7282,16 @@ static void config_parse_variables(int type, void *item, struct ast_variable *vp
} else if (!strcasecmp(v->name, "vmexten")) {
ast_copy_string(vmexten, v->value, sizeof(vmexten));
continue;
+ } else if (!strcasecmp(v->name, "immeddialkey")) {
+ if (!strcmp(v->value,"#")) {
+ immed_dialchar = '#';
+ } else if (!strcmp(v->value,"*")) {
+ immed_dialchar = '*';
+ } else {
+ ast_log(LOG_WARNING, "Invalid immeddialkey '%s' at line %d, only # or * accepted. Immeddial key disabled\n", v->value, v->lineno);
+ }
+
+ continue;
} else if (!strcasecmp(v->name, "dateformat")) {
memcpy(date_format, v->value, sizeof(date_format));
continue;
diff --git a/configs/skinny.conf.sample b/configs/skinny.conf.sample
index d40823ef7..ba8b2d649 100644
--- a/configs/skinny.conf.sample
+++ b/configs/skinny.conf.sample
@@ -38,6 +38,14 @@ keepalive=120
; for framing options
;disallow=
+; The imeddialkey option allows for a key to be used to immediately dial the already
+; entered number. This is useful where the dialplan includes variable length pattern
+; matching. Valid options are '#' and '*'. On devices with soft buttons, a button will
+; be available to immediately dial when a pattern than can be dialed has been entered.
+; Default is unset, that is no immediated dial key (softbutton still exists).
+;
+;immeddialkey='#'
+
; See https://wiki.asterisk.org/wiki/display/AST/IP+Quality+of+Service for a description of these parameters.
;tos=cs3 ; Sets TOS for signaling packets.
;tos_audio=ef ; Sets TOS for RTP audio packets.