@ -277,13 +277,107 @@ typedef struct server_res_message {
} server_res_message ;
# define BUTTON_TEMPLATE_RES_MESSAGE 0x0097
static const char * button_definition_hack = {
" \x01 \x09 \x01 \x02 \x02 \x02 \x03 \x02 \x04 \x02 \x05 \x02 \x06 \x02 \x07 \x02 "
" \x08 \x02 \x09 \x02 \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff "
" \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff "
" \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff "
" \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff \x00 \xff "
" \x00 \xff \x00 \xff "
/*
Define the template for a 30 VIP phone , this is the older Selsius systems
model that has 30 buttons for your button - pushing enjoyment . Each
softbutton defition goes by a ' index ' of a button followed by that buttons
assignment for example " \x01 \x09 " means Line 1 , while " \x02 \x09 " means Line 2
comments on what each assignment means is below
*/
static const char * thirtyvip_button_definition_hack = {
" \x01 \x09 " /* Line 1 */
" \x02 \x09 " /* Line 2 */
" \x03 \x09 " /* Line 3 */
" \x04 \x09 " /* Line 4 */
" \x01 \x7e "
" \x01 \x01 " /* Redial */
" \x00 \xff "
" \x01 \x02 " /* Speeddial 1 */
" \x02 \x02 " /* Speeddial 2 */
" \x03 \x02 " /* Speeddial 3 */
" \x04 \x02 " /* Speeddial 4 */
" \x05 \x02 " /* Speeddial 5 */
" \x06 \x02 " /* Speeddial 6 */
" \x01 \x0f " /* Voicemail */
" \x01 \x05 " /* Forward all */
" \x01 \x7d " /* Conference */
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x07 \x02 " /* Speeddial 7 */
" \x08 \x02 " /* Speeddial 8 */
" \x09 \x02 " /* Speeddial 9 */
" \x0A \x02 " /* Speeddial 10 */
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
} ;
/*
Now , define the buttons on the 12 SP , you 79 XX series folks , you get this
too , as I don ' t know how the buttons are laid out , and I don ' t care as I
don ' t have one . Code your own damn buttons or send me a 7960
*/
static const char * twelvesp_button_definition_hack = {
" \x01 \x09 " /* Line 1 */
" \x01 \x09 " /* Line 2 */
" \x01 \x02 " /* Speeddial 1 */
" \x02 \x02 " /* Speeddial 2 */
" \x03 \x02 " /* Speeddial 3 */
" \x04 \x02 " /* Speeddial 4 */
" \x01 \x0f " /* Voicemail */
" \x05 \x02 " /* Speeddial 5 */
" \x06 \x02 " /* Speeddial 6 */
" \x07 \x02 " /* Speeddial 7 */
" \x08 \x02 " /* Speeddial 8 */
" \x09 \x02 " /* Speeddial 9 */
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
" \x00 \xff "
} ;
typedef struct buttondefinition {
@ -560,6 +654,12 @@ static int callnums = 1;
# define STIMULUS_FORWARDNOANSWER 7
# define STIMULUS_DISPLAY 8
# define STIMULUS_LINE 9
# define STIMULUS_VOICEMAIL 15
# define STIMULUS_AUTOANSWER 17
# define STIMULUS_CONFERENCE 125
# define STIMULUS_CALLPARK 126
# define STIMULUS_CALLPICKUP 127
/* Skinny rtp stream modes. Do we really need this? */
# define SKINNY_CX_SENDONLY 0
@ -677,6 +777,7 @@ static struct skinny_device {
char version_id [ 16 ] ;
int type ;
int registered ;
char model [ 6 ] ;
struct sockaddr_in addr ;
struct in_addr ourip ;
struct skinny_line * lines ;
@ -904,7 +1005,7 @@ static void transmit_selectsoftkeys(struct skinnysession *s, int instance, int c
}
# endif
static void transmit_lamp_indication ( struct skinnysession * s , int instance, int indication )
static void transmit_lamp_indication ( struct skinnysession * s , int stimulus, int instance, int indication )
{
skinny_req * req ;
@ -915,7 +1016,7 @@ static void transmit_lamp_indication(struct skinnysession *s, int instance, int
}
req - > len = sizeof ( set_lamp_message ) + 4 ;
req - > e = SET_LAMP_MESSAGE ;
req - > data . setlamp . stimulus = 0x9 ; /* magic number */
req - > data . setlamp . stimulus = stimulus ;
req - > data . setlamp . stimulusInstance = instance ;
req - > data . setlamp . deviceStimulus = indication ;
transmit_response ( s , req ) ;
@ -962,6 +1063,36 @@ static void transmit_displaymessage(struct skinnysession *s, char *text)
transmit_response ( s , req ) ;
}
static int has_voicemail ( struct skinny_line * l )
{
return ast_app_has_voicemail ( l - > mailbox , NULL ) ;
}
static void do_housekeeping ( struct skinnysession * s )
{
struct skinny_subchannel * sub ;
sub = find_subchannel_by_line ( s - > device - > lines ) ;
transmit_displaymessage ( s , 0 ) ;
if ( skinnydebug ) {
ast_verbose ( " Checking for voicemail Skinny %s@%s \n " , sub - > parent - > name , sub - > parent - > parent - > name ) ;
}
if ( has_voicemail ( sub - > parent ) ) {
int new ;
int old ;
ast_app_messagecount ( sub - > parent - > mailbox , & new , & old ) ;
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 ) ;
} else {
transmit_lamp_indication ( s , STIMULUS_VOICEMAIL , s - > device - > lines - > instance , SKINNY_LAMP_OFF ) ;
}
}
/* I do not believe skinny can deal with video.
Anyone know differently ? */
static struct ast_rtp * skinny_get_vrtp_peer ( struct ast_channel * chan )
@ -1088,6 +1219,8 @@ static struct skinny_device *build_device(char *cat, struct ast_variable *v)
strncpy ( d - > version_id , v - > value , sizeof ( d - > version_id ) - 1 ) ;
} else if ( ! strcasecmp ( v - > name , " nat " ) ) {
nat = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " model " ) ) {
strncpy ( d - > model , v - > value , sizeof ( d - > model ) - 1 ) ;
} else if ( ! strcasecmp ( v - > name , " callerid " ) ) {
if ( ! strcasecmp ( v - > value , " asreceived " ) ) {
cid_num [ 0 ] = ' \0 ' ;
@ -1138,7 +1271,7 @@ static struct skinny_device *build_device(char *cat, struct ast_variable *v)
strncpy ( l - > name , v - > value , sizeof ( l - > name ) - 1 ) ;
/* XXX Should we check for uniqueness?? XXX */
strncpy ( l - > context , context , sizeof ( l - > context ) - 1 ) ;
strncpy ( l - > cid_num , cid_num , sizeof ( l - > cid_num ) - 1 ) ;
strncpy ( l - > cid_name , cid_name , sizeof ( l - > cid_name ) - 1 ) ;
@ -1223,11 +1356,6 @@ static struct skinny_device *build_device(char *cat, struct ast_variable *v)
return d ;
}
static int has_voicemail ( struct skinny_line * l )
{
return ast_app_has_voicemail ( l - > mailbox , NULL ) ;
}
static int skinny_register ( skinny_req * req , struct skinnysession * s )
{
struct skinny_device * d ;
@ -1532,9 +1660,9 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout)
default :
ast_log ( LOG_ERROR , " Don't know how to deal with hookstate %d \n " , l - > hookstate ) ;
break ;
}
}
transmit_lamp_indication ( session , l- > instance , SKINNY_LAMP_BLINK ) ;
transmit_lamp_indication ( session , STIMULUS_LINE, l- > instance , SKINNY_LAMP_BLINK ) ;
transmit_ringer_mode ( session , SKINNY_RING_INSIDE ) ;
if ( ast - > cid . cid_num ) {
@ -1624,22 +1752,15 @@ static int skinny_hangup(struct ast_channel *ast)
if ( ( sub - > parent - > type = TYPE_LINE ) & & ( sub - > parent - > hookstate = = SKINNY_OFFHOOK ) ) {
sub - > parent - > hookstate = SKINNY_ONHOOK ;
transmit_callstate ( s , l - > instance , SKINNY_ONHOOK , sub - > callid ) ;
transmit_lamp_indication ( s , l - > instance , SKINNY_LAMP_OFF ) ;
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_lamp_indication ( s , STIMULUS_LINE , l - > instance , SKINNY_LAMP_OFF ) ;
transmit_speaker_mode ( s , SKINNY_SPEAKEROFF ) ;
} else if ( ( sub - > parent - > type = TYPE_LINE ) & & ( sub - > parent - > hookstate = = SKINNY_ONHOOK ) ) {
transmit_callstate ( s , l - > instance , SKINNY_ONHOOK , sub - > callid ) ;
transmit_speaker_mode ( s , SKINNY_SPEAKEROFF ) ;
transmit_ringer_mode ( s , SKINNY_RING_OFF ) ;
transmit_tone ( s , SKINNY_SILENCE ) ;
transmit_lamp_indication ( s , l - > instance , SKINNY_LAMP_OFF ) ;
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_lamp_indication ( s , STIMULUS_LINE , l - > instance , SKINNY_LAMP_OFF ) ;
do_housekeeping ( s ) ;
}
}
ast_mutex_lock ( & sub - > lock ) ;
@ -1943,7 +2064,7 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
free ( req ) ;
return 0 ;
}
switch ( req - > e ) {
case ALARM_MESSAGE :
/* no response necessary */
@ -1997,10 +2118,15 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
switch ( stimulus ) {
case STIMULUS_REDIAL :
/* XXX how we gonna deal with redial ?!?! */
/* If we can keep an array of dialed frames we can implement a quick
and dirty redial , feeding the frames we last got into the queue
function */
if ( skinnydebug ) {
ast_verbose ( " Recieved Stimulus: Redial(%d) \n " , stimulusInstance ) ;
}
break ;
case STIMULUS_SPEEDDIAL :
if ( skinnydebug ) {
@ -2021,8 +2147,48 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
/* figure out how to transfer */
break ;
case STIMULUS_CONFERENCE :
if ( skinnydebug ) {
ast_verbose ( " Recieved Stimulus: Transfer(%d) \n " , stimulusInstance ) ;
}
transmit_tone ( s , SKINNY_DIALTONE ) ;
/* figure out how to bridge n' stuff */
break ;
case STIMULUS_VOICEMAIL :
if ( skinnydebug ) {
ast_verbose ( " Recieved Stimulus: Voicemail(%d) \n " , stimulusInstance ) ;
}
/* Dial Voicemail */
break ;
case STIMULUS_CALLPARK :
if ( skinnydebug ) {
ast_verbose ( " Recieved Stimulus: Park Call(%d) \n " , stimulusInstance ) ;
}
break ;
case STIMULUS_FORWARDALL :
/* Do not disturb */
transmit_tone ( s , SKINNY_DIALTONE ) ;
if ( s - > device - > lines - > dnd ! = 0 ) {
if ( option_verbose > 2 ) {
ast_verbose ( VERBOSE_PREFIX_3 " Disabling 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 = 0 ;
transmit_lamp_indication ( s , STIMULUS_FORWARDALL , 1 , SKINNY_LAMP_ON ) ;
} 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 ) ;
}
break ;
case STIMULUS_FORWARDBUSY :
case STIMULUS_FORWARDNOANSWER :
/* Gonna be fun, not */
@ -2077,15 +2243,43 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_verbose ( " Buttontemplate requested \n " ) ;
}
memset ( req , 0 , SKINNY_MAX_PACKET ) ;
req - > len = sizeof ( button_template_res_message ) + 4 ;
req - > e = BUTTON_TEMPLATE_RES_MESSAGE ;
req - > data . buttontemplate . buttonOffset = 0 ;
req - > data . buttontemplate . buttonCount = 10 ;
req - > data . buttontemplate . totalButtonCount = 10 ;
/* XXX Figure out how to do this correctly */
memcpy ( req - > data . buttontemplate . definition ,
button_definition_hack ,
sizeof ( req - > data . buttontemplate . definition ) ) ;
/* XXX Less of a hack, more of a kludge now */
sub = find_subchannel_by_line ( s - > device - > lines ) ;
req - > len = sizeof ( button_template_res_message ) + 4 ;
if ( ! strcmp ( s - > device - > model , " 30VIP " ) ) {
req - > data . buttontemplate . buttonOffset = 0 ;
req - > data . buttontemplate . buttonCount = 30 ;
req - > data . buttontemplate . totalButtonCount = 30 ;
memcpy ( req - > data . buttontemplate . definition ,
thirtyvip_button_definition_hack ,
sizeof ( req - > data . buttontemplate . definition ) ) ;
if ( skinnydebug ) {
ast_verbose ( " Sending 30VIP template to %s@%s (%s) \n " , sub - > parent - > name , sub - > parent - > parent - > name , s - > device - > model ) ;
}
} else if ( ! strcmp ( s - > device - > model , " 12SP " ) ) {
req - > data . buttontemplate . buttonOffset = 0 ;
req - > data . buttontemplate . buttonCount = 12 ;
req - > data . buttontemplate . totalButtonCount = 12 ;
memcpy ( req - > data . buttontemplate . definition ,
twelvesp_button_definition_hack ,
sizeof ( req - > data . buttontemplate . definition ) ) ;
if ( skinnydebug ) {
ast_verbose ( " Sending 12SP template to %s@%s (%s) \n " , sub - > parent - > name , sub - > parent - > parent - > name , s - > device - > model ) ;
}
} else {
req - > data . buttontemplate . buttonOffset = 0 ;
req - > data . buttontemplate . buttonCount = 12 ;
req - > data . buttontemplate . totalButtonCount = 12 ;
memcpy ( req - > data . buttontemplate . definition ,
twelvesp_button_definition_hack ,
sizeof ( req - > data . buttontemplate . definition ) ) ;
if ( skinnydebug ) {
ast_verbose ( " Sending default template to %s@%s (%s) \n " , sub - > parent - > name , sub - > parent - > parent - > name , s - > device - > model ) ;
}
}
transmit_response ( s , req ) ;
break ;
case SOFT_KEY_SET_REQ_MESSAGE :
@ -2145,12 +2339,14 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
memset ( req , 0 , SKINNY_MAX_PACKET ) ;
req - > len = sizeof ( speed_dial_stat_res_message ) + 4 ;
req - > e = SPEED_DIAL_STAT_RES_MESSAGE ;
#if 0
#if 0
/* XXX Do this right XXX */
/* If the redial function works the way I think it will, a modification of it
can work here was well . Yikes . */
req - > data . speeddialreq . speedDialNumber = speedDialNum ;
snprintf ( req - > data . speeddial . speedDialDirNumber , sizeof ( req - > data . speeddial . speedDialDirNumber ) , " 31337 " ) ;
snprintf ( req - > data . speeddial . speedDialDisplayName , sizeof ( req - > data . speeddial . speedDialDisplayName ) , " Asterisk Rules! " ) ;
# endif
# endif
transmit_response ( s , req ) ;
break ;
case LINE_STATE_REQ_MESSAGE :
@ -2190,10 +2386,12 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
req - > len = 4 ;
req - > e = KEEP_ALIVE_ACK_MESSAGE ;
transmit_response ( s , req ) ;
do_housekeeping ( s ) ;
break ;
case OFFHOOK_MESSAGE :
transmit_ringer_mode ( s , SKINNY_RING_OFF ) ;
transmit_lamp_indication ( s , s- > device - > lines - > instance , SKINNY_LAMP_ON ) ;
transmit_lamp_indication ( s , STIMULUS_LINE, s- > device - > lines - > instance , SKINNY_LAMP_ON ) ;
sub = find_subchannel_by_line ( s - > device - > lines ) ;
if ( ! sub ) {
@ -2207,24 +2405,28 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
transmit_tone ( s , SKINNY_SILENCE ) ;
ast_setstate ( sub - > owner , AST_STATE_UP ) ;
/* XXX select the appropriate soft key here */
} else {
if ( ! sub - > owner ) {
transmit_callstate ( s , s - > device - > lines - > instance , SKINNY_OFFHOOK , sub - > callid ) ;
transmit_tone ( s , SKINNY_DIALTONE ) ;
c = skinny_new ( sub , AST_STATE_DOWN ) ;
if ( c ) {
/* start switch */
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 " , sub - > parent - > name , s - > device - > name ) ;
} else {
if ( ! sub - > owner ) {
transmit_callstate ( s , s - > device - > lines - > instance , SKINNY_OFFHOOK , sub - > callid ) ;
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_tone ( s , SKINNY_DIALTONE ) ;
c = skinny_new ( sub , AST_STATE_DOWN ) ;
if ( c ) {
/* start switch */
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_ DEBUG, " Current sub [%s] already has owner \n " , sub - > owner - > name ) ;
ast_log ( LOG_ WARNING, " Unable to create channel for %s@%s \n " , sub - > parent - > name , s - > device - > name ) ;
}
} else {
ast_log ( LOG_DEBUG , " Current sub [%s] already has owner \n " , sub - > owner - > name ) ;
}
}
break ;
case ONHOOK_MESSAGE :
@ -2265,20 +2467,10 @@ 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 */
if ( ( sub - > parent - > hookstate = = SKINNY_ONHOOK ) & & ( ! sub - > next - > rtp ) ) {
if ( has_voicemail ( sub - > parent ) ) {
transmit_lamp_indication ( s , s - > device - > lines - > instance , SKINNY_LAMP_FLASH ) ;
} else {
transmit_lamp_indication ( s , s - > device - > lines - > instance , SKINNY_LAMP_OFF ) ;
}
}
do_housekeeping ( s ) ;
}
break ;
case KEYPAD_BUTTON_MESSAGE :
digit = req - > data . keypad . button ;
@ -2360,6 +2552,7 @@ static int handle_message(skinny_req *req, struct skinnysession *s)
ast_verbose ( " RECEIVED UNKNOWN MESSAGE TYPE: %x \n " , req - > e ) ;
break ;
}
free ( req ) ;
return 1 ;