|
|
|
@ -167,6 +167,12 @@ struct keypad_button_message {
|
|
|
|
|
uint32_t callReference;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define ENBLOC_CALL_MESSAGE 0x0004
|
|
|
|
|
struct enbloc_call_message {
|
|
|
|
|
char calledParty[24];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define STIMULUS_MESSAGE 0x0005
|
|
|
|
|
struct stimulus_message {
|
|
|
|
|
uint32_t stimulus;
|
|
|
|
@ -550,6 +556,7 @@ struct soft_key_definitions {
|
|
|
|
|
|
|
|
|
|
static const uint8_t soft_key_default_onhook[] = {
|
|
|
|
|
SOFTKEY_REDIAL,
|
|
|
|
|
SOFTKEY_NEWCALL,
|
|
|
|
|
SOFTKEY_CFWDALL,
|
|
|
|
|
SOFTKEY_CFWDBUSY,
|
|
|
|
|
SOFTKEY_GPICKUP,
|
|
|
|
@ -743,6 +750,7 @@ union skinny_data {
|
|
|
|
|
struct display_notify_message displaynotify;
|
|
|
|
|
struct dialed_number_message dialednumber;
|
|
|
|
|
struct soft_key_event_message softkeyeventmessage;
|
|
|
|
|
struct enbloc_call_message enbloccallmessage;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* packet composition */
|
|
|
|
@ -1685,16 +1693,27 @@ static void transmit_displaypromptstatus(struct skinnysession *s, const char *te
|
|
|
|
|
{
|
|
|
|
|
struct skinny_req *req;
|
|
|
|
|
|
|
|
|
|
if (!(req = req_alloc(sizeof(struct display_prompt_status_message), DISPLAY_PROMPT_STATUS_MESSAGE)))
|
|
|
|
|
return;
|
|
|
|
|
if (text == 0) {
|
|
|
|
|
if (!(req = req_alloc(sizeof(struct clear_prompt_message), CLEAR_PROMPT_MESSAGE)))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ast_copy_string(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage));
|
|
|
|
|
req->data.displaypromptstatus.messageTimeout = htolel(t);
|
|
|
|
|
req->data.displaypromptstatus.lineInstance = htolel(instance);
|
|
|
|
|
req->data.displaypromptstatus.callReference = htolel(callid);
|
|
|
|
|
req->data.clearpromptstatus.lineInstance = htolel(instance);
|
|
|
|
|
req->data.clearpromptstatus.callReference = htolel(callid);
|
|
|
|
|
|
|
|
|
|
if (skinnydebug)
|
|
|
|
|
ast_verbose("Displaying Prompt Status '%s'\n", text);
|
|
|
|
|
if (skinnydebug)
|
|
|
|
|
ast_verbose("Clearing Prompt\n");
|
|
|
|
|
} else {
|
|
|
|
|
if (!(req = req_alloc(sizeof(struct display_prompt_status_message), DISPLAY_PROMPT_STATUS_MESSAGE)))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ast_copy_string(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage));
|
|
|
|
|
req->data.displaypromptstatus.messageTimeout = htolel(t);
|
|
|
|
|
req->data.displaypromptstatus.lineInstance = htolel(instance);
|
|
|
|
|
req->data.displaypromptstatus.callReference = htolel(callid);
|
|
|
|
|
|
|
|
|
|
if (skinnydebug)
|
|
|
|
|
ast_verbose("Displaying Prompt Status '%s'\n", text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
transmit_response(s, req);
|
|
|
|
|
}
|
|
|
|
@ -3728,6 +3747,56 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int handle_enbloc_call_message(struct skinny_req *req, struct skinnysession *s)
|
|
|
|
|
{
|
|
|
|
|
struct skinny_device *d = s->device;
|
|
|
|
|
struct skinny_line *l;
|
|
|
|
|
struct skinny_subchannel *sub = NULL;
|
|
|
|
|
struct ast_channel *c;
|
|
|
|
|
pthread_t t;
|
|
|
|
|
|
|
|
|
|
if (skinnydebug)
|
|
|
|
|
ast_verbose("Received Enbloc Call: %s\n", req->data.enbloccallmessage.calledParty);
|
|
|
|
|
|
|
|
|
|
sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
|
|
|
|
|
|
|
|
|
|
if (!sub) {
|
|
|
|
|
l = find_line_by_instance(d, d->lastlineinstance);
|
|
|
|
|
if (!l) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
l = sub->parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = skinny_new(l, AST_STATE_DOWN);
|
|
|
|
|
|
|
|
|
|
if(!c) {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
|
|
|
|
|
} else {
|
|
|
|
|
l->hookstate = SKINNY_OFFHOOK;
|
|
|
|
|
|
|
|
|
|
sub = c->tech_pvt;
|
|
|
|
|
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); /* clear display */
|
|
|
|
|
transmit_tone(s, SKINNY_DIALTONE);
|
|
|
|
|
|
|
|
|
|
if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) {
|
|
|
|
|
transmit_tone(s, SKINNY_SILENCE);
|
|
|
|
|
}
|
|
|
|
|
ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten));
|
|
|
|
|
if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
|
|
|
|
|
ast_hangup(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int handle_soft_key_set_req_message(struct skinny_req *req, struct skinnysession *s)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
@ -3749,6 +3818,7 @@ static int handle_soft_key_set_req_message(struct skinny_req *req, struct skinny
|
|
|
|
|
for (i = 0; i < (sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition)); i++) {
|
|
|
|
|
if (defaults[y] == i+1) {
|
|
|
|
|
req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyTemplateIndex[y] = htolel(i+1);
|
|
|
|
|
req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyInfoIndex[y] = htolel(i+301);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3836,26 +3906,30 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
|
|
|
|
|
|
|
|
|
|
transmit_ringer_mode(s,SKINNY_RING_OFF);
|
|
|
|
|
transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
|
|
|
|
|
transmit_speaker_mode(s, SKINNY_SPEAKERON);
|
|
|
|
|
|
|
|
|
|
l->hookstate = SKINNY_OFFHOOK;
|
|
|
|
|
|
|
|
|
|
if (sub) {
|
|
|
|
|
ast_verbose("Uhoh, got NewCall with sub != 0\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = skinny_new(l, AST_STATE_DOWN);
|
|
|
|
|
|
|
|
|
|
if(c) {
|
|
|
|
|
sub = c->tech_pvt;
|
|
|
|
|
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); /* clear display */
|
|
|
|
|
transmit_tone(s, SKINNY_DIALTONE);
|
|
|
|
|
transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK);
|
|
|
|
|
c = skinny_new(l, AST_STATE_DOWN);
|
|
|
|
|
if(c) {
|
|
|
|
|
/* start the switch thread */
|
|
|
|
|
if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
|
|
|
|
|
ast_hangup(c);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
|
|
|
|
|
/* start the switch thread */
|
|
|
|
|
if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
|
|
|
|
|
ast_hangup(c);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SOFTKEY_HOLD:
|
|
|
|
@ -4119,6 +4193,9 @@ static int handle_message(struct skinny_req *req, struct skinnysession *s)
|
|
|
|
|
} else
|
|
|
|
|
res = handle_keypad_button_message(req, s);
|
|
|
|
|
break;
|
|
|
|
|
case ENBLOC_CALL_MESSAGE:
|
|
|
|
|
res = handle_enbloc_call_message(req, s);
|
|
|
|
|
break;
|
|
|
|
|
case STIMULUS_MESSAGE:
|
|
|
|
|
res = handle_stimulus_message(req, s);
|
|
|
|
|
break;
|
|
|
|
|