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
changes/78/78/1
Damien Wedhorn 13 years ago
parent 14a9fb761b
commit e9446501c9

@ -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);
}
@ -6701,6 +6757,12 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
setsubstate(sub, SUBSTATE_CONNECTED);
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",
@ -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 */
@ -7219,6 +7281,16 @@ static void config_parse_variables(int type, void *item, struct ast_variable *vp
continue;
} 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));

@ -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.

Loading…
Cancel
Save