Index: channels/chan_skinny.c =================================================================== --- channels/chan_skinny.c (revision 89318) +++ channels/chan_skinny.c (working copy) @@ -421,6 +421,7 @@ #define STIMULUS_LINE 0x09 #define STIMULUS_VOICEMAIL 0x0F #define STIMULUS_AUTOANSWER 0x11 +#define STIMULUS_DND 0x3F #define STIMULUS_CONFERENCE 0x7D #define STIMULUS_CALLPARK 0x7E #define STIMULUS_CALLPICKUP 0x7F @@ -550,6 +551,8 @@ #define SOFTKEY_MEETME 0x10 #define SOFTKEY_PICKUP 0x11 #define SOFTKEY_GPICKUP 0x12 +#define SOFTKEY_DND 0x13 +#define SOFTKEY_IDIVERT 0x14 struct soft_key_template_definition soft_key_template_default[] = { { "\200\001", SOFTKEY_REDIAL }, @@ -570,6 +573,8 @@ { "\200\020", SOFTKEY_MEETME }, { "\200\021", SOFTKEY_PICKUP }, { "\200\022", SOFTKEY_GPICKUP }, + { "\200\077", SOFTKEY_DND }, + { "\200\120", SOFTKEY_IDIVERT }, }; /* Localized message "codes" (in octal) @@ -716,6 +721,7 @@ SOFTKEY_REDIAL, SOFTKEY_NEWCALL, SOFTKEY_CFWDALL, + SOFTKEY_DND, SOFTKEY_CFWDBUSY, SOFTKEY_GPICKUP, SOFTKEY_CONFRN, @@ -1136,6 +1142,7 @@ int threewaycalling; int mwiblink; int cancallforward; + int getforward; int callreturn; int dnd; /* How does this affect callwait? Do we just deny a skinny_request if we're dnd? */ int hascallerid; @@ -2920,6 +2927,7 @@ l->pickupgroup = cur_pickupgroup; l->callreturn = callreturn; l->cancallforward = cancallforward; + l->getforward = 0; l->callwaiting = callwaiting; l->transfer = transfer; l->threewaycalling = threewaycalling; @@ -3030,7 +3038,6 @@ int len = 0; int timeout = firstdigittimeout; int res = 0; - int getforward=0; int loop_pause = 100; ast_verb(3, "Starting simple switch on '%s@%s'\n", l->name, d->name); @@ -3057,22 +3064,23 @@ } if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) { if (!res || !ast_matchmore_extension(c, c->context, d->exten, 1, l->cid_num)) { - if (getforward) { + if (l->getforward) { /* Record this as the forwarding extension */ ast_copy_string(l->call_forward, d->exten, sizeof(l->call_forward)); ast_verb(3, "Setting call forward to '%s' on channel %s\n", l->call_forward, c->name); transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); - if (res) { - break; - } ast_safe_sleep(c, 500); ast_indicate(c, -1); ast_safe_sleep(c, 1000); memset(d->exten, 0, sizeof(d->exten)); - transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); len = 0; - getforward = 0; + l->getforward = 0; + if (sub->owner && sub->owner->_state != AST_STATE_UP) { + ast_indicate(c, -1); + ast_hangup(c); + } + return NULL; } else { ast_copy_string(c->exten, d->exten, sizeof(c->exten)); ast_copy_string(l->lastnumberdialed, d->exten, sizeof(l->lastnumberdialed)); @@ -3702,6 +3710,46 @@ return res; } +static int handle_callforward_button(struct skinny_subchannel *sub) +{ + struct skinny_line *l = sub->parent; + struct skinny_device *d = l->parent; + struct skinnysession *s = d->session; + struct ast_channel *c = sub->owner; + pthread_t t; + + if (l->hookstate == SKINNY_ONHOOK) { + l->hookstate = SKINNY_OFFHOOK; + transmit_speaker_mode(s, SKINNY_SPEAKERON); + transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); + } + if (skinnydebug) + ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name); + transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */ + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); + transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT); + + if (!ast_strlen_zero(l->call_forward)){ + ast_verb(3, "Disabling CFwdAll on %s@%s\n", l->name, d->name); + memset(l->call_forward, 0, sizeof(l->call_forward)); + ast_safe_sleep(c, 500); + transmit_speaker_mode(s, SKINNY_SPEAKEROFF); + transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid); + if (sub->owner && sub->owner->_state != AST_STATE_UP) { + ast_indicate(c, -1); + ast_hangup(c); + } + } else { + l->getforward = 1; + if (ast_pthread_create(&t, NULL, skinny_ss, c)) { + if (!ast_strlen_zero(l->call_forward)){ + ast_verb(3, "Enabling CFwdAll on %s@%s\n", l->name, d->name); + transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF); + } + } + } + return 0; +} static int handle_ip_port_message(struct skinny_req *req, struct skinnysession *s) { /* no response necessary */ @@ -3969,11 +4017,9 @@ ast_verbose("Received Stimulus: Park Call(%d/%d)\n", instance, callreference); /* XXX Park the call */ break; - case STIMULUS_FORWARDALL: + case STIMULUS_DND: /* Need to find the DND softkey */ if (skinnydebug) - ast_verbose("Received Stimulus: Forward All(%d/%d)\n", instance, callreference); - /* Why is DND under FORWARDALL? */ - /* Because it's the same thing. */ + ast_verbose("Received Stimulus: DND (%d/%d)\n", instance, callreference); /* Do not disturb */ if (l->dnd != 0){ @@ -3988,6 +4034,23 @@ transmit_displaynotify(s, "DnD enabled", 10); } break; + case STIMULUS_FORWARDALL: + if (skinnydebug) + ast_verbose("Received Stimulus: Forward All(%d/%d)\n", instance, callreference); + + if (!sub || !sub->owner) { + c = skinny_new(l, AST_STATE_DOWN); + } else { + c = sub->owner; + } + + if (!c) { + ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name); + } else { + sub = c->tech_pvt; + handle_callforward_button(sub); + } + break; case STIMULUS_FORWARDBUSY: if (skinnydebug) ast_verbose("Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference); @@ -4791,7 +4854,7 @@ ast_verbose("Received Softkey Event: Transfer(%d/%d)\n", instance, callreference); /* XXX figure out how to transfer */ break; - case SOFTKEY_CFWDALL: + case SOFTKEY_DND: if (skinnydebug) ast_verbose("Received Softkey Event: Forward All(%d/%d)\n", instance, callreference); @@ -4808,6 +4871,23 @@ transmit_displaynotify(s, "DnD enabled", 10); } break; + case SOFTKEY_CFWDALL: + if (skinnydebug) + ast_verbose("Received Softkey Event: Forward All(%d/%d)\n", instance, callreference); + + if (!sub || !sub->owner) { + c = skinny_new(l, AST_STATE_DOWN); + } else { + c = sub->owner; + } + + if (!c) { + ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name); + } else { + sub = c->tech_pvt; + handle_callforward_button(sub); + } + break; case SOFTKEY_CFWDBUSY: if (skinnydebug) ast_verbose("Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);