aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_skinny.c
diff options
context:
space:
mode:
authorjeremy <jeremy@f38db490-d61c-443f-a65b-d21fe96a405b>2005-06-02 09:11:46 +0000
committerjeremy <jeremy@f38db490-d61c-443f-a65b-d21fe96a405b>2005-06-02 09:11:46 +0000
commitbd9518dcdbbd0825532c6560cfd855a4928050dc (patch)
tree8610a0c55a66089c33f5ddf8aa07d116ec27f618 /channels/chan_skinny.c
parent4fd6d70d9b6b53e77dfe7840d22dad0c6f343c64 (diff)
Add button templates for 7902, 7935, 7940, 7960, 7970, support big endian machines with proper byte ordering, fixed caller*id on 7910 (others?) and more. Bug #4398
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5811 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_skinny.c')
-rwxr-xr-xchannels/chan_skinny.c695
1 files changed, 499 insertions, 196 deletions
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 9d29e2d93..f39df49ec 100755
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -76,6 +76,31 @@ typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define letohl(x) (x)
+#define letohs(x) (x)
+#define htolel(x) (x)
+#define htoles(x) (x)
+#else
+#ifdef SOLARIS
+#define __bswap_16(x) \
+ ((((x) & 0xff00) >> 8) | \
+ (((x) & 0x00ff) << 8))
+#define __bswap_32(x) \
+ ((((x) & 0xff000000) >> 24) | \
+ (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | \
+ (((x) & 0x000000ff) << 24))
+#else
+#include <bits/byteswap.h>
+#endif
+#define letohl(x) __bswap_32(x)
+#define letohs(x) __bswap_16(x)
+#define htolel(x) __bswap_32(x)
+#define htoles(x) __bswap_16(x)
+#endif
+
+
/************************************************************************************/
/* Protocol Messages */
/************************************************************************************/
@@ -340,6 +365,21 @@ button_definition button_def_12sp[] = {
{ 9, STIMULUS_SPEEDDIAL } /* Speeddial 9 */
};
+button_definition button_def_7902[] = {
+ { 1, STIMULUS_LINE }, /* Line 1 */
+ { 1, STIMULUS_HOLD }, /* Hold */
+ { 1, STIMULUS_TRANSFER },
+ { 1, STIMULUS_DISPLAY },
+ { 1, STIMULUS_VOICEMAIL },
+ { 1, STIMULUS_CONFERENCE },
+ { 1, STIMULUS_FORWARDALL },
+ { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
+ { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
+ { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
+ { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
+ { 1, STIMULUS_REDIAL }
+};
+
button_definition button_def_7910[] = {
{ 1, STIMULUS_LINE }, /* Line 1 */
{ 1, STIMULUS_HOLD }, /* Hold */
@@ -362,6 +402,36 @@ button_definition button_def_7920[] = {
{ 4, STIMULUS_SPEEDDIAL } /* Speeddial 4 */
};
+button_definition button_def_7935[] = {
+ { 1, STIMULUS_LINE }, /* Line 1 */
+ { 2, STIMULUS_LINE } /* Line 2 */
+};
+
+button_definition button_def_7940[] = {
+ { 1, STIMULUS_LINE }, /* Line 1 */
+ { 2, STIMULUS_LINE } /* Line 2 */
+};
+
+button_definition button_def_7960[] = {
+ { 1, STIMULUS_LINE }, /* Line 1 */
+ { 2, STIMULUS_LINE }, /* Line 2 */
+ { 3, STIMULUS_LINE }, /* Line 3 */
+ { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
+ { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
+ { 3, STIMULUS_SPEEDDIAL } /* Speeddial 3 */
+};
+
+button_definition button_def_7970[] = {
+ { 1, STIMULUS_LINE }, /* Line 1 */
+ { 2, STIMULUS_LINE }, /* Line 2 */
+ { 3, STIMULUS_LINE }, /* Line 3 */
+ { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
+ { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
+ { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
+ { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
+ { 5, STIMULUS_SPEEDDIAL } /* Speeddial 5 */
+};
+
button_definition button_def_none = { 0, STIMULUS_NONE };
typedef struct button_defs {
@@ -374,8 +444,13 @@ button_defs_t button_defs[] = {
{ "12SP", 12, button_def_12sp }, /* First one is used if
there's no match */
{ "30VIP", 26, button_def_30vip },
+ { "7902", 12, button_def_7902 },
{ "7910", 10, button_def_7910 },
{ "7920", 6, button_def_7920 },
+ { "7935", 2, button_def_7935 },
+ { "7940", 2, button_def_7940 },
+ { "7960", 6, button_def_7960 },
+ { "7970", 8, button_def_7970 },
{ NULL, 0, NULL }
};
@@ -417,24 +492,24 @@ typedef struct soft_key_template_definition {
} soft_key_template_definition;
soft_key_template_definition soft_key_template_default[] = {
- { "Redial", 1 },
- { "NewCall", 2 },
- { "Hold", 3 },
- { "Trnsfer", 4 },
- { "CFwdAll", 5 },
- { "CFwdBusy", 6 },
- { "CFwdNoAnswer", 7 },
- { "<<", 8 },
- { "EndCall", 9 },
- { "Resume", 10 },
- { "Answer", 11 },
- { "Info", 12 },
- { "Confrn", 13 },
- { "Park", 14 },
- { "Join", 15 },
- { "MeetMe", 16 },
- { "PickUp", 17 },
- { "GPickUp", 18 }
+ { "Redial", htolel(1) },
+ { "NewCall", htolel(2) },
+ { "Hold", htolel(3) },
+ { "Trnsfer", htolel(4) },
+ { "CFwdAll", htolel(5) },
+ { "CFwdBusy", htolel(6) },
+ { "CFwdNoAnswer", htolel(7) },
+ { "<<", htolel(8) },
+ { "EndCall", htolel(9) },
+ { "Resume", htolel(10) },
+ { "Answer", htolel(11) },
+ { "Info", htolel(12) },
+ { "Confrn", htolel(13) },
+ { "Park", htolel(14) },
+ { "Join", htolel(15) },
+ { "MeetMe", htolel(16) },
+ { "PickUp", htolel(17) },
+ { "GPickUp", htolel(18) }
};
typedef struct soft_key_template {
@@ -509,11 +584,32 @@ typedef struct call_state_message {
int callReference;
} call_state_message;
+#define DISPLAY_PROMPT_STATUS_MESSAGE 0x0112
+typedef struct display_prompt_status_message {
+ int messageTimeout;
+ char promptMessage[32];
+ int lineInstance;
+ int callReference;
+} display_prompt_status_message;
+
+#define DISPLAY_NOTIFY_MESSAGE 0x0114
+typedef struct display_notify_message {
+ int displayTimeout;
+ char displayMessage[100];
+} display_notify_message;
+
#define ACTIVATE_CALL_PLANE_MESSAGE 0x0116
typedef struct activate_call_plane_message {
int lineInstance;
} activate_call_plane_message;
+#define DIALLED_NUMBER_MESSAGE 0x011D
+typedef struct dialled_number_message {
+ char dialledNumber[24];
+ int lineInstance;
+ int callReference;
+} dialled_number_message;
+
/* packet composition */
typedef struct {
int len;
@@ -528,6 +624,7 @@ typedef struct {
version_res_message version;
button_template_res_message buttontemplate;
displaytext_message displaytext;
+ display_prompt_status_message displaypromptstatus;
definetimedate_message definetimedate;
start_tone_message starttone;
speed_dial_stat_res_message speeddial;
@@ -550,6 +647,8 @@ typedef struct {
open_recieve_channel_message openrecievechannel;
open_recieve_channel_ack_message openrecievechannelack;
close_recieve_channel_message closerecievechannel;
+ display_notify_message displaynotify;
+ dialled_number_message diallednumber;
} data;
} skinny_req;
@@ -581,6 +680,7 @@ static int immediate = 0;
static int callwaiting = 0;
static int callreturn = 0;
static int threewaycalling = 0;
+static int mwiblink = 0;
/* This is for flashhook transfers */
static int transfer = 0;
static int cancallforward = 0;
@@ -611,12 +711,13 @@ static int callnums = 1;
#define SKINNY_PROGRESS 12
#define SKINNY_INVALID 14
-#define SKINNY_SILENCE 0
-#define SKINNY_DIALTONE 33
-#define SKINNY_BUSYTONE 35
-#define SKINNY_ALERT 36
-#define SKINNY_REORDER 37
-#define SKINNY_CALLWAITTONE 45
+#define SKINNY_SILENCE 0x00
+#define SKINNY_DIALTONE 0x21
+#define SKINNY_BUSYTONE 0x23
+#define SKINNY_ALERT 0x24
+#define SKINNY_REORDER 0x25
+#define SKINNY_CALLWAITTONE 0x2D
+#define SKINNY_NOTONE 0x7F
#define SKINNY_LAMP_OFF 1
#define SKINNY_LAMP_ON 2
@@ -668,6 +769,8 @@ AST_MUTEX_DEFINE_STATIC(netlock);
AST_MUTEX_DEFINE_STATIC(sessionlock);
/* Protect the device list */
AST_MUTEX_DEFINE_STATIC(devicelock);
+/* Protect the paging device list */
+AST_MUTEX_DEFINE_STATIC(pagingdevicelock);
/* This is the thread for the monitor which checks for input on the channels
which are not currently in use. */
@@ -720,6 +823,7 @@ struct skinny_line {
int callwaiting;
int transfer;
int threewaycalling;
+ int mwiblink;
int cancallforward;
int callreturn;
int dnd; /* How does this affect callwait? Do we just deny a skinny_request if we're dnd? */
@@ -757,6 +861,13 @@ static struct skinny_device {
struct skinny_device *next;
} *devices = NULL;
+static struct skinny_paging_device {
+ char name[80];
+ char id[16];
+ struct skinny_device ** devices;
+ struct skinny_paging_device *next;
+} *paging_devices = NULL;
+
static struct skinnysession {
pthread_t t;
ast_mutex_t lock;
@@ -858,12 +969,16 @@ static int transmit_response(struct skinnysession *s, skinny_req *req)
{
int res = 0;
ast_mutex_lock(&s->lock);
+
#if 0
- ast_verbose("writing packet type %d (%d bytes) to socket %d\n", req->e, req->len+8, s->fd);
+ if (skinnydebug) {
+ ast_verbose("writing packet type %04X (%d bytes) to socket %d\n", letohl(req->e), letohl(req->len)+8, s->fd);
+ }
#endif
- res = write(s->fd, req, req->len+8);
- if (res != req->len+8) {
- ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, req->len+8, strerror(errno));
+
+ res = write(s->fd, req, letohl(req->len)+8);
+ if (res != letohl(req->len)+8) {
+ ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
}
ast_mutex_unlock(&s->lock);
return 1;
@@ -885,9 +1000,9 @@ static void transmit_speaker_mode(struct skinnysession *s, int mode)
ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
return;
}
- req->len = sizeof(set_speaker_message)+4;
- req->e = SET_SPEAKER_MESSAGE;
- req->data.setspeaker.mode = mode;
+ req->len = htolel(sizeof(set_speaker_message)+4);
+ req->e = htolel(SET_SPEAKER_MESSAGE);
+ req->data.setspeaker.mode = htolel(mode);
transmit_response(s, req);
}
@@ -904,39 +1019,64 @@ static void transmit_callstate(struct skinnysession *s, int instance, int state,
if (state == SKINNY_ONHOOK) {
transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
}
- req->len = sizeof(call_state_message)+4;
- req->e = CALL_STATE_MESSAGE;
- req->data.callstate.callState = state;
- req->data.callstate.lineInstance = instance;
- req->data.callstate.callReference = callid;
+ req->len = htolel(sizeof(call_state_message)+4);
+ req->e = htolel(CALL_STATE_MESSAGE);
+ req->data.callstate.callState = htolel(state);
+ req->data.callstate.lineInstance = htolel(instance);
+ req->data.callstate.callReference = htolel(callid);
transmit_response(s, req);
if (state == SKINNY_OFFHOOK) {
memset(req, 0, memsize);
- req->len = sizeof(activate_call_plane_message)+4;
- req->e = ACTIVATE_CALL_PLANE_MESSAGE;
- req->data.activatecallplane.lineInstance = instance;
+ req->len = htolel(sizeof(activate_call_plane_message)+4);
+ req->e = htolel(ACTIVATE_CALL_PLANE_MESSAGE);
+ req->data.activatecallplane.lineInstance = htolel(instance);
transmit_response(s, req);
} else if (state == SKINNY_ONHOOK) {
memset(req, 0, memsize);
- req->len = sizeof(activate_call_plane_message)+4;
- req->e = ACTIVATE_CALL_PLANE_MESSAGE;
+ req->len = htolel(sizeof(activate_call_plane_message)+4);
+ req->e = htolel(ACTIVATE_CALL_PLANE_MESSAGE);
req->data.activatecallplane.lineInstance = 0;
transmit_response(s, req);
memset(req, 0, memsize);
- req->len = sizeof(close_recieve_channel_message)+4;
- req->e = CLOSE_RECIEVE_CHANNEL_MESSAGE;
+ req->len = htolel(sizeof(close_recieve_channel_message)+4);
+ req->e = htolel(CLOSE_RECIEVE_CHANNEL_MESSAGE);
req->data.closerecievechannel.conferenceId = 0;
req->data.closerecievechannel.partyId = 0;
transmit_response(s, req);
memset(req, 0, memsize);
- req->len = sizeof(stop_media_transmission_message)+4;
- req->e = STOP_MEDIA_TRANSMISSION_MESSAGE;
+ req->len = htolel(sizeof(stop_media_transmission_message)+4);
+ req->e = htolel(STOP_MEDIA_TRANSMISSION_MESSAGE);
req->data.stopmedia.conferenceId = 0;
req->data.stopmedia.passThruPartyId = 0;
transmit_response(s, req);
}
}
+static void transmit_callinfo(struct skinnysession *s, char *fromname, char *fromnum, char *toname, char *tonum, int instance, int callid, int calltype)
+{
+ skinny_req *req;
+
+ req = req_alloc(sizeof(struct call_info_message));
+ if (!req) {
+ ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
+ return;
+ }
+
+ req->len = htolel(sizeof(struct call_info_message));
+ req->e = htolel(CALL_INFO_MESSAGE);
+
+ strncpy(req->data.callinfo.callingPartyName, fromname, 39);
+ strncpy(req->data.callinfo.callingParty, fromnum, 23);
+ strncpy(req->data.callinfo.calledPartyName, toname, 39);
+ strncpy(req->data.callinfo.calledParty, tonum, 23);
+
+ req->data.callinfo.instance = htolel(instance);
+ req->data.callinfo.reference = htolel(callid);
+ req->data.callinfo.type = htolel(calltype);
+
+ transmit_response(s, req);
+}
+
static void transmit_connect(struct skinnysession *s)
{
skinny_req *req;
@@ -947,12 +1087,12 @@ static void transmit_connect(struct skinnysession *s)
ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
return;
}
- req->len = sizeof(struct call_info_message);
- req->e = OPEN_RECIEVE_CHANNEL_MESSAGE;
+ req->len = htolel(sizeof(struct open_recieve_channel_message));
+ req->e = htolel(OPEN_RECIEVE_CHANNEL_MESSAGE);
req->data.openrecievechannel.conferenceId = 0;
req->data.openrecievechannel.partyId = 0;
- req->data.openrecievechannel.packets = 20;
- req->data.openrecievechannel.capability = convert_cap(l->capability);
+ req->data.openrecievechannel.packets = htolel(20);
+ req->data.openrecievechannel.capability = htolel(convert_cap(l->capability));
req->data.openrecievechannel.echo = 0;
req->data.openrecievechannel.bitrate = 0;
transmit_response(s, req);
@@ -971,12 +1111,12 @@ static void transmit_tone(struct skinnysession *s, int tone)
return;
}
if (tone > 0) {
- req->len = sizeof(start_tone_message)+4;
- req->e = START_TONE_MESSAGE;
- req->data.starttone.tone = tone;
+ req->len = htolel(sizeof(start_tone_message)+4);
+ req->e = htolel(START_TONE_MESSAGE);
+ req->data.starttone.tone = htolel(tone);
} else {
- req->len = 4;
- req->e = STOP_TONE_MESSAGE;
+ req->len = htolel(4);
+ req->e = htolel(STOP_TONE_MESSAGE);
}
transmit_response(s, req);
}
@@ -994,11 +1134,11 @@ static void transmit_selectsoftkeys(struct skinnysession *s, int instance, int c
return;
}
memset(req, 0, memsize);
- req->len = sizeof(select_soft_keys_message)+4;
- req->e = SELECT_SOFT_KEYS_MESSAGE;
- req->data.selectsoftkey.instance = instance;
- req->data.selectsoftkey.reference = callid;
- req->data.selectsoftkey.softKeySetIndex = softkey;
+ req->len = htolel(sizeof(select_soft_keys_message)+4);
+ req->e = htolel(SELECT_SOFT_KEYS_MESSAGE);
+ req->data.selectsoftkey.instance = htolel(instance);
+ req->data.selectsoftkey.reference = htolel(callid);
+ req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
transmit_response(s, req);
}
#endif
@@ -1012,11 +1152,11 @@ static void transmit_lamp_indication(struct skinnysession *s, int stimulus, int
ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
return;
}
- req->len = sizeof(set_lamp_message)+4;
- req->e = SET_LAMP_MESSAGE;
- req->data.setlamp.stimulus = stimulus;
- req->data.setlamp.stimulusInstance = instance;
- req->data.setlamp.deviceStimulus = indication;
+ req->len = htolel(sizeof(set_lamp_message)+4);
+ req->e = htolel(SET_LAMP_MESSAGE);
+ req->data.setlamp.stimulus = htolel(stimulus);
+ req->data.setlamp.stimulusInstance = htolel(instance);
+ req->data.setlamp.deviceStimulus = htolel(indication);
transmit_response(s, req);
}
@@ -1029,9 +1169,9 @@ static void transmit_ringer_mode(struct skinnysession *s, int mode)
ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
return;
}
- req->len = sizeof(set_ringer_message)+4;
- req->e = SET_RINGER_MESSAGE;
- req->data.setringer.ringerMode = mode;
+ req->len = htolel(sizeof(set_ringer_message)+4);
+ req->e = htolel(SET_RINGER_MESSAGE);
+ req->data.setringer.ringerMode = htolel(mode);
transmit_response(s, req);
}
@@ -1041,14 +1181,14 @@ static void transmit_displaymessage(struct skinnysession *s, char *text)
if (text == 0) {
req = req_alloc(4);
- req->len = 4;
- req->e = CLEAR_DISPLAY_MESSAGE;
+ req->len = htolel(4);
+ req->e = htolel(CLEAR_DISPLAY_MESSAGE);
} else {
req = req_alloc(sizeof(struct displaytext_message));
strncpy(req->data.displaytext.text, text, sizeof(req->data.displaytext.text)-1);
- req->len = sizeof(displaytext_message) + 4;
- req->e = DISPLAYTEXT_MESSAGE;
+ req->len = htolel(sizeof(displaytext_message) + 4);
+ req->e = htolel(DISPLAYTEXT_MESSAGE);
if (skinnydebug) {
ast_verbose("Displaying message '%s'\n", req->data.displaytext.text);
}
@@ -1061,6 +1201,74 @@ static void transmit_displaymessage(struct skinnysession *s, char *text)
transmit_response(s, req);
}
+static void transmit_displaynotify(struct skinnysession *s, char *text, int t)
+{
+ skinny_req *req;
+
+ req = req_alloc(sizeof(struct display_notify_message));
+
+ if (!req) {
+ ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
+ return;
+ }
+
+ req->e = htolel(DISPLAY_NOTIFY_MESSAGE);
+ req->len = htolel(sizeof(display_notify_message) + 4);
+ strncpy(req->data.displaynotify.displayMessage, text, sizeof(req->data.displaynotify.displayMessage)-1);
+ req->data.displaynotify.displayTimeout = htolel(t);
+
+ if (skinnydebug) {
+ ast_verbose("Displaying notify '%s'\n", text);
+ }
+
+ transmit_response(s, req);
+}
+
+static void transmit_displaypromptstatus(struct skinnysession *s, char *text, int t, int instance, int callid)
+{
+ skinny_req *req;
+
+ req = req_alloc(sizeof(struct display_prompt_status_message));
+
+ if (!req) {
+ ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
+ return;
+ }
+
+ req->e = htolel(DISPLAY_PROMPT_STATUS_MESSAGE);
+ req->len = htolel(sizeof(display_prompt_status_message) + 4);
+ strncpy(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage)-1);
+ 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);
+}
+
+static void transmit_diallednumber(struct skinnysession *s, char *text, int instance, int callid)
+{
+ skinny_req *req;
+
+ req = req_alloc(sizeof(struct dialled_number_message));
+
+ if (!req) {
+ ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
+ return;
+ }
+
+ req->e = htolel(DIALLED_NUMBER_MESSAGE);
+ req->len = htolel(sizeof(dialled_number_message) + 4);
+ strncpy(req->data.diallednumber.dialledNumber, text, sizeof(req->data.diallednumber.dialledNumber)-1);
+ req->data.diallednumber.lineInstance = htolel(instance);
+ req->data.diallednumber.callReference = htolel(callid);
+
+ transmit_response(s, req);
+}
+
static int has_voicemail(struct skinny_line *l)
{
return ast_app_has_voicemail(l->mailbox, NULL);
@@ -1070,9 +1278,10 @@ static int has_voicemail(struct skinny_line *l)
static void do_housekeeping(struct skinnysession *s)
{
struct skinny_subchannel *sub;
+ struct skinny_line *l = s->device->lines;
- sub = find_subchannel_by_line(s->device->lines);
- transmit_displaymessage(s, 0);
+ sub = find_subchannel_by_line(l);
+ transmit_displaymessage(s, NULL);
if (skinnydebug) {
ast_verbose("Checking for voicemail Skinny %s@%s\n", sub->parent->name, sub->parent->parent->name);
@@ -1084,9 +1293,9 @@ static void do_housekeeping(struct skinnysession *s)
if (skinnydebug) {
ast_verbose("Skinny %s@%s has voicemail! Yay!\n", sub->parent->name, sub->parent->parent->name);
}
- transmit_lamp_indication(s, STIMULUS_VOICEMAIL, s->device->lines->instance, SKINNY_LAMP_BLINK);
+ transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
} else {
- transmit_lamp_indication(s, STIMULUS_VOICEMAIL, s->device->lines->instance, SKINNY_LAMP_OFF);
+ transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
}
}
@@ -1143,33 +1352,77 @@ static int skinny_no_debug(int fd, int argc, char *argv[])
return RESULT_SUCCESS;
}
-static int skinny_show_lines(int fd, int argc, char *argv[])
+static int skinny_show_devices(int fd, int argc, char *argv[])
{
struct skinny_device *d;
struct skinny_line *l;
- int haslines = 0;
+ int numlines = 0;
char iabuf[INET_ADDRSTRLEN];
+
+ if (argc != 3)
+ return RESULT_SHOWUSAGE;
+
+ ast_mutex_lock(&devicelock);
+ d = devices;
+
+ ast_cli(fd, "Name DeviceId IP TypeId R Model NL\n");
+ ast_cli(fd, "-------------------- ---------------- --------------- ------ - ------ --\n");
+ while(d) {
+ l = d->lines;
+ numlines = 0;
+ while(l) { numlines++; l = l->next; }
+
+ ast_cli(fd, "%-20s %-16s %-16s %6X %c %-6s %2d\n",
+ d->name,
+ d->id,
+ ast_inet_ntoa(iabuf, sizeof(iabuf), d->addr.sin_addr),
+ d->type,
+ d->registered?'Y':'N',
+ d->model,
+ numlines);
+
+ d = d->next;
+ }
+ ast_mutex_unlock(&devicelock);
+
+ return RESULT_SUCCESS;
+}
+
+static int skinny_show_lines(int fd, int argc, char *argv[])
+{
+
+ struct skinny_device *d;
+ struct skinny_line *l;
+
if (argc != 3)
return RESULT_SHOWUSAGE;
+
ast_mutex_lock(&devicelock);
d = devices;
while(d) {
l = d->lines;
- ast_cli(fd, "Device '%s' at %s\n", d->name, ast_inet_ntoa(iabuf, sizeof(iabuf), d->addr.sin_addr));
- while(l) {
- ast_cli(fd, " -- '%s@%s in '%s' is %s\n", l->name, d->name, l->context, l->sub->owner ? "active" : "idle");
- haslines = 1;
+ while (l) {
+ ast_cli(fd, "%-20s %2d %-20s %-20s %c %c\n",
+ l->parent->name,
+ l->instance,
+ l->name,
+ l->label,
+ l->sub->owner?'Y':'N',
+ l->sub->rtp?'Y':'N');
+
l = l->next;
}
- if (!haslines) {
- ast_cli(fd, " << No Lines Defined >> ");
- }
d = d->next;
}
ast_mutex_unlock(&devicelock);
+
return RESULT_SUCCESS;
}
+static char show_devices_usage[] =
+"Usage: skinny show devices\n"
+" Lists all devices known to the Skinny subsystem.\n";
+
static char show_lines_usage[] =
"Usage: skinny show lines\n"
" Lists all lines known to the Skinny subsystem.\n";
@@ -1182,13 +1435,23 @@ static char no_debug_usage[] =
"Usage: skinny no debug\n"
" Disables dumping of Skinny packets for debugging purposes\n";
+static struct ast_cli_entry cli_show_devices =
+ { { "skinny", "show", "devices", NULL }, skinny_show_devices, "Show defined Skinny devices", show_devices_usage };
+
static struct ast_cli_entry cli_show_lines =
{ { "skinny", "show", "lines", NULL }, skinny_show_lines, "Show defined Skinny lines per device", show_lines_usage };
+
static struct ast_cli_entry cli_debug =
{ { "skinny", "debug", NULL }, skinny_do_debug, "Enable Skinny debugging", debug_usage };
+
static struct ast_cli_entry cli_no_debug =
{ { "skinny", "no", "debug", NULL }, skinny_no_debug, "Disable Skinny debugging", no_debug_usage };
+static struct skinny_paging_device *build_paging_device(char *cat, struct ast_variable *v)
+{
+ return NULL;
+}
+
static struct skinny_device *build_device(char *cat, struct ast_variable *v)
{
struct skinny_device *d;
@@ -1252,14 +1515,14 @@ static struct skinny_device *build_device(char *cat, struct ast_variable *v)
strncpy(mailbox, v->value, sizeof(mailbox) -1);
} else if (!strcasecmp(v->name, "callreturn")) {
callreturn = ast_true(v->value);
- } else if (!strcasecmp(v->name, "immediate")) {
- immediate = ast_true(v->value);
} else if (!strcasecmp(v->name, "callwaiting")) {
callwaiting = ast_true(v->value);
} else if (!strcasecmp(v->name, "transfer")) {
transfer = ast_true(v->value);
} else if (!strcasecmp(v->name, "threewaycalling")) {
threewaycalling = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "mwiblink")) {
+ mwiblink = ast_true(v->value);
} else if (!strcasecmp(v->name, "linelabel")) {
strncpy(linelabel, v->value, sizeof(linelabel)-1);
} else if (!strcasecmp(v->name, "trunk") || !strcasecmp(v->name, "line")) {
@@ -1299,6 +1562,7 @@ static struct skinny_device *build_device(char *cat, struct ast_variable *v)
l->callwaiting = callwaiting;
l->transfer = transfer;
l->threewaycalling = threewaycalling;
+ l->mwiblink = mwiblink;
l->onhooktime = time(NULL);
l->instance = 1;
/* ASSUME we're onhook at this point*/
@@ -1362,10 +1626,10 @@ static int skinny_register(skinny_req *req, struct skinnysession *s)
ast_mutex_lock(&devicelock);
d = devices;
while (d) {
- if (!strcasecmp(req->data.reg.name, d->id)) {
- /* XXX Deal with IP authentication */
+ if (!strcasecmp(req->data.reg.name, d->id)
+ && ast_apply_ha(d->ha, &(s->sin))) {
s->device = d;
- d->type = req->data.reg.type;
+ d->type = letohl(req->data.reg.type);
if (ast_strlen_zero(d->version_id)) {
strncpy(d->version_id, version_id, sizeof(d->version_id) - 1);
}
@@ -1710,25 +1974,16 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout)
transmit_tone(session, tone);
transmit_callstate(session, l->instance, SKINNY_RINGIN, sub->callid);
+ transmit_displaypromptstatus(session, "Ring-In", 0, l->instance, sub->callid);
+ transmit_callinfo(session, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1); /* 1 = incoming to phone */
- /* XXX need to set the prompt */
/* XXX need to deal with softkeys */
ast_setstate(ast, AST_STATE_RINGING);
ast_queue_control(ast, AST_CONTROL_RINGING);
sub->outgoing = 1;
- if (l->type == TYPE_LINE) {
- if (!sub->rtp) {
- start_rtp(sub);
- } else {
- /* do/should we need to anything if there already is an RTP allocated? */
- }
- } else {
- ast_log(LOG_ERROR, "I don't know how to dial on trunks, yet\n");
- res = -1;
- }
return res;
}
@@ -1780,6 +2035,8 @@ static int skinny_answer(struct ast_channel *ast)
int res = 0;
struct skinny_subchannel *sub = ast->tech_pvt;
struct skinny_line *l = sub->parent;
+ struct skinnysession *s = l->parent->session;
+
sub->cxmode = SKINNY_CX_SENDRECV;
if (!sub->rtp) {
start_rtp(sub);
@@ -1788,6 +2045,10 @@ static int skinny_answer(struct ast_channel *ast)
if (ast->_state != AST_STATE_UP) {
ast_setstate(ast, AST_STATE_UP);
}
+
+ transmit_tone(s, SKINNY_NOTONE);
+ transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
+ transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
return res;
}
@@ -1873,6 +2134,8 @@ static int skinny_senddigit(struct ast_channel *ast, char digit)
}
static char *control2str(int ind) {
+ static char tmp[100];
+
switch (ind) {
case AST_CONTROL_HANGUP:
return "Other end has hungup";
@@ -1900,10 +2163,19 @@ static char *control2str(int ind) {
return "Key Radio";
case AST_CONTROL_RADIO_UNKEY:
return "Un-Key Radio";
- case -1:
- return "Stop tone";
+ case AST_CONTROL_PROGRESS:
+ return "Remote end is making Progress";
+ case AST_CONTROL_PROCEEDING:
+ return "Remote end is proceeding";
+ case AST_CONTROL_HOLD:
+ return "Hold";
+ case AST_CONTROL_UNHOLD:
+ return "Unhold";
+ case -1:
+ return "Stop tone";
}
- return "UNKNOWN";
+ snprintf(tmp, 100, "UNKNOWN-%d", ind);
+ return tmp;
}
@@ -1922,6 +2194,9 @@ static int skinny_indicate(struct ast_channel *ast, int ind)
if (!sub->progress) {
transmit_tone(s, SKINNY_ALERT);
transmit_callstate(s, l->instance, SKINNY_RINGOUT, sub->callid);
+ transmit_diallednumber(s, ast->exten, l->instance, sub->callid);
+ transmit_displaypromptstatus(s, "Ring Out", 0, l->instance, sub->callid);
+ transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
sub->ringing = 1;
break;
}
@@ -1947,7 +2222,10 @@ static int skinny_indicate(struct ast_channel *ast, int ind)
return -1;
case AST_CONTROL_PROGRESS:
if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
+ transmit_tone(s, SKINNY_ALERT);
transmit_callstate(s, l->instance, SKINNY_PROGRESS, sub->callid);
+ transmit_displaypromptstatus(s, "Call Progress", 0, l->instance, sub->callid);
+ transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
sub->progress = 1;
break;
}
@@ -1977,6 +2255,7 @@ static struct ast_channel *skinny_new(struct skinny_subchannel *sub, int state)
if (!tmp->nativeformats)
tmp->nativeformats = capability;
fmt = ast_best_codec(tmp->nativeformats);
+ast_verbose("chan_skinny: skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
snprintf(tmp->name, sizeof(tmp->name), "Skinny/%s@%s-%d", l->name, l->parent->name, sub->callid);
if (sub->rtp)
tmp->fds[0] = ast_rtp_fd(sub->rtp);
@@ -2012,6 +2291,10 @@ static struct ast_channel *skinny_new(struct skinny_subchannel *sub, int state)
tmp->cid.cid_name = strdup(l->cid_name);
}
tmp->priority = 1;
+
+ tmp->adsicpe = AST_ADSI_UNAVAILABLE;
+
+
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
@@ -2037,6 +2320,7 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
char name[16];
char addr[4];
char d;
+ char iabuf[INET_ADDRSTRLEN];
int digit;
int res=0;
int speedDialNum;
@@ -2051,13 +2335,13 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
pthread_t t;
button_defs_t *b, *buse;
- if ( (!s->device) && (req->e != REGISTER_MESSAGE && req->e != ALARM_MESSAGE)) {
+ if ( (!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
free(req);
return 0;
}
- switch(req->e) {
+ switch(letohl(req->e)) {
case ALARM_MESSAGE:
/* no response necessary */
break;
@@ -2070,8 +2354,8 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", req->data.reg.name);
memcpy(&name, req->data.reg.name, sizeof(req->data.reg.name));
memset(req, 0, sizeof(skinny_req));
- req->len = sizeof(register_rej_message)+4;
- req->e = REGISTER_REJ_MESSAGE;
+ req->len = htolel(sizeof(register_rej_message)+4);
+ req->e = htolel(REGISTER_REJ_MESSAGE);
snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
transmit_response(s, req);
break;
@@ -2080,22 +2364,22 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfuly registered\n", s->device->name);
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(register_ack_message)+4;
- req->e = REGISTER_ACK_MESSAGE;
+ req->len = htolel(sizeof(register_ack_message)+4);
+ req->e = htolel(REGISTER_ACK_MESSAGE);
req->data.regack.res[0] = '0';
req->data.regack.res[1] = '\0';
- req->data.regack.keepAlive = keep_alive;
+ req->data.regack.keepAlive = htolel(keep_alive);
strncpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate) - 1);
req->data.regack.res2[0] = '0';
req->data.regack.res2[1] = '\0';
- req->data.regack.secondaryKeepAlive = keep_alive;
+ req->data.regack.secondaryKeepAlive = htolel(keep_alive);
transmit_response(s, req);
if (skinnydebug) {
ast_verbose("Requesting capabilities\n");
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = 4;
- req->e = CAPABILITIES_REQ_MESSAGE;
+ req->len = htolel(4);
+ req->e = htolel(CAPABILITIES_REQ_MESSAGE);
transmit_response(s, req);
break;
case UNREGISTER_MESSAGE:
@@ -2105,8 +2389,8 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
/* no response necessary */
break;
case STIMULUS_MESSAGE:
- stimulus = req->data.stimulus.stimulus;
- stimulusInstance = req->data.stimulus.stimulusInstance;
+ stimulus = letohl(req->data.stimulus.stimulus);
+ stimulusInstance = letohl(req->data.stimulus.stimulusInstance);
switch(stimulus) {
case STIMULUS_REDIAL:
@@ -2173,12 +2457,14 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
}
s->device->lines->dnd = 0;
transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
+ transmit_displaynotify(s, "DnD disabled",10);
}else{
if (option_verbose > 2) {
ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n",find_subchannel_by_line(s->device->lines)->parent->name,find_subchannel_by_line(s->device->lines)->parent->name);
}
s->device->lines->dnd = 1;
transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
+ transmit_displaynotify(s, "DnD enabled",10);
}
break;
case STIMULUS_FORWARDBUSY:
@@ -2212,8 +2498,8 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_verbose("Version Request\n");
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(version_res_message)+4;
- req->e = VERSION_RES_MESSAGE;
+ req->len = htolel(sizeof(version_res_message)+4);
+ req->e = htolel(VERSION_RES_MESSAGE);
snprintf(req->data.version.version, sizeof(req->data.version.version), s->device->version_id);
transmit_response(s, req);
break;
@@ -2222,12 +2508,12 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_verbose("Recieved Server Request\n");
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(server_res_message)+4;
- req->e = SERVER_RES_MESSAGE;
+ req->len = htolel(sizeof(server_res_message)+4);
+ req->e = htolel(SERVER_RES_MESSAGE);
memcpy(req->data.serverres.server[0].serverName, ourhost,
sizeof(req->data.serverres.server[0].serverName));
- req->data.serverres.serverListenPort[0] = ourport;
- req->data.serverres.serverIpAddr[0] = __ourip.s_addr;
+ req->data.serverres.serverListenPort[0] = htolel(ourport);
+ req->data.serverres.serverIpAddr[0] = htolel(__ourip.s_addr);
transmit_response(s, req);
break;
case BUTTON_TEMPLATE_REQ_MESSAGE:
@@ -2238,8 +2524,8 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
sub = find_subchannel_by_line(s->device->lines);
memset(req, 0, SKINNY_MAX_PACKET);
- req->e = BUTTON_TEMPLATE_RES_MESSAGE;
- req->len = sizeof(button_template_res_message)+4;
+ req->e = htolel(BUTTON_TEMPLATE_RES_MESSAGE);
+ req->len = htolel(sizeof(button_template_res_message)+4);
/* Find a matching button definition, default to first in the
list */
@@ -2251,8 +2537,8 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
}
req->data.buttontemplate.buttonOffset = 0;
- req->data.buttontemplate.buttonCount = buse->num_buttons;
- req->data.buttontemplate.totalButtonCount = buse->num_buttons;
+ req->data.buttontemplate.buttonCount = htolel(buse->num_buttons);
+ req->data.buttontemplate.totalButtonCount = htolel(buse->num_buttons);
for (i=0; i<42; i++) {
if (i < buse->num_buttons) {
memcpy(&(req->data.buttontemplate.definition[i]),
@@ -2280,11 +2566,11 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_verbose("Received SoftKeySetReq\n");
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(soft_key_sets)+4;
- req->e = SOFT_KEY_SET_RES_MESSAGE;
+ req->len = htolel(sizeof(soft_key_sets)+4);
+ req->e = htolel(SOFT_KEY_SET_RES_MESSAGE);
req->data.softkeysets.softKeySetOffset = 0;
- req->data.softkeysets.softKeySetCount = 11;
- req->data.softkeysets.totalSoftKeySetCount = 11;
+ req->data.softkeysets.softKeySetCount = htolel(11);
+ req->data.softkeysets.totalSoftKeySetCount = htolel(11);
/* XXX Wicked hack XXX */
memcpy(req->data.softkeysets.softKeySetDefinition,
soft_key_set_hack,
@@ -2296,11 +2582,11 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_verbose("Recieved SoftKey Template Request\n");
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(soft_key_template)+4;
- req->e = SOFT_KEY_TEMPLATE_RES_MESSAGE;
+ req->len = htolel(sizeof(soft_key_template)+4);
+ req->e = htolel(SOFT_KEY_TEMPLATE_RES_MESSAGE);
req->data.softkeytemplate.softKeyOffset = 0;
- req->data.softkeytemplate.softKeyCount = sizeof(soft_key_template_default) / sizeof(soft_key_template_definition);
- req->data.softkeytemplate.totalSoftKeyCount = sizeof(soft_key_template_default) / sizeof(soft_key_template_definition);
+ req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(soft_key_template_definition));
+ req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(soft_key_template_definition));
memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
soft_key_template_default,
sizeof(soft_key_template_default));
@@ -2311,26 +2597,26 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_verbose("Received Time/Date Request\n");
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(definetimedate_message)+4;
- req->e = DEFINETIMEDATE_MESSAGE;
+ req->len = htolel(sizeof(definetimedate_message)+4);
+ req->e = htolel(DEFINETIMEDATE_MESSAGE);
timer=time(NULL);
cmtime = localtime(&timer);
- req->data.definetimedate.year = cmtime->tm_year+1900;
- req->data.definetimedate.month = cmtime->tm_mon+1;
- req->data.definetimedate.dayofweek = cmtime->tm_wday;
- req->data.definetimedate.day = cmtime->tm_mday;
- req->data.definetimedate.hour = cmtime->tm_hour;
- req->data.definetimedate.minute = cmtime->tm_min;
- req->data.definetimedate.seconds = cmtime->tm_sec;
+ req->data.definetimedate.year = htolel(cmtime->tm_year+1900);
+ req->data.definetimedate.month = htolel(cmtime->tm_mon+1);
+ req->data.definetimedate.dayofweek = htolel(cmtime->tm_wday);
+ req->data.definetimedate.day = htolel(cmtime->tm_mday);
+ req->data.definetimedate.hour = htolel(cmtime->tm_hour);
+ req->data.definetimedate.minute = htolel(cmtime->tm_min);
+ req->data.definetimedate.seconds = htolel(cmtime->tm_sec);
transmit_response(s, req);
break;
case SPEED_DIAL_STAT_REQ_MESSAGE:
/* Not really sure how Speed Dial's are different than the
Softkey templates */
- speedDialNum = req->data.speeddialreq.speedDialNumber;
+ speedDialNum = letohl(req->data.speeddialreq.speedDialNumber);
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(speed_dial_stat_res_message)+4;
- req->e = SPEED_DIAL_STAT_RES_MESSAGE;
+ req->len = htolel(sizeof(speed_dial_stat_res_message)+4);
+ req->e = htolel(SPEED_DIAL_STAT_RES_MESSAGE);
#if 0
/* XXX Do this right XXX */
/* If the redial function works the way I think it will, a modification of it
@@ -2342,13 +2628,13 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
transmit_response(s, req);
break;
case LINE_STATE_REQ_MESSAGE:
- lineNumber = req->data.line.lineNumber;
+ lineNumber = letohl(req->data.line.lineNumber);
if (skinnydebug) {
ast_verbose("Received LineStateReq\n");
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(line_stat_res_message)+4;
- req->e = LINE_STAT_RES_MESSAGE;
+ req->len = htolel(sizeof(line_stat_res_message)+4);
+ req->e = htolel(LINE_STAT_RES_MESSAGE);
sub = find_subchannel_by_line(s->device->lines);
if (!sub) {
ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
@@ -2360,7 +2646,7 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
lines = lines->next;
}
ast_mutex_unlock(&devicelock);
- req->data.linestat.linenumber = lineNumber;
+ req->data.linestat.linenumber = letohl(lineNumber);
memcpy(req->data.linestat.lineDirNumber, lines->name,
sizeof(req->data.linestat.lineDirNumber));
memcpy(req->data.linestat.lineDisplayName, lines->label,
@@ -2375,8 +2661,8 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
break;
case KEEP_ALIVE_MESSAGE:
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = 4;
- req->e = KEEP_ALIVE_ACK_MESSAGE;
+ req->len = htolel(4);
+ req->e = htolel(KEEP_ALIVE_ACK_MESSAGE);
transmit_response(s, req);
do_housekeeping(s);
@@ -2393,8 +2679,12 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
sub->parent->hookstate = SKINNY_OFFHOOK;
if (sub->outgoing) {
+ /* We're answering a ringing call */
+ ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
transmit_callstate(s, s->device->lines->instance, SKINNY_OFFHOOK, sub->callid);
transmit_tone(s, SKINNY_SILENCE);
+ transmit_callstate(s, s->device->lines->instance, SKINNY_CONNECTED, sub->callid);
+ start_rtp(sub);
ast_setstate(sub->owner, AST_STATE_UP);
/* XXX select the appropriate soft key here */
} else {
@@ -2403,7 +2693,7 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
if (skinnydebug) {
ast_verbose("Attempting to Clear display on Skinny %s@%s\n",sub->parent->name, sub->parent->parent->name);
}
- transmit_displaymessage(s, 0); /* clear display */
+ transmit_displaymessage(s, NULL); /* clear display */
transmit_tone(s, SKINNY_DIALTONE);
c = skinny_new(sub, AST_STATE_DOWN);
if(c) {
@@ -2430,42 +2720,46 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
sub->cxmode = SKINNY_CX_RECVONLY;
sub->parent->hookstate = SKINNY_ONHOOK;
transmit_callstate(s, s->device->lines->instance, sub->parent->hookstate,sub->callid);
- if (skinnydebug) {
+
+ if (skinnydebug) {
ast_verbose("Skinny %s@%s went on hook\n",sub->parent->name, sub->parent->parent->name);
- }
- if (sub->parent->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
+ }
+
+ if (sub->parent->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
/* We're allowed to transfer, we have two active calls and */
/* we made at least one of the calls. Let's try and transfer */
+
#if 0
- if ((res = attempt_transfer(p)) < 0) {
+ if ((res = attempt_transfer(p)) < 0) {
if (p->sub->next->owner) {
sub->next->alreadygone = 1;
ast_queue_hangup(sub->next->owner,1);
}
- } else if (res) {
- ast_log(LOG_WARNING, "Transfer attempt failed\n");
- return -1;
- }
+ } else if (res) {
+ ast_log(LOG_WARNING, "Transfer attempt failed\n");
+ return -1;
+ }
#endif
- } else {
- /* Hangup the current call */
- /* If there is another active call, skinny_hangup will ring the phone with the other call */
- if (sub->owner) {
- sub->alreadygone = 1;
- ast_queue_hangup(sub->owner);
- } else {
- ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
- sub->parent->name, sub->parent->parent->name, sub->callid);
- }
- }
-
- if ((sub->parent->hookstate == SKINNY_ONHOOK) && (!sub->next->rtp)) {
+ } else {
+ /* Hangup the current call */
+ /* If there is another active call, skinny_hangup will ring the phone with the other call */
+ if (sub->owner) {
+ sub->alreadygone = 1;
+ ast_queue_hangup(sub->owner);
+ } else {
+ ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
+ sub->parent->name, sub->parent->parent->name, sub->callid);
+ }
+ }
+
+ if ((sub->parent->hookstate == SKINNY_ONHOOK) && (!sub->next->rtp)) {
do_housekeeping(s);
- }
+ }
+
+ break;
- break;
case KEYPAD_BUTTON_MESSAGE:
- digit = req->data.keypad.button;
+ digit = letohl(req->data.keypad.button);
if (skinnydebug) {
ast_verbose("Collected digit: [%d]\n", digit);
}
@@ -2504,18 +2798,21 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
break;
case OPEN_RECIEVE_CHANNEL_ACK_MESSAGE:
ast_verbose("Recieved Open Recieve Channel Ack\n");
- status = req->data.openrecievechannelack.status;
+ status = letohl(req->data.openrecievechannelack.status);
if (status) {
ast_log(LOG_ERROR, "Open Recieve Channel Failure\n");
break;
}
+ /* ENDIAN */
memcpy(addr, req->data.openrecievechannelack.ipAddr, sizeof(addr));
- port = req->data.openrecievechannelack.port;
+ port = htolel(req->data.openrecievechannelack.port);
sin.sin_family = AF_INET;
/* I smell endian problems */
memcpy(&sin.sin_addr, addr, sizeof(sin.sin_addr));
sin.sin_port = htons(port);
+
+ ast_verbose("ipaddr = %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
sub = find_subchannel_by_line(s->device->lines);
if (sub->rtp) {
@@ -2526,22 +2823,22 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
break;
}
memset(req, 0, SKINNY_MAX_PACKET);
- req->len = sizeof(start_media_transmission_message)+4;
- req->e = START_MEDIA_TRANSMISSION_MESSAGE;
+ req->len = htolel(sizeof(start_media_transmission_message)+4);
+ req->e = htolel(START_MEDIA_TRANSMISSION_MESSAGE);
req->data.startmedia.conferenceId = 0;
req->data.startmedia.passThruPartyId = 0;
memcpy(req->data.startmedia.remoteIp, &s->device->ourip, 4); /* Endian? */
- req->data.startmedia.remotePort = ntohs(us.sin_port);
- req->data.startmedia.packetSize = 20;
- req->data.startmedia.payloadType = convert_cap(s->device->lines->capability);
- req->data.startmedia.qualifier.precedence = 127;
+ req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
+ req->data.startmedia.packetSize = htolel(20);
+ req->data.startmedia.payloadType = htolel(convert_cap(s->device->lines->capability));
+ req->data.startmedia.qualifier.precedence = htolel(127);
req->data.startmedia.qualifier.vad = 0;
req->data.startmedia.qualifier.packets = 0;
req->data.startmedia.qualifier.bitRate = 0;
transmit_response(s, req);
break;
default:
- ast_verbose("RECEIVED UNKNOWN MESSAGE TYPE: %x\n", req->e);
+ ast_verbose("RECEIVED UNKNOWN MESSAGE TYPE: %x\n", letohl(req->e));
break;
}
@@ -2594,10 +2891,10 @@ static int get_input(struct skinnysession *s)
ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
return -1;
}
- dlen = *(int *)s->inbuf;
+ dlen = letohl(*(int *)s->inbuf);
if (dlen+8 > sizeof(s->inbuf))
dlen = sizeof(s->inbuf) - 8;
- *(int *)s->inbuf = dlen;
+ *(int *)s->inbuf = htolel(dlen);
res = read(s->fd, s->inbuf+4, dlen+4);
ast_mutex_unlock(&s->lock);
if (res != (dlen+4)) {
@@ -2619,8 +2916,8 @@ static skinny_req *skinny_req_parse(struct skinnysession *s)
}
memset(req, 0, sizeof(skinny_req));
/* +8 to account for reserved and length fields */
- memcpy(req, s->inbuf, *(int*)(s->inbuf)+8);
- if (req->e < 0) {
+ memcpy(req, s->inbuf, letohl(*(int*)(s->inbuf))+8);
+ if (letohl(req->e) < 0) {
ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
free(req);
return NULL;
@@ -2816,6 +3113,7 @@ static int reload_config(void)
char *cat;
char iabuf[INET_ADDRSTRLEN];
struct skinny_device *d;
+ struct skinny_paging_device *p;
int oldport = ntohs(bindaddr.sin_port);
#if 0
@@ -2889,7 +3187,15 @@ static int reload_config(void)
/* load the device sections */
cat = ast_category_browse(cfg, NULL);
while(cat) {
- if (strcasecmp(cat, "general")) {
+ if (!strcasecmp(cat, "general")) {
+ /* Nothing to do */
+#if 0
+ } else if (!strncasecmp(cat, "paging-", 7)) {
+ p = build_paging_device(cat, ast_variable_browse(cfg, cat));
+ if (p) {
+ }
+#endif
+ } else {
d = build_device(cat, ast_variable_browse(cfg, cat));
if (d) {
if (option_verbose > 2) {
@@ -2954,7 +3260,6 @@ static int reload_config(void)
return 0;
}
-#if 0
void delete_devices(void)
{
struct skinny_device *d, *dlast;
@@ -2987,17 +3292,13 @@ void delete_devices(void)
devices=NULL;
ast_mutex_unlock(&devicelock);
}
-#endif
int reload(void)
{
-#if 0
-/* XXX Causes Seg - needs to be fixed, or? */
-
delete_devices();
reload_config();
restart_monitor();
-#endif
+
return 0;
}
@@ -3018,6 +3319,7 @@ int load_module()
}
}
ast_rtp_proto_register(&skinny_rtp);
+ ast_cli_register(&cli_show_devices);
ast_cli_register(&cli_show_lines);
ast_cli_register(&cli_debug);
ast_cli_register(&cli_no_debug);
@@ -3081,6 +3383,7 @@ int unload_module()
ast_rtp_proto_register(&skinny_rtp);
ast_channel_unregister(&skinny_tech);
+ ast_cli_register(&cli_show_devices);
ast_cli_register(&cli_show_lines);
ast_cli_register(&cli_debug);
ast_cli_register(&cli_no_debug);