2007-05-06 13:54:52 +00:00
/*****************************************************************************\
* * * *
2007-07-26 12:23:56 +00:00
* * Linux Call Router * *
2007-05-06 13:54:52 +00:00
* * * *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * *
* * Copyright : Andreas Eversberg * *
* * * *
2008-04-13 17:52:42 +00:00
* * mISDN port abstraction for dss1 * *
2007-05-06 13:54:52 +00:00
* * * *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "main.h"
2008-04-13 17:52:42 +00:00
# include "myisdn.h"
2008-02-03 12:47:33 +00:00
2010-03-11 15:27:28 +00:00
# include <mISDN/mISDNcompat.h>
int __af_isdn = MISDN_AF_ISDN ;
# include <mISDN/q931.h>
2008-04-24 07:24:04 +00:00
# undef offsetof
# ifdef __compiler_offsetof
# define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
# else
# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
# endif
2009-06-28 15:29:07 +00:00
# ifndef container_of
2008-04-24 07:24:04 +00:00
# define container_of(ptr, type, member) ({ \
const typeof ( ( ( type * ) 0 ) - > member ) * __mptr = ( ptr ) ; \
( type * ) ( ( char * ) __mptr - offsetof ( type , member ) ) ; } )
2009-06-28 15:29:07 +00:00
# endif
2007-05-06 13:54:52 +00:00
2008-02-16 08:09:35 +00:00
// timeouts if activating/deactivating response from mISDN got lost
2008-04-12 16:24:31 +00:00
# define B_TIMER_ACTIVATING 1 // seconds
# define B_TIMER_DEACTIVATING 1 // seconds
2008-02-16 08:09:35 +00:00
2007-07-31 05:34:18 +00:00
/* list of mISDN ports */
struct mISDNport * mISDNport_first ;
2007-05-06 13:54:52 +00:00
/* noise randomizer */
unsigned char mISDN_rand [ 256 ] ;
int mISDN_rand_count = 0 ;
2008-06-14 06:34:50 +00:00
unsigned int mt_assign_pid = ~ 0 ;
2008-04-13 17:52:42 +00:00
2007-08-26 13:23:58 +00:00
int mISDNsocket = - 1 ;
2010-01-16 10:20:23 +00:00
static int upqueue_pipe [ 2 ] ;
static struct lcr_fd upqueue_fd ;
int upqueue_avail = 0 ;
static int mISDN_upqueue ( struct lcr_fd * fd , unsigned int what , void * instance , int i ) ;
static int mISDN_timeout ( struct lcr_timer * timer , void * instance , int i ) ;
2007-08-26 13:23:58 +00:00
2007-07-31 05:34:18 +00:00
int mISDN_initialize ( void )
{
2008-04-13 17:52:42 +00:00
char filename [ 256 ] ;
2007-07-31 05:34:18 +00:00
/* try to open raw socket to check kernel */
2007-08-26 13:23:58 +00:00
mISDNsocket = socket ( PF_ISDN , SOCK_RAW , ISDN_P_BASE ) ;
2009-05-14 18:31:43 +00:00
if ( mISDNsocket < 0 ) {
2010-03-11 15:27:28 +00:00
fprintf ( stderr , " Cannot open mISDN due to '%s'. (Does your Kernel support socket based mISDN? Protocol family is %d.) \n " , strerror ( errno ) , PF_ISDN ) ;
2007-07-31 05:34:18 +00:00
return ( - 1 ) ;
}
2008-05-09 19:31:58 +00:00
/* init mlayer3 */
init_layer3 ( 4 ) ; // buffer of 4
2008-03-24 10:13:44 +00:00
/* open debug, if enabled and not only stack debugging */
2009-05-14 18:31:43 +00:00
if ( options . deb ) {
2008-09-21 06:57:51 +00:00
SPRINT ( filename , " %s/debug.log " , LOG_DIR ) ;
2008-04-13 17:52:42 +00:00
debug_fp = fopen ( filename , " a " ) ;
2008-03-24 10:13:44 +00:00
}
2009-05-14 18:31:43 +00:00
if ( options . deb & DEBUG_STACK ) {
2008-09-21 06:57:51 +00:00
SPRINT ( filename , " %s/debug_mISDN.log " , LOG_DIR ) ;
2009-04-05 10:52:24 +00:00
mISDN_debug_init ( 0xfffffeff , filename , filename , filename ) ;
2007-08-26 13:23:58 +00:00
} else
2008-03-24 10:13:44 +00:00
mISDN_debug_init ( 0 , NULL , NULL , NULL ) ;
2007-08-26 13:23:58 +00:00
2010-01-16 10:20:23 +00:00
if ( pipe ( upqueue_pipe ) < 0 )
FATAL ( " Failed to open pipe \n " ) ;
2010-01-30 10:59:07 +00:00
memset ( & upqueue_fd , 0 , sizeof ( upqueue_fd ) ) ;
2010-01-16 10:20:23 +00:00
upqueue_fd . fd = upqueue_pipe [ 0 ] ;
register_fd ( & upqueue_fd , LCR_FD_READ , mISDN_upqueue , NULL , 0 ) ;
2007-07-31 05:34:18 +00:00
return ( 0 ) ;
}
void mISDN_deinitialize ( void )
{
cleanup_layer3 ( ) ;
2007-08-26 13:23:58 +00:00
mISDN_debug_close ( ) ;
2008-03-24 10:13:44 +00:00
if ( debug_fp )
fclose ( debug_fp ) ;
debug_fp = NULL ;
2007-08-26 13:23:58 +00:00
if ( mISDNsocket > - 1 )
close ( mISDNsocket ) ;
2010-01-16 10:20:23 +00:00
if ( upqueue_fd . inuse ) {
unregister_fd ( & upqueue_fd ) ;
close ( upqueue_pipe [ 0 ] ) ;
close ( upqueue_pipe [ 1 ] ) ;
}
upqueue_avail = 0 ;
2007-07-31 05:34:18 +00:00
}
2007-05-06 13:54:52 +00:00
2010-01-16 10:20:23 +00:00
int load_timer ( struct lcr_timer * timer , void * instance , int index ) ;
2007-05-06 13:54:52 +00:00
/*
* constructor
*/
2008-07-26 15:42:16 +00:00
PmISDN : : PmISDN ( int type , mISDNport * mISDNport , char * portname , struct port_settings * settings , int channel , int exclusive , int mode ) : Port ( type , portname , settings )
2007-05-06 13:54:52 +00:00
{
p_m_mISDNport = mISDNport ;
p_m_portnum = mISDNport - > portnum ;
p_m_b_index = - 1 ;
p_m_b_channel = 0 ;
p_m_b_exclusive = 0 ;
p_m_b_reserve = 0 ;
2008-07-26 15:42:16 +00:00
p_m_b_mode = mode ;
2007-05-06 13:54:52 +00:00
p_m_hold = 0 ;
2008-01-19 17:10:46 +00:00
p_m_tx_gain = mISDNport - > ifport - > interface - > tx_gain ;
p_m_rx_gain = mISDNport - > ifport - > interface - > rx_gain ;
2007-05-06 13:54:52 +00:00
p_m_conf = 0 ;
2009-09-26 11:20:29 +00:00
p_m_mute = 0 ;
2007-05-15 20:59:29 +00:00
p_m_txdata = 0 ;
2007-05-06 13:54:52 +00:00
p_m_delay = 0 ;
p_m_echo = 0 ;
p_m_tone = 0 ;
p_m_rxoff = 0 ;
2007-07-17 17:28:09 +00:00
p_m_joindata = 0 ;
2009-09-26 11:20:29 +00:00
p_m_inband_send_on = 0 ;
p_m_inband_receive_on = 0 ;
2007-06-27 06:23:50 +00:00
p_m_dtmf = ! mISDNport - > ifport - > nodtmf ;
2010-01-16 10:20:23 +00:00
memset ( & p_m_timeout , 0 , sizeof ( p_m_timeout ) ) ;
add_timer ( & p_m_timeout , mISDN_timeout , this , 0 ) ;
2007-08-12 08:16:19 +00:00
p_m_remote_ref = 0 ; /* channel shall be exported to given remote */
2008-06-07 09:49:28 +00:00
p_m_remote_id = 0 ; /* remote admin socket */
2008-01-06 14:49:29 +00:00
SCPY ( p_m_pipeline , mISDNport - > ifport - > interface - > pipeline ) ;
2007-07-15 10:01:27 +00:00
/* audio */
2010-01-16 10:20:23 +00:00
memset ( & p_m_loadtimer , 0 , sizeof ( p_m_loadtimer ) ) ;
add_timer ( & p_m_loadtimer , load_timer , this , 0 ) ;
2007-07-15 10:01:27 +00:00
p_m_load = 0 ;
p_m_last_tv_sec = 0 ;
2007-06-27 06:23:50 +00:00
/* crypt */
2007-05-06 13:54:52 +00:00
p_m_crypt = 0 ;
p_m_crypt_listen = 0 ;
p_m_crypt_msg_loops = 0 ;
p_m_crypt_msg_loops = 0 ;
p_m_crypt_msg_len = 0 ;
p_m_crypt_msg [ 0 ] = ' \0 ' ;
p_m_crypt_msg_current = 0 ;
p_m_crypt_key_len = 0 ;
p_m_crypt_listen = 0 ;
p_m_crypt_listen_state = 0 ;
p_m_crypt_listen_len = 0 ;
p_m_crypt_listen_msg [ 0 ] = ' \0 ' ;
p_m_crypt_listen_crc = 0 ;
2009-05-14 18:31:43 +00:00
if ( mISDNport - > ifport - > interface - > bf_len > = 4 & & mISDNport - > ifport - > interface - > bf_len < = 56 ) {
2008-01-06 14:49:29 +00:00
memcpy ( p_m_crypt_key , mISDNport - > ifport - > interface - > bf_key , p_m_crypt_key_len ) ;
p_m_crypt_key_len = mISDNport - > ifport - > interface - > bf_len ;
p_m_crypt = 1 ;
}
2007-05-06 13:54:52 +00:00
/* if any channel requested by constructor */
2009-05-14 18:31:43 +00:00
if ( channel = = CHANNEL_ANY ) {
2007-05-06 13:54:52 +00:00
/* reserve channel */
p_m_b_reserve = 1 ;
mISDNport - > b_reserved + + ;
}
/* reserve channel */
2007-06-27 06:23:50 +00:00
if ( channel > 0 ) // only if constructor was called with a channel resevation
2007-05-06 13:54:52 +00:00
seize_bchannel ( channel , exclusive ) ;
/* we increase the number of objects: */
mISDNport - > use + + ;
PDEBUG ( DEBUG_ISDN , " Created new mISDNPort(%s). Currently %d objects use, port #%d \n " , portname , mISDNport - > use , p_m_portnum ) ;
2009-09-26 11:20:29 +00:00
//inband_receive_on();
2007-05-06 13:54:52 +00:00
}
/*
* destructor
*/
PmISDN : : ~ PmISDN ( )
{
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-05-06 13:54:52 +00:00
2010-01-16 10:20:23 +00:00
del_timer ( & p_m_timeout ) ;
del_timer ( & p_m_loadtimer ) ;
2007-05-06 13:54:52 +00:00
/* remove bchannel relation */
2007-06-27 06:23:50 +00:00
drop_bchannel ( ) ;
2007-05-06 13:54:52 +00:00
/* release epoint */
2009-05-14 18:31:43 +00:00
while ( p_epointlist ) {
2007-05-06 13:54:52 +00:00
PDEBUG ( DEBUG_ISDN , " destroy mISDNPort(%s). endpoint still exists, releaseing. \n " , p_name ) ;
message = message_create ( p_serial , p_epointlist - > epoint_id , PORT_TO_EPOINT , MESSAGE_RELEASE ) ;
message - > param . disconnectinfo . cause = 16 ;
message - > param . disconnectinfo . location = LOCATION_PRIVATE_LOCAL ;
message_put ( message ) ;
/* remove from list */
free_epointlist ( p_epointlist ) ;
}
/* we decrease the number of objects: */
p_m_mISDNport - > use - - ;
PDEBUG ( DEBUG_ISDN , " destroyed mISDNPort(%s). Currently %d objects \n " , p_name , p_m_mISDNport - > use ) ;
}
2007-06-27 06:23:50 +00:00
/*
* trace
*/
2008-09-02 00:02:11 +00:00
void chan_trace_header ( struct mISDNport * mISDNport , class PmISDN * port , const char * msgtext , int direction )
2007-06-27 06:23:50 +00:00
{
/* init trace with given values */
2008-09-06 11:59:48 +00:00
start_trace ( mISDNport ? mISDNport - > portnum : - 1 ,
2007-07-07 15:13:20 +00:00
( mISDNport ) ? ( ( mISDNport - > ifport ) ? mISDNport - > ifport - > interface : NULL ) : NULL ,
2008-05-01 08:35:20 +00:00
port ? numberrize_callerinfo ( port - > p_callerinfo . id , port - > p_callerinfo . ntype , options . national , options . international ) : NULL ,
2007-07-07 15:13:20 +00:00
port ? port - > p_dialinginfo . id : NULL ,
2007-06-27 06:23:50 +00:00
direction ,
CATEGORY_CH ,
port ? port - > p_serial : 0 ,
msgtext ) ;
}
/*
* layer trace header
*/
static struct isdn_message {
2008-09-02 00:02:11 +00:00
const char * name ;
2008-06-14 06:34:50 +00:00
unsigned int value ;
2007-06-27 06:23:50 +00:00
} isdn_message [ ] = {
2008-04-12 16:24:31 +00:00
{ " PH_ACTIVATE " , L1_ACTIVATE_REQ } ,
{ " PH_DEACTIVATE " , L1_DEACTIVATE_REQ } ,
{ " DL_ESTABLISH " , L2_ESTABLISH_REQ } ,
{ " DL_RELEASE " , L2_RELEASE_REQ } ,
2009-03-20 17:47:31 +00:00
{ " UNKNOWN " , L3_UNKNOWN_REQ } ,
2008-04-12 16:24:31 +00:00
{ " MT_TIMEOUT " , L3_TIMEOUT_REQ } ,
{ " MT_SETUP " , L3_SETUP_REQ } ,
{ " MT_SETUP_ACK " , L3_SETUP_ACKNOWLEDGE_REQ } ,
{ " MT_PROCEEDING " , L3_PROCEEDING_REQ } ,
{ " MT_ALERTING " , L3_ALERTING_REQ } ,
{ " MT_CONNECT " , L3_CONNECT_REQ } ,
{ " MT_CONNECT_ACK " , L3_CONNECT_ACKNOWLEDGE_REQ } ,
{ " MT_DISCONNECT " , L3_DISCONNECT_REQ } ,
{ " MT_RELEASE " , L3_RELEASE_REQ } ,
{ " MT_RELEASE_COMP " , L3_RELEASE_COMPLETE_REQ } ,
{ " MT_INFORMATION " , L3_INFORMATION_REQ } ,
{ " MT_PROGRESS " , L3_PROGRESS_REQ } ,
{ " MT_NOTIFY " , L3_NOTIFY_REQ } ,
{ " MT_SUSPEND " , L3_SUSPEND_REQ } ,
{ " MT_SUSPEND_ACK " , L3_SUSPEND_ACKNOWLEDGE_REQ } ,
{ " MT_SUSPEND_REJ " , L3_SUSPEND_REJECT_REQ } ,
{ " MT_RESUME " , L3_RESUME_REQ } ,
{ " MT_RESUME_ACK " , L3_RESUME_ACKNOWLEDGE_REQ } ,
{ " MT_RESUME_REJ " , L3_RESUME_REJECT_REQ } ,
{ " MT_HOLD " , L3_HOLD_REQ } ,
{ " MT_HOLD_ACK " , L3_HOLD_ACKNOWLEDGE_REQ } ,
{ " MT_HOLD_REJ " , L3_HOLD_REJECT_REQ } ,
{ " MT_RETRIEVE " , L3_RETRIEVE_REQ } ,
{ " MT_RETRIEVE_ACK " , L3_RETRIEVE_ACKNOWLEDGE_REQ } ,
{ " MT_RETRIEVE_REJ " , L3_RETRIEVE_REJECT_REQ } ,
{ " MT_FACILITY " , L3_FACILITY_REQ } ,
{ " MT_STATUS " , L3_STATUS_REQ } ,
{ " MT_RESTART " , L3_RESTART_REQ } ,
2008-04-13 17:52:42 +00:00
{ " MT_NEW_L3ID " , L3_NEW_L3ID_REQ } ,
{ " MT_RELEASE_L3ID " , L3_RELEASE_L3ID_REQ } ,
2007-06-27 06:23:50 +00:00
{ NULL , 0 } ,
} ;
2008-09-02 00:02:11 +00:00
static const char * isdn_prim [ 4 ] = {
2007-06-27 06:23:50 +00:00
" REQUEST " ,
" CONFIRM " ,
" INDICATION " ,
" RESPONSE " ,
} ;
2008-06-14 06:34:50 +00:00
void l1l2l3_trace_header ( struct mISDNport * mISDNport , class PmISDN * port , unsigned int msg , int direction )
2007-06-27 06:23:50 +00:00
{
int i ;
2008-09-02 00:02:11 +00:00
char msgtext [ 64 ] ;
2007-06-27 06:23:50 +00:00
2008-09-02 00:02:11 +00:00
SCPY ( msgtext , " <<UNKNOWN MESSAGE>> " ) ;
2007-06-27 06:23:50 +00:00
/* select message and primitive text */
i = 0 ;
2009-05-14 18:31:43 +00:00
while ( isdn_message [ i ] . name ) {
2009-03-20 17:47:31 +00:00
// if (msg == L3_NOTIFY_REQ) printf("val = %x %s\n", isdn_message[i].value, isdn_message[i].name);
2009-05-14 18:31:43 +00:00
if ( isdn_message [ i ] . value = = ( msg & 0xffffff00 ) ) {
2007-06-27 06:23:50 +00:00
SCPY ( msgtext , isdn_message [ i ] . name ) ;
break ;
}
i + + ;
}
2008-04-12 16:24:31 +00:00
SCAT ( msgtext , isdn_prim [ msg & 0x00000003 ] ) ;
2007-06-27 06:23:50 +00:00
/* add direction */
2009-05-14 18:31:43 +00:00
if ( direction & & ( msg & 0xffffff00 ) ! = L3_NEW_L3ID_REQ & & ( msg & 0xffffff00 ) ! = L3_RELEASE_L3ID_REQ ) {
if ( mISDNport ) {
if ( mISDNport - > ntmode ) {
2007-06-27 06:23:50 +00:00
if ( direction = = DIRECTION_OUT )
SCAT ( msgtext , " N->U " ) ;
else
SCAT ( msgtext , " N<-U " ) ;
2009-05-14 18:31:43 +00:00
} else {
2007-06-27 06:23:50 +00:00
if ( direction = = DIRECTION_OUT )
SCAT ( msgtext , " U->N " ) ;
else
SCAT ( msgtext , " U<-N " ) ;
}
}
}
/* init trace with given values */
2008-09-06 11:59:48 +00:00
start_trace ( mISDNport ? mISDNport - > portnum : - 1 ,
2008-05-09 19:31:58 +00:00
mISDNport ? ( mISDNport - > ifport ? mISDNport - > ifport - > interface : NULL ) : NULL ,
2008-05-01 08:35:20 +00:00
port ? numberrize_callerinfo ( port - > p_callerinfo . id , port - > p_callerinfo . ntype , options . national , options . international ) : NULL ,
2007-07-07 15:13:20 +00:00
port ? port - > p_dialinginfo . id : NULL ,
2007-06-27 06:23:50 +00:00
direction ,
CATEGORY_CH ,
port ? port - > p_serial : 0 ,
msgtext ) ;
}
2007-05-06 13:54:52 +00:00
/*
* send control information to the channel ( dsp - module )
*/
2008-09-02 00:02:11 +00:00
void ph_control ( struct mISDNport * mISDNport , class PmISDN * isdnport , int sock , unsigned int c1 , unsigned int c2 , const char * trace_name , int trace_value )
2008-05-09 19:31:58 +00:00
{
2007-08-26 13:23:58 +00:00
unsigned char buffer [ MISDN_HEADER_LEN + sizeof ( int ) + sizeof ( int ) ] ;
struct mISDNhead * ctrl = ( struct mISDNhead * ) buffer ;
2008-06-14 06:34:50 +00:00
unsigned int * d = ( unsigned int * ) ( buffer + MISDN_HEADER_LEN ) ;
2007-08-26 13:23:58 +00:00
int ret ;
2008-05-09 19:31:58 +00:00
if ( sock < 0 )
return ;
2007-08-26 13:23:58 +00:00
ctrl - > prim = PH_CONTROL_REQ ;
ctrl - > id = 0 ;
* d + + = c1 ;
* d + + = c2 ;
2008-05-09 19:31:58 +00:00
ret = sendto ( sock , buffer , MISDN_HEADER_LEN + sizeof ( int ) * 2 , 0 , NULL , 0 ) ;
2008-05-10 19:40:23 +00:00
if ( ret < = 0 )
2008-05-09 19:31:58 +00:00
PERROR ( " Failed to send to socket %d \n " , sock ) ;
2007-06-27 06:23:50 +00:00
chan_trace_header ( mISDNport , isdnport , " BCHANNEL control " , DIRECTION_OUT ) ;
2008-04-24 07:24:04 +00:00
if ( c1 = = DSP_CONF_JOIN )
2007-07-15 10:01:27 +00:00
add_trace ( trace_name , NULL , " 0x%08x " , trace_value ) ;
else
add_trace ( trace_name , NULL , " %d " , trace_value ) ;
2007-06-27 06:23:50 +00:00
end_trace ( ) ;
2007-05-06 13:54:52 +00:00
}
2008-09-02 00:02:11 +00:00
void ph_control_block ( struct mISDNport * mISDNport , class PmISDN * isdnport , int sock , unsigned int c1 , void * c2 , int c2_len , const char * trace_name , int trace_value )
2008-05-09 19:31:58 +00:00
{
2007-08-26 13:23:58 +00:00
unsigned char buffer [ MISDN_HEADER_LEN + sizeof ( int ) + c2_len ] ;
struct mISDNhead * ctrl = ( struct mISDNhead * ) buffer ;
2008-06-14 06:34:50 +00:00
unsigned int * d = ( unsigned int * ) ( buffer + MISDN_HEADER_LEN ) ;
2007-08-26 13:23:58 +00:00
int ret ;
2008-05-09 19:31:58 +00:00
if ( sock < 0 )
return ;
2007-08-26 13:23:58 +00:00
ctrl - > prim = PH_CONTROL_REQ ;
ctrl - > id = 0 ;
* d + + = c1 ;
memcpy ( d , c2 , c2_len ) ;
2008-05-09 19:31:58 +00:00
ret = sendto ( sock , buffer , MISDN_HEADER_LEN + sizeof ( int ) + c2_len , 0 , NULL , 0 ) ;
2008-05-10 19:40:23 +00:00
if ( ret < = 0 )
2008-05-09 19:31:58 +00:00
PERROR ( " Failed to send to socket %d \n " , sock ) ;
2007-06-27 06:23:50 +00:00
chan_trace_header ( mISDNport , isdnport , " BCHANNEL control " , DIRECTION_OUT ) ;
add_trace ( trace_name , NULL , " %d " , trace_value ) ;
end_trace ( ) ;
2007-05-06 13:54:52 +00:00
}
2010-01-16 10:20:23 +00:00
static int b_sock_callback ( struct lcr_fd * fd , unsigned int what , void * instance , int i ) ;
2007-05-06 13:54:52 +00:00
/*
2007-06-27 06:23:50 +00:00
* subfunction for bchannel_event
* create stack
2007-05-06 13:54:52 +00:00
*/
2007-06-27 06:23:50 +00:00
static int _bchannel_create ( struct mISDNport * mISDNport , int i )
2007-05-06 13:54:52 +00:00
{
2007-08-26 13:23:58 +00:00
int ret ;
2008-04-13 17:52:42 +00:00
struct sockaddr_mISDN addr ;
2007-08-26 13:23:58 +00:00
2010-01-16 10:20:23 +00:00
if ( mISDNport - > b_sock [ i ] . inuse ) {
2007-08-26 13:23:58 +00:00
PERROR ( " Error: Socket already created for index %d \n " , i ) ;
return ( 0 ) ;
}
/* open socket */
2008-05-09 19:31:58 +00:00
//#warning testing without DSP
2010-01-16 10:20:23 +00:00
// mISDNport->b_sock[i].fd = socket(PF_ISDN, SOCK_DGRAM, (mISDNport->b_mode[i]==B_MODE_HDLC)?ISDN_P_B_HDLC:ISDN_P_B_RAW);
mISDNport - > b_sock [ i ] . fd = socket ( PF_ISDN , SOCK_DGRAM , ( mISDNport - > b_mode [ i ] = = B_MODE_HDLC ) ? ISDN_P_B_L2DSPHDLC : ISDN_P_B_L2DSP ) ;
if ( mISDNport - > b_sock [ i ] . fd < 0 ) {
2008-09-12 05:43:21 +00:00
PERROR ( " Error: Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDN_dsp.ko? \n " , i ) ;
2007-08-26 13:23:58 +00:00
return ( 0 ) ;
}
2010-01-16 10:20:23 +00:00
/* register callback for read */
register_fd ( & mISDNport - > b_sock [ i ] , LCR_FD_READ , b_sock_callback , mISDNport , i ) ;
2007-08-26 13:23:58 +00:00
/* bind socket to bchannel */
addr . family = AF_ISDN ;
2008-09-06 11:59:48 +00:00
addr . dev = mISDNport - > portnum ;
2007-08-26 13:23:58 +00:00
addr . channel = i + 1 + ( i > = 15 ) ;
2010-01-16 10:20:23 +00:00
ret = bind ( mISDNport - > b_sock [ i ] . fd , ( struct sockaddr * ) & addr , sizeof ( addr ) ) ;
2009-05-14 18:31:43 +00:00
if ( ret < 0 ) {
2008-09-14 12:37:51 +00:00
PERROR ( " Error: Failed to bind bchannel-socket for index %d with mISDN-DSP layer (errno=%d). Did you load mISDN_dsp.ko? \n " , i , errno ) ;
2010-01-16 10:20:23 +00:00
close ( mISDNport - > b_sock [ i ] . fd ) ;
unregister_fd ( & mISDNport - > b_sock [ i ] ) ;
2007-08-26 13:23:58 +00:00
return ( 0 ) ;
}
chan_trace_header ( mISDNport , mISDNport - > b_port [ i ] , " BCHANNEL create socket " , DIRECTION_OUT ) ;
add_trace ( " channel " , NULL , " %d " , i + 1 + ( i > = 15 ) ) ;
2010-01-16 10:20:23 +00:00
add_trace ( " socket " , NULL , " %d " , mISDNport - > b_sock [ i ] . fd ) ;
2007-08-26 13:23:58 +00:00
end_trace ( ) ;
2008-04-13 17:52:42 +00:00
return ( 1 ) ;
2007-06-27 06:23:50 +00:00
}
/*
* subfunction for bchannel_event
2007-08-11 13:57:58 +00:00
* activate / deactivate request
2007-06-27 06:23:50 +00:00
*/
2010-01-16 10:20:23 +00:00
static void _bchannel_activate ( struct mISDNport * mISDNport , int i , int activate , int timeout )
2007-06-27 06:23:50 +00:00
{
2007-08-26 13:23:58 +00:00
struct mISDNhead act ;
int ret ;
2010-01-16 10:20:23 +00:00
if ( ! mISDNport - > b_sock [ i ] . inuse )
2008-05-09 19:31:58 +00:00
return ;
act . prim = ( activate ) ? PH_ACTIVATE_REQ : PH_DEACTIVATE_REQ ;
2007-08-26 13:23:58 +00:00
act . id = 0 ;
2010-01-16 10:20:23 +00:00
ret = sendto ( mISDNport - > b_sock [ i ] . fd , & act , MISDN_HEADER_LEN , 0 , NULL , 0 ) ;
2008-05-10 19:40:23 +00:00
if ( ret < = 0 )
2010-01-16 10:20:23 +00:00
PERROR ( " Failed to send to socket %d \n " , mISDNport - > b_sock [ i ] . fd ) ;
2007-08-26 13:23:58 +00:00
/* trace */
2008-09-02 00:02:11 +00:00
chan_trace_header ( mISDNport , mISDNport - > b_port [ i ] , activate ? " BCHANNEL activate " : " BCHANNEL deactivate " , DIRECTION_OUT ) ;
2007-08-26 13:23:58 +00:00
add_trace ( " channel " , NULL , " %d " , i + 1 + ( i > = 15 ) ) ;
2010-01-16 10:20:23 +00:00
if ( timeout )
2008-02-16 08:09:35 +00:00
add_trace ( " event " , NULL , " timeout recovery " ) ;
2007-08-26 13:23:58 +00:00
end_trace ( ) ;
2007-06-27 06:23:50 +00:00
}
/*
* subfunction for bchannel_event
* set features
*/
static void _bchannel_configure ( struct mISDNport * mISDNport , int i )
{
struct PmISDN * port ;
2008-07-26 15:42:16 +00:00
int handle , mode ;
2007-08-26 13:23:58 +00:00
2010-01-16 10:20:23 +00:00
if ( ! mISDNport - > b_sock [ i ] . inuse )
2008-05-09 19:31:58 +00:00
return ;
2010-01-16 10:20:23 +00:00
handle = mISDNport - > b_sock [ i ] . fd ;
2008-04-24 07:24:04 +00:00
port = mISDNport - > b_port [ i ] ;
2008-07-26 15:42:16 +00:00
mode = mISDNport - > b_mode [ i ] ;
2009-05-14 18:31:43 +00:00
if ( ! port ) {
2008-04-24 07:24:04 +00:00
PERROR ( " bchannel index i=%d not associated with a port object \n " , i ) ;
return ;
}
/* set dsp features */
if ( port - > p_m_txdata )
ph_control ( mISDNport , port , handle , ( port - > p_m_txdata ) ? DSP_TXDATA_ON : DSP_TXDATA_OFF , 0 , " DSP-TXDATA " , port - > p_m_txdata ) ;
2008-07-26 15:42:16 +00:00
if ( port - > p_m_delay & & mode = = B_MODE_TRANSPARENT )
2008-04-24 07:24:04 +00:00
ph_control ( mISDNport , port , handle , DSP_DELAY , port - > p_m_delay , " DSP-DELAY " , port - > p_m_delay ) ;
2008-07-26 15:42:16 +00:00
if ( port - > p_m_tx_gain & & mode = = B_MODE_TRANSPARENT )
2008-04-24 07:24:04 +00:00
ph_control ( mISDNport , port , handle , DSP_VOL_CHANGE_TX , port - > p_m_tx_gain , " DSP-TX_GAIN " , port - > p_m_tx_gain ) ;
2008-07-26 15:42:16 +00:00
if ( port - > p_m_rx_gain & & mode = = B_MODE_TRANSPARENT )
2008-04-24 07:24:04 +00:00
ph_control ( mISDNport , port , handle , DSP_VOL_CHANGE_RX , port - > p_m_rx_gain , " DSP-RX_GAIN " , port - > p_m_rx_gain ) ;
2008-07-26 15:42:16 +00:00
if ( port - > p_m_pipeline [ 0 ] & & mode = = B_MODE_TRANSPARENT )
2008-04-24 07:24:04 +00:00
ph_control_block ( mISDNport , port , handle , DSP_PIPELINE_CFG , port - > p_m_pipeline , strlen ( port - > p_m_pipeline ) + 1 , " DSP-PIPELINE " , 0 ) ;
2009-09-26 11:20:29 +00:00
if ( port - > p_m_conf & & ! port - > p_m_mute )
2008-04-24 07:24:04 +00:00
ph_control ( mISDNport , port , handle , DSP_CONF_JOIN , port - > p_m_conf , " DSP-CONF " , port - > p_m_conf ) ;
if ( port - > p_m_echo )
ph_control ( mISDNport , port , handle , DSP_ECHO_ON , 0 , " DSP-ECHO " , 1 ) ;
2008-07-26 15:42:16 +00:00
if ( port - > p_m_tone & & mode = = B_MODE_TRANSPARENT )
2008-04-24 07:24:04 +00:00
ph_control ( mISDNport , port , handle , DSP_TONE_PATT_ON , port - > p_m_tone , " DSP-TONE " , port - > p_m_tone ) ;
if ( port - > p_m_rxoff )
ph_control ( mISDNport , port , handle , DSP_RECEIVE_OFF , 0 , " DSP-RXOFF " , 1 ) ;
2008-07-26 15:42:16 +00:00
// if (port->p_m_txmix && mode == B_MODE_TRANSPARENT)
2008-04-24 07:24:04 +00:00
// ph_control(mISDNport, port, handle, DSP_MIX_ON, 0, "DSP-MIX", 1);
2008-07-26 15:42:16 +00:00
if ( port - > p_m_dtmf & & mode = = B_MODE_TRANSPARENT )
2008-04-24 07:24:04 +00:00
ph_control ( mISDNport , port , handle , DTMF_TONE_START , 0 , " DSP-DTMF " , 1 ) ;
2008-07-26 15:42:16 +00:00
if ( port - > p_m_crypt & & mode = = B_MODE_TRANSPARENT )
2008-04-24 07:24:04 +00:00
ph_control_block ( mISDNport , port , handle , DSP_BF_ENABLE_KEY , port - > p_m_crypt_key , port - > p_m_crypt_key_len , " DSP-CRYPT " , port - > p_m_crypt_key_len ) ;
2007-05-06 13:54:52 +00:00
}
2009-09-26 11:20:29 +00:00
void PmISDN : : set_conf ( int oldconf , int newconf )
{
if ( oldconf ! = newconf ) {
PDEBUG ( DEBUG_BCHANNEL , " we change conference from conf=%d to conf=%d. \n " , oldconf , newconf ) ;
if ( p_m_b_index > - 1 )
if ( p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE )
2010-01-16 10:20:23 +00:00
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , ( newconf ) ? DSP_CONF_JOIN : DSP_CONF_SPLIT , newconf , " DSP-CONF " , newconf ) ;
2009-09-26 11:20:29 +00:00
} else
PDEBUG ( DEBUG_BCHANNEL , " we already have conf=%d. \n " , newconf ) ;
}
2007-06-27 06:23:50 +00:00
/*
* subfunction for bchannel_event
* destroy stack
*/
static void _bchannel_destroy ( struct mISDNport * mISDNport , int i )
{
2010-01-16 10:20:23 +00:00
if ( ! mISDNport - > b_sock [ i ] . inuse )
2008-05-09 19:31:58 +00:00
return ;
2007-08-26 13:23:58 +00:00
chan_trace_header ( mISDNport , mISDNport - > b_port [ i ] , " BCHANNEL remove socket " , DIRECTION_OUT ) ;
add_trace ( " channel " , NULL , " %d " , i + 1 + ( i > = 15 ) ) ;
2010-01-16 10:20:23 +00:00
add_trace ( " socket " , NULL , " %d " , mISDNport - > b_sock [ i ] . fd ) ;
2007-08-26 13:23:58 +00:00
end_trace ( ) ;
2010-01-16 10:20:23 +00:00
close ( mISDNport - > b_sock [ i ] . fd ) ;
unregister_fd ( & mISDNport - > b_sock [ i ] ) ;
2007-06-27 06:23:50 +00:00
}
2007-05-06 13:54:52 +00:00
2007-06-27 06:23:50 +00:00
/*
bchannel procedure
- - - - - - - - - - - - - - - - - -
A bchannel goes through the following states in this order :
- B_STATE_IDLE
No one is using the bchannel .
It is available and not linked to Port class , nor reserved .
- B_STATE_ACTIVATING
The bchannel stack is created and an activation request is sent .
It MAY be linked to Port class , but already unlinked due to Port class removal .
- B_STATE_ACTIVE
The bchannel is active and cofigured to the Port class needs .
Also it is linked to a Port class , otherwhise it would be deactivated .
- B_STATE_DEACTIVATING
The bchannel is in deactivating state , due to deactivation request .
It may be linked to a Port class , that likes to reactivate it .
- B_STATE_IDLE
See above .
After deactivating bchannel , and if not used , the bchannel becomes idle again .
2007-08-11 13:57:58 +00:00
Also the bchannel may be exported , but only if the state is or becomes idle :
- B_STATE_EXPORTING
The bchannel assignment has been sent to the remove application .
- B_STATE_REMOTE
The bchannel assignment is acknowledged by the remote application .
- B_STATE_IMPORTING
The bchannel is re - imported by mISDN port object .
- B_STATE_IDLE
See above .
After re - importing bchannel , and if not used , the bchannel becomes idle again .
2007-06-27 06:23:50 +00:00
A bchannel can have the following events :
2007-08-11 13:57:58 +00:00
- B_EVENT_USE
2007-06-27 06:23:50 +00:00
A bchannel is required by a Port class .
- B_EVENT_ACTIVATED
The bchannel beomes active .
2007-08-11 13:57:58 +00:00
- B_EVENT_DROP
2007-06-27 06:23:50 +00:00
The bchannel is not required by Port class anymore
- B_EVENT_DEACTIVATED
The bchannel becomes inactive .
2007-08-11 13:57:58 +00:00
- B_EVENT_EXPORTED
The bchannel is now used by remote application .
- B_EVENT_IMPORTED
The bchannel is not used by remote application .
2008-06-01 16:52:10 +00:00
- B_EVENT_EXPORTREQUEST
The bchannel shall be exported to the remote application .
- B_EVENT_IMPORTREQUEST
The bchannel is released from the remote application .
2007-06-27 06:23:50 +00:00
All actions taken on these events depend on the current bchannel ' s state and if it is linked to a Port class .
2007-08-13 21:29:09 +00:00
if an export request is receive by remote application , p_m_remote_ * is set .
the b_remote_ * [ index ] indicates if and where the channel is exported to . ( set from the point on , where export is initiated , until imported is acknowledged . )
2007-08-12 08:16:19 +00:00
- set on export request from remote application ( if port is assigned )
2007-08-13 21:29:09 +00:00
- set on channel use , if requested by remote application ( p_m_remote_ * )
2007-08-12 08:16:19 +00:00
- cleared on drop request
the bchannel will be exported with ref and stack given . remote application uses the ref to link bchannel to the call .
the bchannel will be imported with stack given only . remote application must store stack id with the bchannel process .
the bchannel import / export is acknowledged with stack given .
2007-08-13 21:29:09 +00:00
if exporting , b_remote_ * [ index ] is set to the remote socket id .
if importing has been acknowledged . b_remote_ * [ index ] is cleared .
2007-08-12 08:16:19 +00:00
2007-06-27 06:23:50 +00:00
*/
/*
* process bchannel events
* - mISDNport is a pointer to the port ' s structure
* - i is the index of the bchannel
* - event is the B_EVENT_ * value
* - port is the PmISDN class pointer
*/
2007-08-12 08:16:19 +00:00
void bchannel_event ( struct mISDNport * mISDNport , int i , int event )
2007-06-27 06:23:50 +00:00
{
2007-08-11 13:57:58 +00:00
class PmISDN * b_port = mISDNport - > b_port [ i ] ;
2007-06-27 06:23:50 +00:00
int state = mISDNport - > b_state [ i ] ;
2010-01-16 10:20:23 +00:00
int timer = - 1 ; // no change
2008-06-14 06:34:50 +00:00
unsigned int p_m_remote_ref = 0 ;
unsigned int p_m_remote_id = 0 ;
2008-01-19 17:10:46 +00:00
int p_m_tx_gain = 0 ;
int p_m_rx_gain = 0 ;
char * p_m_pipeline = NULL ;
unsigned char * p_m_crypt_key = NULL ;
int p_m_crypt_key_len = 0 ;
int p_m_crypt_key_type = 0 ;
2008-06-14 06:34:50 +00:00
unsigned int portid = ( mISDNport - > portnum < < 8 ) + i + 1 + ( i > = 15 ) ;
2007-07-07 15:13:20 +00:00
2009-05-14 18:31:43 +00:00
if ( b_port ) {
2007-08-12 08:16:19 +00:00
p_m_remote_id = b_port - > p_m_remote_id ;
p_m_remote_ref = b_port - > p_m_remote_ref ;
2008-01-19 17:10:46 +00:00
p_m_tx_gain = b_port - > p_m_tx_gain ;
p_m_rx_gain = b_port - > p_m_rx_gain ;
p_m_pipeline = b_port - > p_m_pipeline ;
p_m_crypt_key = b_port - > p_m_crypt_key ;
p_m_crypt_key_len = b_port - > p_m_crypt_key_len ;
p_m_crypt_key_type = /*b_port->p_m_crypt_key_type*/ 1 ;
2007-08-12 08:16:19 +00:00
}
2009-05-14 18:31:43 +00:00
switch ( event ) {
2007-08-11 13:57:58 +00:00
case B_EVENT_USE :
2007-07-07 15:13:20 +00:00
/* port must be linked in order to allow activation */
2007-08-11 13:57:58 +00:00
if ( ! b_port )
2007-07-15 10:01:27 +00:00
FATAL ( " bchannel must be linked to a Port class \n " ) ;
2009-05-14 18:31:43 +00:00
switch ( state ) {
2007-06-27 06:23:50 +00:00
case B_STATE_IDLE :
2009-05-14 18:31:43 +00:00
if ( p_m_remote_ref ) {
2007-08-11 13:57:58 +00:00
/* export bchannel */
2010-12-13 08:22:49 +00:00
message_bchannel_to_remote ( p_m_remote_id , p_m_remote_ref , BCHANNEL_ASSIGN , portid , p_m_tx_gain , p_m_rx_gain , p_m_pipeline , p_m_crypt_key , p_m_crypt_key_len , p_m_crypt_key_type , 0 ) ;
2007-08-11 13:57:58 +00:00
chan_trace_header ( mISDNport , b_port , " MESSAGE_BCHANNEL (to remote application) " , DIRECTION_NONE ) ;
add_trace ( " type " , NULL , " assign " ) ;
2007-08-29 16:56:03 +00:00
add_trace ( " channel " , NULL , " %d.%d " , portid > > 8 , portid & 0xff ) ;
2007-08-11 13:57:58 +00:00
end_trace ( ) ;
state = B_STATE_EXPORTING ;
2007-08-12 08:16:19 +00:00
mISDNport - > b_remote_id [ i ] = p_m_remote_id ;
2007-08-13 21:29:09 +00:00
mISDNport - > b_remote_ref [ i ] = p_m_remote_ref ;
2009-05-14 18:31:43 +00:00
} else {
2007-08-11 13:57:58 +00:00
/* create stack and send activation request */
2009-05-14 18:31:43 +00:00
if ( _bchannel_create ( mISDNport , i ) ) {
2010-01-16 10:20:23 +00:00
_bchannel_activate ( mISDNport , i , 1 , 0 ) ;
2007-08-11 13:57:58 +00:00
state = B_STATE_ACTIVATING ;
2010-01-16 10:20:23 +00:00
timer = B_TIMER_ACTIVATING ;
2007-08-11 13:57:58 +00:00
}
2007-05-06 13:54:52 +00:00
}
2007-06-27 06:23:50 +00:00
break ;
case B_STATE_ACTIVATING :
2007-08-11 13:57:58 +00:00
case B_STATE_EXPORTING :
/* do nothing, because it is already activating */
break ;
case B_STATE_DEACTIVATING :
case B_STATE_IMPORTING :
/* do nothing, because we must wait until we can reactivate */
break ;
default :
/* problems that might ocurr:
* B_EVENT_USE is received when channel already in use .
* bchannel exported , but not freed by other port
*/
PERROR ( " Illegal event %d at state %d, please correct. \n " , event , state ) ;
}
break ;
case B_EVENT_EXPORTREQUEST :
/* special case where the bchannel is requested by remote */
2009-05-14 18:31:43 +00:00
if ( ! p_m_remote_ref ) {
2007-08-12 08:16:19 +00:00
PERROR ( " export request without remote channel set, please correct. \n " ) ;
break ;
2007-08-11 13:57:58 +00:00
}
2009-05-14 18:31:43 +00:00
switch ( state ) {
2007-08-11 13:57:58 +00:00
case B_STATE_IDLE :
2007-08-12 08:16:19 +00:00
/* in case, the bchannel is exported right after seize_bchannel */
2007-08-11 13:57:58 +00:00
/* export bchannel */
2007-08-12 08:16:19 +00:00
/* p_m_remote_id is set, when this event happens. */
2010-12-13 08:22:49 +00:00
message_bchannel_to_remote ( p_m_remote_id , p_m_remote_ref , BCHANNEL_ASSIGN , portid , p_m_tx_gain , p_m_rx_gain , p_m_pipeline , p_m_crypt_key , p_m_crypt_key_len , p_m_crypt_key_type , 0 ) ;
2007-08-11 13:57:58 +00:00
chan_trace_header ( mISDNport , b_port , " MESSAGE_BCHANNEL (to remote application) " , DIRECTION_NONE ) ;
add_trace ( " type " , NULL , " assign " ) ;
2007-08-29 16:56:03 +00:00
add_trace ( " channel " , NULL , " %d.%d " , portid > > 8 , portid & 0xff ) ;
2007-08-11 13:57:58 +00:00
end_trace ( ) ;
state = B_STATE_EXPORTING ;
2007-08-12 08:16:19 +00:00
mISDNport - > b_remote_id [ i ] = p_m_remote_id ;
2007-08-13 21:29:09 +00:00
mISDNport - > b_remote_ref [ i ] = p_m_remote_ref ;
2007-08-11 13:57:58 +00:00
break ;
case B_STATE_ACTIVATING :
case B_STATE_EXPORTING :
2007-06-27 06:23:50 +00:00
/* do nothing, because it is already activating */
break ;
case B_STATE_DEACTIVATING :
2007-08-11 13:57:58 +00:00
case B_STATE_IMPORTING :
2007-06-27 06:23:50 +00:00
/* do nothing, because we must wait until we can reactivate */
break ;
2007-08-11 13:57:58 +00:00
case B_STATE_ACTIVE :
/* bchannel is active, so we deactivate */
2010-01-16 10:20:23 +00:00
_bchannel_activate ( mISDNport , i , 0 , 0 ) ;
2007-08-11 13:57:58 +00:00
state = B_STATE_DEACTIVATING ;
2010-01-16 10:20:23 +00:00
timer = B_TIMER_DEACTIVATING ;
2007-08-11 13:57:58 +00:00
break ;
2007-06-27 06:23:50 +00:00
default :
2007-08-11 13:57:58 +00:00
/* problems that might ocurr:
* . . . when channel already in use .
* bchannel exported , but not freed by other port
*/
2007-06-27 06:23:50 +00:00
PERROR ( " Illegal event %d at state %d, please correct. \n " , event , state ) ;
}
break ;
2008-06-01 16:52:10 +00:00
case B_EVENT_IMPORTREQUEST :
/* special case where the bchannel is released by remote */
2009-05-14 18:31:43 +00:00
if ( p_m_remote_ref ) {
2008-06-01 16:52:10 +00:00
PERROR ( " import request with remote channel set, please correct. \n " ) ;
break ;
}
2009-05-14 18:31:43 +00:00
switch ( state ) {
2008-06-01 16:52:10 +00:00
case B_STATE_IDLE :
case B_STATE_ACTIVE :
/* bchannel is not exported */
break ;
case B_STATE_ACTIVATING :
case B_STATE_EXPORTING :
/* do nothing because we must wait until bchanenl is active before deactivating */
break ;
case B_STATE_REMOTE :
/* bchannel is exported, so we re-import */
2010-12-13 08:22:49 +00:00
message_bchannel_to_remote ( mISDNport - > b_remote_id [ i ] , 0 , BCHANNEL_REMOVE , portid , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
2008-06-01 16:52:10 +00:00
chan_trace_header ( mISDNport , b_port , " MESSAGE_BCHANNEL (to remote application) " , DIRECTION_NONE ) ;
add_trace ( " type " , NULL , " remove " ) ;
add_trace ( " channel " , NULL , " %d.%d " , portid > > 8 , portid & 0xff ) ;
end_trace ( ) ;
state = B_STATE_IMPORTING ;
break ;
case B_STATE_DEACTIVATING :
case B_STATE_IMPORTING :
/* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
break ;
default :
PERROR ( " Illegal event %d at state %d, please correct. \n " , event , state ) ;
}
break ;
2007-06-27 06:23:50 +00:00
case B_EVENT_ACTIVATED :
2008-02-16 08:09:35 +00:00
timer = 0 ;
2009-05-14 18:31:43 +00:00
switch ( state ) {
2007-06-27 06:23:50 +00:00
case B_STATE_ACTIVATING :
2009-05-14 18:31:43 +00:00
if ( b_port & & ! p_m_remote_id ) {
2007-06-27 06:23:50 +00:00
/* bchannel is active and used by Port class, so we configure bchannel */
_bchannel_configure ( mISDNport , i ) ;
state = B_STATE_ACTIVE ;
2008-07-30 17:35:28 +00:00
b_port - > p_m_load = 0 ;
2009-05-14 18:31:43 +00:00
} else {
2007-08-11 13:57:58 +00:00
/* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
2010-01-16 10:20:23 +00:00
_bchannel_activate ( mISDNport , i , 0 , 0 ) ;
2007-06-27 06:23:50 +00:00
state = B_STATE_DEACTIVATING ;
2010-01-16 10:20:23 +00:00
timer = B_TIMER_DEACTIVATING ;
2007-05-06 13:54:52 +00:00
}
2007-06-27 06:23:50 +00:00
break ;
default :
PERROR ( " Illegal event %d at state %d, please correct. \n " , event , state ) ;
}
break ;
2007-08-11 13:57:58 +00:00
case B_EVENT_EXPORTED :
2009-05-14 18:31:43 +00:00
switch ( state ) {
2007-08-11 13:57:58 +00:00
case B_STATE_EXPORTING :
2009-05-14 18:31:43 +00:00
if ( b_port & & p_m_remote_ref & & p_m_remote_ref = = mISDNport - > b_remote_ref [ i ] ) {
2007-08-11 13:57:58 +00:00
/* remote export done */
state = B_STATE_REMOTE ;
2009-05-14 18:31:43 +00:00
} else {
2007-08-13 21:29:09 +00:00
/* bchannel is now exported, but we need bchannel back
* OR bchannel is not used anymore
* OR bchannel has been exported to an obsolete ref ,
* so reimport , to later export to new remote */
2010-12-13 08:22:49 +00:00
message_bchannel_to_remote ( mISDNport - > b_remote_id [ i ] , 0 , BCHANNEL_REMOVE , portid , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
2007-08-11 13:57:58 +00:00
chan_trace_header ( mISDNport , b_port , " MESSAGE_BCHANNEL (to remote application) " , DIRECTION_NONE ) ;
add_trace ( " type " , NULL , " remove " ) ;
2007-08-29 16:56:03 +00:00
add_trace ( " channel " , NULL , " %d.%d " , portid > > 8 , portid & 0xff ) ;
2007-08-11 13:57:58 +00:00
end_trace ( ) ;
state = B_STATE_IMPORTING ;
}
break ;
default :
PERROR ( " Illegal event %d at state %d, please correct. \n " , event , state ) ;
}
break ;
case B_EVENT_DROP :
if ( ! b_port )
2007-07-15 10:01:27 +00:00
FATAL ( " bchannel must be linked to a Port class \n " ) ;
2009-05-14 18:31:43 +00:00
switch ( state ) {
2007-06-27 06:23:50 +00:00
case B_STATE_IDLE :
/* bchannel is idle due to an error, so we do nothing */
break ;
case B_STATE_ACTIVATING :
2007-08-11 13:57:58 +00:00
case B_STATE_EXPORTING :
2007-06-27 06:23:50 +00:00
/* do nothing because we must wait until bchanenl is active before deactivating */
break ;
case B_STATE_ACTIVE :
/* bchannel is active, so we deactivate */
2010-01-16 10:20:23 +00:00
_bchannel_activate ( mISDNport , i , 0 , 0 ) ;
2007-06-27 06:23:50 +00:00
state = B_STATE_DEACTIVATING ;
2010-01-16 10:20:23 +00:00
timer = B_TIMER_DEACTIVATING ;
2007-06-27 06:23:50 +00:00
break ;
2007-08-11 13:57:58 +00:00
case B_STATE_REMOTE :
/* bchannel is exported, so we re-import */
2010-12-13 08:22:49 +00:00
message_bchannel_to_remote ( mISDNport - > b_remote_id [ i ] , 0 , BCHANNEL_REMOVE , portid , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
2007-08-11 13:57:58 +00:00
chan_trace_header ( mISDNport , b_port , " MESSAGE_BCHANNEL (to remote application) " , DIRECTION_NONE ) ;
add_trace ( " type " , NULL , " remove " ) ;
2007-08-29 16:56:03 +00:00
add_trace ( " channel " , NULL , " %d.%d " , portid > > 8 , portid & 0xff ) ;
2007-08-11 13:57:58 +00:00
end_trace ( ) ;
state = B_STATE_IMPORTING ;
break ;
2007-06-27 06:23:50 +00:00
case B_STATE_DEACTIVATING :
2007-08-11 13:57:58 +00:00
case B_STATE_IMPORTING :
2007-06-27 06:23:50 +00:00
/* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
break ;
default :
PERROR ( " Illegal event %d at state %d, please correct. \n " , event , state ) ;
}
break ;
case B_EVENT_DEACTIVATED :
2008-02-16 08:09:35 +00:00
timer = 0 ;
2009-05-14 18:31:43 +00:00
switch ( state ) {
2007-07-07 19:36:16 +00:00
case B_STATE_IDLE :
/* ignore due to deactivation confirm after unloading */
break ;
2007-06-27 06:23:50 +00:00
case B_STATE_DEACTIVATING :
2007-07-07 19:36:16 +00:00
_bchannel_destroy ( mISDNport , i ) ;
state = B_STATE_IDLE ;
2009-05-14 18:31:43 +00:00
if ( b_port ) {
2007-08-11 13:57:58 +00:00
/* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
2009-05-14 18:31:43 +00:00
if ( p_m_remote_ref ) {
2010-12-13 08:22:49 +00:00
message_bchannel_to_remote ( p_m_remote_id , p_m_remote_ref , BCHANNEL_ASSIGN , portid , p_m_tx_gain , p_m_rx_gain , p_m_pipeline , p_m_crypt_key , p_m_crypt_key_len , p_m_crypt_key_type , 0 ) ;
2007-08-11 13:57:58 +00:00
chan_trace_header ( mISDNport , b_port , " MESSAGE_BCHANNEL (to remote application) " , DIRECTION_NONE ) ;
add_trace ( " type " , NULL , " assign " ) ;
2007-08-29 16:56:03 +00:00
add_trace ( " channel " , NULL , " %d.%d " , portid > > 8 , portid & 0xff ) ;
2007-08-11 13:57:58 +00:00
end_trace ( ) ;
state = B_STATE_EXPORTING ;
2007-08-12 08:16:19 +00:00
mISDNport - > b_remote_id [ i ] = p_m_remote_id ;
2007-08-13 21:29:09 +00:00
mISDNport - > b_remote_ref [ i ] = p_m_remote_ref ;
2009-05-14 18:31:43 +00:00
} else {
if ( _bchannel_create ( mISDNport , i ) ) {
2010-01-16 10:20:23 +00:00
_bchannel_activate ( mISDNport , i , 1 , 0 ) ;
2007-08-11 13:57:58 +00:00
state = B_STATE_ACTIVATING ;
2010-01-16 10:20:23 +00:00
timer = B_TIMER_ACTIVATING ;
2007-08-11 13:57:58 +00:00
}
2007-06-27 06:23:50 +00:00
}
2007-05-06 13:54:52 +00:00
}
2007-06-27 06:23:50 +00:00
break ;
default :
PERROR ( " Illegal event %d at state %d, please correct. \n " , event , state ) ;
2007-05-06 13:54:52 +00:00
}
2007-06-27 06:23:50 +00:00
break ;
2007-08-11 13:57:58 +00:00
case B_EVENT_IMPORTED :
2009-05-14 18:31:43 +00:00
switch ( state ) {
2007-08-11 13:57:58 +00:00
case B_STATE_IMPORTING :
state = B_STATE_IDLE ;
2007-08-12 08:16:19 +00:00
mISDNport - > b_remote_id [ i ] = 0 ;
2007-08-13 21:29:09 +00:00
mISDNport - > b_remote_ref [ i ] = 0 ;
2009-05-14 18:31:43 +00:00
if ( b_port ) {
2007-08-11 13:57:58 +00:00
/* bchannel is now imported, but is requied by Port class, so we reactivate / export */
2009-05-14 18:31:43 +00:00
if ( p_m_remote_ref ) {
2010-12-13 08:22:49 +00:00
message_bchannel_to_remote ( p_m_remote_id , p_m_remote_ref , BCHANNEL_ASSIGN , portid , p_m_tx_gain , p_m_rx_gain , p_m_pipeline , p_m_crypt_key , p_m_crypt_key_len , p_m_crypt_key_type , 0 ) ;
2007-08-11 13:57:58 +00:00
chan_trace_header ( mISDNport , b_port , " MESSAGE_BCHANNEL (to remote application) " , DIRECTION_NONE ) ;
add_trace ( " type " , NULL , " assign " ) ;
2007-08-29 16:56:03 +00:00
add_trace ( " channel " , NULL , " %d.%d " , portid > > 8 , portid & 0xff ) ;
2007-08-11 13:57:58 +00:00
end_trace ( ) ;
state = B_STATE_EXPORTING ;
2007-08-12 08:16:19 +00:00
mISDNport - > b_remote_id [ i ] = p_m_remote_id ;
2007-08-13 21:29:09 +00:00
mISDNport - > b_remote_ref [ i ] = p_m_remote_ref ;
2009-05-14 18:31:43 +00:00
} else {
if ( _bchannel_create ( mISDNport , i ) ) {
2010-01-16 10:20:23 +00:00
_bchannel_activate ( mISDNport , i , 1 , 0 ) ;
2007-08-11 13:57:58 +00:00
state = B_STATE_ACTIVATING ;
2010-01-16 10:20:23 +00:00
timer = B_TIMER_ACTIVATING ;
2007-08-11 13:57:58 +00:00
}
}
}
break ;
default :
/* ignore, because not assigned */
;
}
break ;
2008-02-16 08:09:35 +00:00
case B_EVENT_TIMEOUT :
timer = 0 ;
2009-05-14 18:31:43 +00:00
switch ( state ) {
2008-02-16 08:09:35 +00:00
case B_STATE_IDLE :
/* ignore due to deactivation confirm after unloading */
break ;
case B_STATE_ACTIVATING :
2010-01-16 10:20:23 +00:00
_bchannel_activate ( mISDNport , i , 1 , 1 ) ;
timer = B_TIMER_ACTIVATING ;
2008-02-16 08:09:35 +00:00
break ;
case B_STATE_DEACTIVATING :
2010-01-16 10:20:23 +00:00
_bchannel_activate ( mISDNport , i , 0 , 1 ) ;
timer = B_TIMER_DEACTIVATING ;
2008-02-16 08:09:35 +00:00
break ;
default :
PERROR ( " Illegal event %d at state %d, please correct. \n " , event , state ) ;
}
break ;
2007-06-27 06:23:50 +00:00
default :
PERROR ( " Illegal event %d, please correct. \n " , event ) ;
2007-05-06 13:54:52 +00:00
}
2007-06-27 06:23:50 +00:00
mISDNport - > b_state [ i ] = state ;
2010-01-16 10:20:23 +00:00
if ( timer = = 0 )
unsched_timer ( & mISDNport - > b_timer [ i ] ) ;
else if ( timer > 0 )
schedule_timer ( & mISDNport - > b_timer [ i ] , timer , 0 ) ;
2007-05-06 13:54:52 +00:00
}
2007-06-27 06:23:50 +00:00
2007-05-06 13:54:52 +00:00
/*
* check for available channel and reserve + set it .
* give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
* give exclusiv flag
* returns - ( cause value ) or x = channel x or 0 = no channel
2007-06-27 06:23:50 +00:00
* NOTE : no activation is done here
2007-05-06 13:54:52 +00:00
*/
int PmISDN : : seize_bchannel ( int channel , int exclusive )
{
int i ;
/* the channel is what we have */
if ( p_m_b_channel = = channel )
return ( channel ) ;
/* if channel already in use, release it */
if ( p_m_b_channel )
drop_bchannel ( ) ;
/* if CHANNEL_NO */
if ( channel = = CHANNEL_NO | | channel = = 0 )
return ( 0 ) ;
/* is channel in range ? */
if ( channel = = 16
| | ( channel > p_m_mISDNport - > b_num & & channel < 16 )
| | ( ( channel - 1 ) > p_m_mISDNport - > b_num & & channel > 16 ) ) /* channel-1 because channel 16 is not counted */
return ( - 6 ) ; /* channel unacceptable */
/* request exclusive channel */
2009-05-14 18:31:43 +00:00
if ( exclusive & & channel > 0 ) {
2007-05-06 13:54:52 +00:00
i = channel - 1 - ( channel > 16 ) ;
if ( p_m_mISDNport - > b_port [ i ] )
return ( - 44 ) ; /* requested channel not available */
goto seize ;
}
/* ask for channel */
2009-05-14 18:31:43 +00:00
if ( channel > 0 ) {
2007-05-06 13:54:52 +00:00
i = channel - 1 - ( channel > 16 ) ;
if ( p_m_mISDNport - > b_port [ i ] = = NULL )
goto seize ;
}
/* search for channel */
i = 0 ;
2009-05-14 18:31:43 +00:00
while ( i < p_m_mISDNport - > b_num ) {
if ( ! p_m_mISDNport - > b_port [ i ] ) {
2007-05-06 13:54:52 +00:00
channel = i + 1 + ( i > = 15 ) ;
goto seize ;
}
i + + ;
}
return ( - 34 ) ; /* no free channel */
seize :
2007-06-27 06:23:50 +00:00
PDEBUG ( DEBUG_BCHANNEL , " PmISDN(%s) seizing bchannel %d (index %d) \n " , p_name , channel , i ) ;
2008-07-26 15:42:16 +00:00
/* link Port, set parameters */
2007-05-06 13:54:52 +00:00
p_m_mISDNport - > b_port [ i ] = this ;
p_m_b_index = i ;
p_m_b_channel = channel ;
p_m_b_exclusive = exclusive ;
2008-07-26 15:42:16 +00:00
p_m_mISDNport - > b_mode [ i ] = p_m_b_mode ;
2007-05-06 13:54:52 +00:00
/* reserve channel */
2009-05-14 18:31:43 +00:00
if ( ! p_m_b_reserve ) {
2007-05-06 13:54:52 +00:00
p_m_b_reserve = 1 ;
2007-06-27 06:23:50 +00:00
p_m_mISDNport - > b_reserved + + ;
2007-05-06 13:54:52 +00:00
}
return ( channel ) ;
}
/*
* drop reserved channel and unset it .
2007-06-27 06:23:50 +00:00
* deactivation is also done
2007-05-06 13:54:52 +00:00
*/
void PmISDN : : drop_bchannel ( void )
{
/* unreserve channel */
if ( p_m_b_reserve )
p_m_mISDNport - > b_reserved - - ;
p_m_b_reserve = 0 ;
/* if not in use */
2007-09-19 15:56:13 +00:00
if ( p_m_b_index < 0 )
return ;
2007-05-06 13:54:52 +00:00
if ( ! p_m_b_channel )
return ;
PDEBUG ( DEBUG_BCHANNEL , " PmISDN(%s) dropping bchannel \n " , p_name ) ;
2007-06-27 06:23:50 +00:00
if ( p_m_mISDNport - > b_state [ p_m_b_index ] ! = B_STATE_IDLE )
2007-08-12 08:16:19 +00:00
bchannel_event ( p_m_mISDNport , p_m_b_index , B_EVENT_DROP ) ;
2007-05-06 13:54:52 +00:00
p_m_mISDNport - > b_port [ p_m_b_index ] = NULL ;
2008-07-26 15:42:16 +00:00
p_m_mISDNport - > b_mode [ p_m_b_index ] = 0 ;
2007-05-06 13:54:52 +00:00
p_m_b_index = - 1 ;
p_m_b_channel = 0 ;
p_m_b_exclusive = 0 ;
2007-05-19 17:45:42 +00:00
}
2007-08-11 13:57:58 +00:00
/* process bchannel export/import message from join */
2008-06-14 06:34:50 +00:00
void message_bchannel_from_remote ( class JoinRemote * joinremote , int type , unsigned int handle )
2007-08-11 13:57:58 +00:00
{
class Endpoint * epoint ;
class Port * port ;
class PmISDN * isdnport ;
struct mISDNport * mISDNport ;
int i , ii ;
2009-05-14 18:31:43 +00:00
switch ( type ) {
2007-08-11 13:57:58 +00:00
case BCHANNEL_REQUEST :
/* find the port object for the join object ref */
2009-05-14 18:31:43 +00:00
if ( ! ( epoint = find_epoint_id ( joinremote - > j_epoint_id ) ) ) {
2007-08-11 13:57:58 +00:00
PDEBUG ( DEBUG_BCHANNEL , " join %d has no endpoint (anymore) \n " , joinremote - > j_serial ) ;
return ;
}
2009-05-14 18:31:43 +00:00
if ( ! epoint - > ep_portlist ) {
2007-08-11 13:57:58 +00:00
PDEBUG ( DEBUG_BCHANNEL , " join %d has no port (anymore in portlist) \n " , joinremote - > j_serial ) ;
return ;
}
2009-05-14 18:31:43 +00:00
if ( epoint - > ep_portlist - > next ) {
2007-08-11 13:57:58 +00:00
PERROR ( " join %d has enpoint %d with more than one port. this shall not happen to remote joins. \n " , joinremote - > j_serial , epoint - > ep_serial ) ;
}
2009-05-14 18:31:43 +00:00
if ( ! ( port = find_port_id ( epoint - > ep_portlist - > port_id ) ) ) {
2007-08-11 13:57:58 +00:00
PDEBUG ( DEBUG_BCHANNEL , " join %d has no port (anymore as object) \n " , joinremote - > j_serial ) ;
return ;
}
2009-05-14 18:31:43 +00:00
if ( ( port - > p_type & PORT_CLASS_MASK ) ! = PORT_CLASS_mISDN ) {
2007-08-11 13:57:58 +00:00
PERROR ( " join %d has port %d not of mISDN type. This shall not happen. \n " , joinremote - > j_serial , port - > p_serial ) ;
}
isdnport = ( class PmISDN * ) port ;
/* assign */
2009-05-14 18:31:43 +00:00
if ( isdnport - > p_m_remote_id ) {
2007-08-11 13:57:58 +00:00
PERROR ( " join %d recevied bchannel request from remote, but channel is already assinged. \n " , joinremote - > j_serial ) ;
break ;
}
2007-08-12 08:16:19 +00:00
mISDNport = isdnport - > p_m_mISDNport ;
i = isdnport - > p_m_b_index ;
chan_trace_header ( mISDNport , isdnport , " MESSAGE_BCHANNEL (from remote application) " , DIRECTION_NONE ) ;
2007-08-11 13:57:58 +00:00
add_trace ( " type " , NULL , " export request " ) ;
2008-06-01 16:52:10 +00:00
end_trace ( ) ;
2007-08-12 08:16:19 +00:00
isdnport - > p_m_remote_ref = joinremote - > j_serial ;
isdnport - > p_m_remote_id = joinremote - > j_remote_id ;
2009-05-14 18:31:43 +00:00
if ( mISDNport & & i > = 0 ) {
2007-08-12 08:16:19 +00:00
bchannel_event ( mISDNport , i , B_EVENT_EXPORTREQUEST ) ;
}
2008-06-01 16:52:10 +00:00
break ;
case BCHANNEL_RELEASE :
2007-08-11 13:57:58 +00:00
case BCHANNEL_ASSIGN_ACK :
case BCHANNEL_REMOVE_ACK :
/* find mISDNport for stack ID */
mISDNport = mISDNport_first ;
2009-05-14 18:31:43 +00:00
while ( mISDNport ) {
2007-08-11 13:57:58 +00:00
i = 0 ;
ii = mISDNport - > b_num ;
2009-05-14 18:31:43 +00:00
while ( i < ii ) {
2008-06-14 06:34:50 +00:00
if ( ( unsigned int ) ( mISDNport - > portnum < < 8 ) + i + 1 + ( i > = 15 ) = = handle )
2007-08-11 13:57:58 +00:00
break ;
i + + ;
}
if ( i ! = ii )
break ;
mISDNport = mISDNport - > next ;
}
2009-05-14 18:31:43 +00:00
if ( ! mISDNport ) {
2008-04-13 17:52:42 +00:00
PERROR ( " received assign/remove ack for bchannel's handle=%x, but handle does not exist in any mISDNport structure. \n " , handle ) ;
2007-08-12 08:16:19 +00:00
break ;
}
2007-08-11 13:57:58 +00:00
2009-05-14 18:31:43 +00:00
if ( type ! = BCHANNEL_RELEASE ) {
2008-06-06 13:18:59 +00:00
/* ack */
chan_trace_header ( mISDNport , mISDNport - > b_port [ i ] , " MESSAGE_BCHANNEL (from remote application) " , DIRECTION_NONE ) ;
add_trace ( " type " , NULL , ( type = = BCHANNEL_ASSIGN_ACK ) ? " assign_ack " : " remove_ack " ) ;
end_trace ( ) ;
2007-08-12 08:16:19 +00:00
bchannel_event ( mISDNport , i , ( type = = BCHANNEL_ASSIGN_ACK ) ? B_EVENT_EXPORTED : B_EVENT_IMPORTED ) ;
2009-05-14 18:31:43 +00:00
} else {
2008-06-06 13:18:59 +00:00
/* release */
isdnport = mISDNport - > b_port [ i ] ;
chan_trace_header ( mISDNport , isdnport , " MESSAGE_BCHANNEL (from remote application) " , DIRECTION_NONE ) ;
2008-06-06 17:15:14 +00:00
add_trace ( " type " , NULL , " import request " ) ;
2008-06-06 13:18:59 +00:00
end_trace ( ) ;
2009-05-14 18:31:43 +00:00
if ( isdnport ) {
2008-06-06 13:18:59 +00:00
isdnport - > p_m_remote_ref = 0 ;
isdnport - > p_m_remote_id = 0 ;
}
bchannel_event ( mISDNport , i , B_EVENT_IMPORTREQUEST ) ;
}
2007-08-11 13:57:58 +00:00
break ;
default :
PERROR ( " received wrong bchannel message type %d from remote \n " , type ) ;
}
}
2007-05-19 17:45:42 +00:00
2007-05-06 13:54:52 +00:00
/*
* handler
2007-07-15 10:01:27 +00:00
audio transmission procedure :
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* priority
three sources of audio transmission :
- crypto - data high priority
- tones high priority ( also high )
- remote - data low priority
* elapsed
a variable that temporarily shows the number of samples elapsed since last transmission process .
p_m_last_tv_ * is used to store that last timestamp . this is used to calculate the time elapsed .
* load
a variable that is increased whenever data is transmitted .
it is decreased while time elapses . it stores the number of samples that
are currently loaded to dsp module .
since clock in dsp module is the same clock for user space process , these
times have no skew .
* levels
there are two levels :
ISDN_LOAD will give the load that have to be kept in dsp .
ISDN_MAXLOAD will give the maximum load before dropping .
* procedure for low priority data
see txfromup ( ) for procedure
in short : remote data is ignored during high priority tones
* procedure for high priority data
whenever load is below ISDN_LOAD , load is filled up to ISDN_LOAD
if no more data is available , load becomes empty again .
' load ' variable :
0 ISDN_LOAD ISDN_MAXLOAD
+ - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - +
| | |
+ - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - +
on empty load or on load below ISDN_LOAD , the load is inceased to ISDN_LOAD :
0 ISDN_LOAD ISDN_MAXLOAD
+ - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - +
| TTTTTTTTTTTTTTTTTTTT | |
+ - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - +
on empty load , remote - audio causes the load with the remote audio to be increased to ISDN_LOAD .
0 ISDN_LOAD ISDN_MAXLOAD
+ - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - +
| TTTTTTTTTTTTTTTTTTTTRRRRR |
+ - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - +
2007-05-06 13:54:52 +00:00
*/
2010-01-16 10:20:23 +00:00
void PmISDN : : update_load ( void )
{
/* don't trigger load event if: */
if ( ! p_tone_name [ 0 ] & & ! p_m_crypt_msg_loops & & ! p_m_inband_send_on )
return ;
/* don't trigger load event if event already active */
if ( p_m_loadtimer . active )
return ;
schedule_timer ( & p_m_loadtimer , 0 , 0 ) ; /* no delay the first time */
}
int load_timer ( struct lcr_timer * timer , void * instance , int index )
{
class PmISDN * isdnport = ( class PmISDN * ) instance ;
isdnport - > load_tx ( ) ;
return 0 ;
}
void PmISDN : : load_tx ( void )
2007-05-06 13:54:52 +00:00
{
2007-07-15 10:01:27 +00:00
int elapsed = 0 ;
2007-06-27 06:23:50 +00:00
int ret ;
2010-01-16 10:20:23 +00:00
struct timeval current_time ;
2007-05-19 17:45:42 +00:00
2007-07-15 10:01:27 +00:00
/* get elapsed */
2010-01-16 10:20:23 +00:00
gettimeofday ( & current_time , NULL ) ;
2009-05-14 18:31:43 +00:00
if ( p_m_last_tv_sec ) {
2010-01-16 10:20:23 +00:00
elapsed = 8000 * ( current_time . tv_sec - p_m_last_tv_sec )
+ 8 * ( current_time . tv_usec / 1000 - p_m_last_tv_msec ) ;
2007-07-15 10:01:27 +00:00
}
2010-01-16 10:20:23 +00:00
/* set clock of last process! */
p_m_last_tv_sec = current_time . tv_sec ;
p_m_last_tv_msec = current_time . tv_usec / 1000 ;
2007-07-15 10:01:27 +00:00
2010-01-16 10:20:23 +00:00
/* process only if we have samples and we are active */
if ( elapsed & & p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE ) {
2007-07-15 10:01:27 +00:00
/* update load */
if ( elapsed < p_m_load )
p_m_load - = elapsed ;
else
p_m_load = 0 ;
2009-09-26 11:20:29 +00:00
/* to send data, tone must be on */
if ( ( p_tone_name [ 0 ] | | p_m_crypt_msg_loops | | p_m_inband_send_on ) /* what tones? */
2010-01-16 10:20:23 +00:00
& & ( p_m_load < ISDN_LOAD ) /* not too much load? */
2009-09-26 11:20:29 +00:00
& & ( p_state = = PORT_STATE_CONNECT | | p_m_mISDNport - > tones | | p_m_inband_send_on ) ) { /* connected or inband-tones? */
2007-07-15 10:01:27 +00:00
int tosend = ISDN_LOAD - p_m_load , length ;
2007-08-26 13:23:58 +00:00
unsigned char buf [ MISDN_HEADER_LEN + tosend ] ;
struct mISDNhead * frm = ( struct mISDNhead * ) buf ;
2008-04-13 17:52:42 +00:00
unsigned char * p = buf + MISDN_HEADER_LEN ;
2007-05-19 17:45:42 +00:00
2009-09-26 11:20:29 +00:00
/* copy inband signalling (e.g. used by ss5) */
if ( p_m_inband_send_on & & tosend ) {
tosend - = inband_send ( p , tosend ) ;
}
2007-07-15 10:01:27 +00:00
/* copy crypto loops */
2009-05-14 18:31:43 +00:00
while ( p_m_crypt_msg_loops & & tosend ) {
2007-06-27 06:23:50 +00:00
/* how much do we have to send */
2007-07-15 10:01:27 +00:00
length = p_m_crypt_msg_len - p_m_crypt_msg_current ;
2007-06-27 06:23:50 +00:00
2007-07-15 10:01:27 +00:00
/* clip tosend */
if ( length > tosend )
2007-06-27 06:23:50 +00:00
length = tosend ;
/* copy message (part) to buffer */
2007-07-15 10:01:27 +00:00
memcpy ( p , p_m_crypt_msg + p_m_crypt_msg_current , length ) ;
/* new position */
p_m_crypt_msg_current + = length ;
2009-05-14 18:31:43 +00:00
if ( p_m_crypt_msg_current = = p_m_crypt_msg_len ) {
2007-07-15 10:01:27 +00:00
/* next loop */
2007-05-19 17:45:42 +00:00
p_m_crypt_msg_current = 0 ;
p_m_crypt_msg_loops - - ;
2010-01-16 10:20:23 +00:00
if ( ! p_m_crypt_msg_loops )
update_rxoff ( ) ;
2007-09-22 07:28:26 +00:00
// puts("eine loop weniger");
2007-05-19 17:45:42 +00:00
}
2007-07-15 10:01:27 +00:00
/* new length */
tosend - = length ;
}
/* copy tones */
2009-05-14 18:31:43 +00:00
if ( p_tone_name [ 0 ] & & tosend ) {
2007-07-15 10:01:27 +00:00
tosend - = read_audio ( p , tosend ) ;
2007-05-19 17:45:42 +00:00
}
2007-07-15 10:01:27 +00:00
/* send data */
2009-05-14 18:31:43 +00:00
if ( ISDN_LOAD - p_m_load - tosend > 0 ) {
2008-05-09 19:31:58 +00:00
frm - > prim = PH_DATA_REQ ;
frm - > id = 0 ;
2010-01-16 10:20:23 +00:00
ret = sendto ( p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , buf , MISDN_HEADER_LEN + ISDN_LOAD - p_m_load - tosend , 0 , NULL , 0 ) ;
2008-05-10 19:40:23 +00:00
if ( ret < = 0 )
2010-01-16 10:20:23 +00:00
PERROR ( " Failed to send to socket %d (samples = %d) \n " , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , ISDN_LOAD - p_m_load - tosend ) ;
2008-07-30 17:35:28 +00:00
p_m_load + = ISDN_LOAD - p_m_load - tosend ;
2008-05-09 19:31:58 +00:00
}
2007-05-19 17:45:42 +00:00
}
}
2007-05-06 13:54:52 +00:00
2010-01-16 10:20:23 +00:00
if ( p_tone_name [ 0 ] | | p_m_crypt_msg_loops | | p_m_inband_send_on | | p_m_load ) {
schedule_timer ( & p_m_loadtimer , 0 , ISDN_TRANSMIT * 125 ) ;
2007-05-06 13:54:52 +00:00
}
}
2010-01-16 10:20:23 +00:00
/* handle timeouts */
static int mISDN_timeout ( struct lcr_timer * timer , void * instance , int i )
{
class PmISDN * isdnport = ( class PmISDN * ) instance ;
struct lcr_msg * message ;
PDEBUG ( DEBUG_ISDN , " (%s) timeout after %d seconds detected (state=%d). \n " , isdnport - > p_name , isdnport - > p_m_timeout . timeout . tv_sec , isdnport - > p_state ) ;
/* send timeout to endpoint */
message = message_create ( isdnport - > p_serial , ACTIVE_EPOINT ( isdnport - > p_epointlist ) , PORT_TO_EPOINT , MESSAGE_TIMEOUT ) ;
message - > param . state = isdnport - > p_state ;
message_put ( message ) ;
return 0 ;
}
2007-05-06 13:54:52 +00:00
/*
* whenever we get audio data from bchannel , we process it here
*/
2008-04-13 17:52:42 +00:00
void PmISDN : : bchannel_receive ( struct mISDNhead * hh , unsigned char * data , int len )
2007-08-26 13:23:58 +00:00
{
2008-06-14 06:34:50 +00:00
unsigned int cont = * ( ( unsigned int * ) data ) ;
2007-05-06 13:54:52 +00:00
unsigned char * data_temp ;
2008-06-14 06:34:50 +00:00
unsigned int length_temp ;
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-05-06 13:54:52 +00:00
unsigned char * p ;
int l ;
2009-05-14 18:31:43 +00:00
if ( hh - > prim = = PH_CONTROL_IND ) {
if ( len < 4 ) {
2007-05-23 09:19:25 +00:00
PERROR ( " SHORT READ OF PH_CONTROL INDICATION \n " ) ;
return ;
}
2009-05-14 18:31:43 +00:00
if ( ( cont & ( ~ DTMF_TONE_MASK ) ) = = DTMF_TONE_VAL ) {
2007-06-27 06:23:50 +00:00
chan_trace_header ( p_m_mISDNport , this , " BCHANNEL control " , DIRECTION_IN ) ;
add_trace ( " DTMF " , NULL , " %c " , cont & DTMF_TONE_MASK ) ;
end_trace ( ) ;
2007-05-06 13:54:52 +00:00
message = message_create ( p_serial , ACTIVE_EPOINT ( p_epointlist ) , PORT_TO_EPOINT , MESSAGE_DTMF ) ;
message - > param . dtmf = cont & DTMF_TONE_MASK ;
2007-05-23 09:19:25 +00:00
PDEBUG ( DEBUG_PORT , " PmISDN(%s) PH_CONTROL INDICATION DTMF digit '%c' \n " , p_name , message - > param . dtmf ) ;
2007-05-06 13:54:52 +00:00
message_put ( message ) ;
2007-05-23 09:19:25 +00:00
return ;
2007-05-06 13:54:52 +00:00
}
2009-05-14 18:31:43 +00:00
switch ( cont ) {
2008-04-24 07:24:04 +00:00
case DSP_BF_REJECT :
2007-06-27 06:23:50 +00:00
chan_trace_header ( p_m_mISDNport , this , " BCHANNEL control " , DIRECTION_IN ) ;
add_trace ( " DSP-CRYPT " , NULL , " error " ) ;
end_trace ( ) ;
2007-05-06 13:54:52 +00:00
message = message_create ( p_serial , ACTIVE_EPOINT ( p_epointlist ) , PORT_TO_EPOINT , MESSAGE_CRYPT ) ;
message - > param . crypt . type = CC_ERROR_IND ;
2007-05-23 09:19:25 +00:00
PDEBUG ( DEBUG_PORT , " PmISDN(%s) PH_CONTROL INDICATION reject of blowfish. \n " , p_name ) ;
2007-05-06 13:54:52 +00:00
message_put ( message ) ;
break ;
2008-04-24 07:24:04 +00:00
case DSP_BF_ACCEPT :
2007-06-27 06:23:50 +00:00
chan_trace_header ( p_m_mISDNport , this , " BCHANNEL control " , DIRECTION_IN ) ;
add_trace ( " DSP-CRYPT " , NULL , " ok " ) ;
end_trace ( ) ;
2007-05-06 13:54:52 +00:00
message = message_create ( p_serial , ACTIVE_EPOINT ( p_epointlist ) , PORT_TO_EPOINT , MESSAGE_CRYPT ) ;
message - > param . crypt . type = CC_ACTBF_CONF ;
2007-05-23 09:19:25 +00:00
PDEBUG ( DEBUG_PORT , " PmISDN(%s) PH_CONTROL INDICATION accept of blowfish. \n " , p_name ) ;
2007-05-06 13:54:52 +00:00
message_put ( message ) ;
break ;
2007-05-23 09:19:25 +00:00
2007-09-19 15:28:56 +00:00
default :
chan_trace_header ( p_m_mISDNport , this , " BCHANNEL control " , DIRECTION_IN ) ;
add_trace ( " unknown " , NULL , " 0x%x " , cont ) ;
end_trace ( ) ;
}
return ;
}
2009-05-14 18:31:43 +00:00
if ( hh - > prim = = PH_CONTROL_IND ) {
switch ( hh - > id ) {
2007-05-23 09:19:25 +00:00
default :
2008-04-13 17:52:42 +00:00
chan_trace_header ( p_m_mISDNport , this , " BCHANNEL control " , DIRECTION_IN ) ;
add_trace ( " unknown " , NULL , " 0x%x " , hh - > id ) ;
2007-06-27 06:23:50 +00:00
end_trace ( ) ;
2007-05-06 13:54:52 +00:00
}
return ;
2007-07-08 09:24:26 +00:00
}
2009-05-14 18:31:43 +00:00
if ( hh - > prim = = PH_DATA_REQ | | hh - > prim = = DL_DATA_REQ ) {
if ( ! p_m_txdata ) {
2008-05-18 07:23:10 +00:00
/* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
PDEBUG ( DEBUG_BCHANNEL , " PmISDN(%s) ignoring tx data, because 'txdata' is turned off \n " , p_name ) ;
return ;
}
/* see below (same condition) */
if ( p_state ! = PORT_STATE_CONNECT
& & ! p_m_mISDNport - > tones )
return ;
// printf(".");fflush(stdout);return;
if ( p_record )
record ( data , len , 1 ) ; // from up
return ;
}
2009-05-14 18:31:43 +00:00
if ( hh - > prim ! = PH_DATA_IND & & hh - > prim ! = DL_DATA_IND ) {
2007-08-26 13:23:58 +00:00
PERROR ( " Bchannel received unknown primitve: 0x%x \n " , hh - > prim ) ;
2007-05-23 09:19:25 +00:00
return ;
2007-05-06 13:54:52 +00:00
}
2008-06-01 16:52:10 +00:00
2009-09-26 11:20:29 +00:00
/* inband is processed */
if ( p_m_inband_receive_on )
inband_receive ( data , len ) ;
2007-05-09 05:39:20 +00:00
/* calls will not process any audio data unless
2008-06-01 16:52:10 +00:00
* the call is connected OR tones feature is enabled .
2007-05-06 13:54:52 +00:00
*/
2007-07-15 10:01:27 +00:00
# ifndef DEBUG_COREBRIDGE
2007-07-08 09:24:26 +00:00
if ( p_state ! = PORT_STATE_CONNECT
2007-09-19 15:28:56 +00:00
& & ! p_m_mISDNport - > tones )
2007-05-06 13:54:52 +00:00
return ;
# endif
2008-06-01 16:52:10 +00:00
#if 0
/* the bearer capability must be audio in order to send and receive
* audio prior or after connect .
*/
if ( ! ( p_bearerinfo . capability & CLASS_CAPABILITY_AUDIO ) & & p_state ! = PORT_STATE_CONNECT )
return ;
# endif
2007-05-06 13:54:52 +00:00
/* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
2009-05-14 18:31:43 +00:00
if ( p_m_rxoff ) {
2007-05-06 13:54:52 +00:00
PDEBUG ( DEBUG_BCHANNEL , " PmISDN(%s) ignoring data, because rx is turned off \n " , p_name ) ;
return ;
}
2007-05-23 09:19:25 +00:00
/* record data */
if ( p_record )
2007-08-26 13:23:58 +00:00
record ( data , len , 0 ) ; // from down
2007-05-23 09:19:25 +00:00
2007-05-06 13:54:52 +00:00
/* randomize and listen to crypt message if enabled */
2009-05-14 18:31:43 +00:00
if ( p_m_crypt_listen ) {
2007-05-06 13:54:52 +00:00
/* the noisy randomizer */
2007-08-26 13:23:58 +00:00
p = data ;
l = len ;
2007-05-06 13:54:52 +00:00
while ( l - - )
mISDN_rand [ mISDN_rand_count & 0xff ] + = * p + + ;
2007-08-26 13:23:58 +00:00
cryptman_listen_bch ( data , len ) ;
2007-05-06 13:54:52 +00:00
}
2007-08-26 13:23:58 +00:00
p = data ;
2007-05-06 13:54:52 +00:00
/* send data to epoint */
2009-05-14 18:31:43 +00:00
if ( p_m_joindata & & ACTIVE_EPOINT ( p_epointlist ) ) { /* only if we have an epoint object */
2007-08-26 13:23:58 +00:00
length_temp = len ;
2007-05-06 13:54:52 +00:00
data_temp = p ;
2009-05-14 18:31:43 +00:00
while ( length_temp ) {
2007-05-06 13:54:52 +00:00
message = message_create ( p_serial , ACTIVE_EPOINT ( p_epointlist ) , PORT_TO_EPOINT , MESSAGE_DATA ) ;
message - > param . data . len = ( length_temp > sizeof ( message - > param . data . data ) ) ? sizeof ( message - > param . data . data ) : length_temp ;
memcpy ( message - > param . data . data , data_temp , message - > param . data . len ) ;
message_put ( message ) ;
if ( length_temp < = sizeof ( message - > param . data . data ) )
break ;
data_temp + = sizeof ( message - > param . data . data ) ;
length_temp - = sizeof ( message - > param . data . data ) ;
}
}
}
/*
* set echotest
*/
void PmISDN : : set_echotest ( int echo )
{
2009-05-14 18:31:43 +00:00
if ( p_m_echo ! = echo ) {
2007-05-06 13:54:52 +00:00
p_m_echo = echo ;
PDEBUG ( DEBUG_ISDN , " we set echo to echo=%d. \n " , p_m_echo ) ;
if ( p_m_b_channel )
if ( p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE )
2010-01-16 10:20:23 +00:00
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , p_m_echo ? DSP_ECHO_ON : DSP_ECHO_OFF , 0 , " DSP-ECHO " , p_m_echo ) ;
2007-05-06 13:54:52 +00:00
}
}
/*
* set tone
*/
2008-09-02 00:02:11 +00:00
void PmISDN : : set_tone ( const char * dir , const char * tone )
2007-05-06 13:54:52 +00:00
{
2008-11-04 08:31:09 +00:00
int id = TONE_OFF ;
2009-05-14 18:31:43 +00:00
int dsp = DSP_NONE ;
/* if no directory is given (by extension), we use interface.conf or options.conf */
if ( ! dir | | ! dir [ 0 ] ) {
if ( p_m_mISDNport - > ifport - > tones_dir [ 0 ] )
dir = p_m_mISDNport - > ifport - > tones_dir ;
else if ( options . tones_dir [ 0 ] )
dir = options . tones_dir ;
}
2007-05-06 13:54:52 +00:00
if ( ! tone )
tone = " " ;
PDEBUG ( DEBUG_ISDN , " isdn port now plays tone:'%s'. \n " , tone ) ;
2009-05-14 18:31:43 +00:00
if ( ! tone [ 0 ] ) {
2007-05-06 13:54:52 +00:00
id = TONE_OFF ;
goto setdsp ;
}
2009-05-14 18:31:43 +00:00
/* check for dsp tones */
if ( ! strcmp ( dir , " american " ) )
dsp = DSP_AMERICAN ;
if ( ! strcmp ( dir , " german " ) )
dsp = DSP_GERMAN ;
if ( ! strcmp ( dir , " oldgerman " ) )
dsp = DSP_OLDGERMAN ;
2007-05-06 13:54:52 +00:00
/* check if we NOT really have to use a dsp-tone */
2009-05-14 18:31:43 +00:00
if ( dsp = = DSP_NONE ) {
2007-05-06 13:54:52 +00:00
nodsp :
if ( p_m_tone )
2008-04-13 17:52:42 +00:00
if ( p_m_b_index > - 1 )
2009-05-14 18:31:43 +00:00
if ( p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE & & p_m_mISDNport - > b_mode [ p_m_b_index ] = = B_MODE_TRANSPARENT ) {
2007-05-06 13:54:52 +00:00
PDEBUG ( DEBUG_ISDN , " we reset tone from id=%d to OFF. \n " , p_m_tone ) ;
2010-01-16 10:20:23 +00:00
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , DSP_TONE_PATT_OFF , 0 , " DSP-TONE " , 0 ) ;
2007-05-06 13:54:52 +00:00
}
p_m_tone = 0 ;
Port : : set_tone ( dir , tone ) ;
return ;
}
/* now we USE dsp-tone, convert name */
2009-05-14 18:31:43 +00:00
if ( ! strcmp ( tone , " dialtone " ) ) {
switch ( dsp ) {
2007-05-06 13:54:52 +00:00
case DSP_AMERICAN : id = TONE_AMERICAN_DIALTONE ; break ;
case DSP_GERMAN : id = TONE_GERMAN_DIALTONE ; break ;
case DSP_OLDGERMAN : id = TONE_GERMAN_OLDDIALTONE ; break ;
}
2009-05-14 18:31:43 +00:00
} else if ( ! strcmp ( tone , " dialpbx " ) ) {
switch ( dsp ) {
2007-05-06 13:54:52 +00:00
case DSP_AMERICAN : id = TONE_AMERICAN_DIALPBX ; break ;
case DSP_GERMAN : id = TONE_GERMAN_DIALPBX ; break ;
case DSP_OLDGERMAN : id = TONE_GERMAN_OLDDIALPBX ; break ;
}
2009-05-14 18:31:43 +00:00
} else if ( ! strcmp ( tone , " ringing " ) ) {
switch ( dsp ) {
2007-05-06 13:54:52 +00:00
case DSP_AMERICAN : id = TONE_AMERICAN_RINGING ; break ;
case DSP_GERMAN : id = TONE_GERMAN_RINGING ; break ;
case DSP_OLDGERMAN : id = TONE_GERMAN_OLDRINGING ; break ;
}
2009-05-14 18:31:43 +00:00
} else if ( ! strcmp ( tone , " ringpbx " ) ) {
switch ( dsp ) {
2007-05-06 13:54:52 +00:00
case DSP_AMERICAN : id = TONE_AMERICAN_RINGPBX ; break ;
case DSP_GERMAN : id = TONE_GERMAN_RINGPBX ; break ;
case DSP_OLDGERMAN : id = TONE_GERMAN_OLDRINGPBX ; break ;
}
2009-05-14 18:31:43 +00:00
} else if ( ! strcmp ( tone , " busy " ) ) {
2007-05-06 13:54:52 +00:00
busy :
2009-05-14 18:31:43 +00:00
switch ( dsp ) {
2007-05-06 13:54:52 +00:00
case DSP_AMERICAN : id = TONE_AMERICAN_BUSY ; break ;
case DSP_GERMAN : id = TONE_GERMAN_BUSY ; break ;
case DSP_OLDGERMAN : id = TONE_GERMAN_OLDBUSY ; break ;
}
2009-05-14 18:31:43 +00:00
} else if ( ! strcmp ( tone , " release " ) ) {
2007-05-06 13:54:52 +00:00
hangup :
2009-05-14 18:31:43 +00:00
switch ( dsp ) {
2007-05-06 13:54:52 +00:00
case DSP_AMERICAN : id = TONE_AMERICAN_HANGUP ; break ;
case DSP_GERMAN : id = TONE_GERMAN_HANGUP ; break ;
case DSP_OLDGERMAN : id = TONE_GERMAN_OLDHANGUP ; break ;
}
} else if ( ! strcmp ( tone , " cause_10 " ) )
goto hangup ;
else if ( ! strcmp ( tone , " cause_11 " ) )
goto busy ;
2009-05-14 18:31:43 +00:00
else if ( ! strcmp ( tone , " cause_22 " ) ) {
switch ( dsp ) {
2007-05-06 13:54:52 +00:00
case DSP_AMERICAN : id = TONE_SPECIAL_INFO ; break ;
case DSP_GERMAN : id = TONE_GERMAN_GASSENBESETZT ; break ;
case DSP_OLDGERMAN : id = TONE_GERMAN_OLDBUSY ; break ;
}
} else if ( ! strncmp ( tone , " cause_ " , 6 ) )
id = TONE_SPECIAL_INFO ;
else
id = TONE_OFF ;
/* if we have a tone that is not supported by dsp */
if ( id = = TONE_OFF & & tone [ 0 ] )
goto nodsp ;
setdsp :
2009-05-14 18:31:43 +00:00
if ( p_m_tone ! = id ) {
2007-05-06 13:54:52 +00:00
/* set new tone */
p_m_tone = id ;
PDEBUG ( DEBUG_ISDN , " we set tone to id=%d. \n " , p_m_tone ) ;
2008-04-13 17:52:42 +00:00
if ( p_m_b_index > - 1 )
2008-07-26 15:42:16 +00:00
if ( p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE & & p_m_mISDNport - > b_mode [ p_m_b_index ] = = B_MODE_TRANSPARENT )
2010-01-16 10:20:23 +00:00
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , p_m_tone ? DSP_TONE_PATT_ON : DSP_TONE_PATT_OFF , p_m_tone , " DSP-TONE " , p_m_tone ) ;
2007-05-06 13:54:52 +00:00
}
/* turn user-space tones off in cases of no tone OR dsp tone */
Port : : set_tone ( " " , NULL ) ;
}
/* MESSAGE_mISDNSIGNAL */
2008-04-25 07:06:20 +00:00
//extern struct lcr_msg *dddebug;
2008-06-14 06:34:50 +00:00
void PmISDN : : message_mISDNsignal ( unsigned int epoint_id , int message_id , union parameter * param )
2007-05-06 13:54:52 +00:00
{
2009-09-26 11:20:29 +00:00
int oldconf , newconf ;
2009-05-14 18:31:43 +00:00
switch ( param - > mISDNsignal . message ) {
2007-05-06 13:54:52 +00:00
case mISDNSIGNAL_VOLUME :
2009-05-14 18:31:43 +00:00
if ( p_m_tx_gain ! = param - > mISDNsignal . tx_gain ) {
2008-01-19 17:10:46 +00:00
p_m_tx_gain = param - > mISDNsignal . tx_gain ;
PDEBUG ( DEBUG_BCHANNEL , " we change tx-volume to shift=%d. \n " , p_m_tx_gain ) ;
2008-04-13 17:52:42 +00:00
if ( p_m_b_index > - 1 )
2008-07-26 15:42:16 +00:00
if ( p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE & & p_m_mISDNport - > b_mode [ p_m_b_index ] = = B_MODE_TRANSPARENT )
2010-01-16 10:20:23 +00:00
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , DSP_VOL_CHANGE_TX , p_m_tx_gain , " DSP-TX_GAIN " , p_m_tx_gain ) ;
2007-07-08 09:24:26 +00:00
} else
2008-01-19 17:10:46 +00:00
PDEBUG ( DEBUG_BCHANNEL , " we already have tx-volume shift=%d. \n " , p_m_rx_gain ) ;
2009-05-14 18:31:43 +00:00
if ( p_m_rx_gain ! = param - > mISDNsignal . rx_gain ) {
2008-01-19 17:10:46 +00:00
p_m_rx_gain = param - > mISDNsignal . rx_gain ;
PDEBUG ( DEBUG_BCHANNEL , " we change rx-volume to shift=%d. \n " , p_m_rx_gain ) ;
2008-04-13 17:52:42 +00:00
if ( p_m_b_index > - 1 )
2008-07-26 15:42:16 +00:00
if ( p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE & & p_m_mISDNport - > b_mode [ p_m_b_index ] = = B_MODE_TRANSPARENT )
2010-01-16 10:20:23 +00:00
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , DSP_VOL_CHANGE_RX , p_m_rx_gain , " DSP-RX_GAIN " , p_m_rx_gain ) ;
2007-07-08 09:24:26 +00:00
} else
2008-01-19 17:10:46 +00:00
PDEBUG ( DEBUG_BCHANNEL , " we already have rx-volume shift=%d. \n " , p_m_rx_gain ) ;
2007-05-06 13:54:52 +00:00
break ;
case mISDNSIGNAL_CONF :
2009-09-26 11:20:29 +00:00
oldconf = p_m_mute ? 0 : p_m_conf ;
2007-05-06 13:54:52 +00:00
p_m_conf = param - > mISDNsignal . conf ;
2009-09-26 11:20:29 +00:00
newconf = p_m_mute ? 0 : p_m_conf ;
set_conf ( oldconf , newconf ) ;
2007-05-06 13:54:52 +00:00
break ;
2007-07-17 17:28:09 +00:00
case mISDNSIGNAL_JOINDATA :
2009-05-14 18:31:43 +00:00
if ( p_m_joindata ! = param - > mISDNsignal . joindata ) {
2007-07-17 17:28:09 +00:00
p_m_joindata = param - > mISDNsignal . joindata ;
PDEBUG ( DEBUG_BCHANNEL , " we change to joindata=%d. \n " , p_m_joindata ) ;
2010-01-16 10:20:23 +00:00
update_rxoff ( ) ;
2007-07-08 09:24:26 +00:00
} else
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_BCHANNEL , " we already have joindata=%d. \n " , p_m_joindata ) ;
2007-05-15 20:59:29 +00:00
break ;
2007-06-27 06:23:50 +00:00
case mISDNSIGNAL_DELAY :
2009-05-14 18:31:43 +00:00
if ( p_m_delay ! = param - > mISDNsignal . delay ) {
2007-06-27 06:23:50 +00:00
p_m_delay = param - > mISDNsignal . delay ;
PDEBUG ( DEBUG_BCHANNEL , " we change delay mode to delay=%d. \n " , p_m_delay ) ;
2008-04-13 17:52:42 +00:00
if ( p_m_b_index > - 1 )
2008-07-26 15:42:16 +00:00
if ( p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE & & p_m_mISDNport - > b_mode [ p_m_b_index ] = = B_MODE_TRANSPARENT )
2010-01-16 10:20:23 +00:00
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , p_m_delay ? DSP_DELAY : DSP_JITTER , p_m_delay , " DSP-DELAY " , p_m_delay ) ;
2007-07-08 09:24:26 +00:00
} else
PDEBUG ( DEBUG_BCHANNEL , " we already have delay=%d. \n " , p_m_delay ) ;
2007-05-06 13:54:52 +00:00
break ;
default :
PERROR ( " PmISDN(%s) unsupported signal message %d. \n " , p_name , param - > mISDNsignal . message ) ;
}
}
/* MESSAGE_CRYPT */
2008-06-14 06:34:50 +00:00
void PmISDN : : message_crypt ( unsigned int epoint_id , int message_id , union parameter * param )
2007-05-06 13:54:52 +00:00
{
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-05-06 13:54:52 +00:00
2009-05-14 18:31:43 +00:00
switch ( param - > crypt . type ) {
2007-05-06 13:54:52 +00:00
case CC_ACTBF_REQ : /* activate blowfish */
p_m_crypt = 1 ;
p_m_crypt_key_len = param - > crypt . len ;
2009-05-14 18:31:43 +00:00
if ( p_m_crypt_key_len > ( int ) sizeof ( p_m_crypt_key ) ) {
2007-05-06 13:54:52 +00:00
PERROR ( " PmISDN(%s) key too long %d > %d \n " , p_name , p_m_crypt_key_len , sizeof ( p_m_crypt_key ) ) ;
message = message_create ( p_serial , ACTIVE_EPOINT ( p_epointlist ) , PORT_TO_EPOINT , MESSAGE_CRYPT ) ;
message - > param . crypt . type = CC_ERROR_IND ;
message_put ( message ) ;
break ;
}
memcpy ( p_m_crypt_key , param - > crypt . data , p_m_crypt_key_len ) ;
crypt_off :
PDEBUG ( DEBUG_BCHANNEL , " we set encryption to crypt=%d. (0 means OFF) \n " , p_m_crypt ) ;
2008-04-13 17:52:42 +00:00
if ( p_m_b_index > - 1 )
2008-07-26 15:42:16 +00:00
if ( p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE & & p_m_mISDNport - > b_mode [ p_m_b_index ] = = B_MODE_TRANSPARENT )
2010-01-16 10:20:23 +00:00
ph_control_block ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , p_m_crypt ? DSP_BF_ENABLE_KEY : DSP_BF_DISABLE , p_m_crypt_key , p_m_crypt_key_len , " DSP-CRYPT " , p_m_crypt_key_len ) ;
2007-05-06 13:54:52 +00:00
break ;
case CC_DACT_REQ : /* deactivate session encryption */
p_m_crypt = 0 ;
goto crypt_off ;
break ;
case CR_LISTEN_REQ : /* start listening to messages */
p_m_crypt_listen = 1 ;
2010-01-16 10:20:23 +00:00
update_rxoff ( ) ;
2007-05-06 13:54:52 +00:00
p_m_crypt_listen_state = 0 ;
break ;
case CR_UNLISTEN_REQ : /* stop listening to messages */
p_m_crypt_listen = 0 ;
2010-01-16 10:20:23 +00:00
update_rxoff ( ) ;
2007-05-06 13:54:52 +00:00
break ;
case CR_MESSAGE_REQ : /* send message */
p_m_crypt_msg_len = cryptman_encode_bch ( param - > crypt . data , param - > crypt . len , p_m_crypt_msg , sizeof ( p_m_crypt_msg ) ) ;
2009-05-14 18:31:43 +00:00
if ( ! p_m_crypt_msg_len ) {
2007-05-06 13:54:52 +00:00
PERROR ( " PmISDN(%s) message too long %d > %d \n " , p_name , param - > crypt . len - 1 , sizeof ( p_m_crypt_msg ) ) ;
break ;
}
p_m_crypt_msg_current = 0 ; /* reset */
2007-09-22 07:28:26 +00:00
p_m_crypt_msg_loops = 6 ; /* enable */
2010-01-16 10:20:23 +00:00
update_rxoff ( ) ;
update_load ( ) ;
2007-05-15 20:59:29 +00:00
#if 0
2007-05-06 13:54:52 +00:00
/* disable txmix, or we get corrupt data due to audio process */
2009-05-14 18:31:43 +00:00
if ( p_m_txmix & & p_m_b_index > = 0 & & p_m_mISDNport - > b_mode [ p_m_b_index ] = = B_MODE_TRANSPARENT ) {
2007-05-06 13:54:52 +00:00
PDEBUG ( DEBUG_BCHANNEL , " for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d. \n " , p_m_txmix ) ;
2010-01-16 10:20:23 +00:00
ph_control ( p_m_mISDNport , this , p_mISDNport - > b_sock [ p_m_b_index ] . fd , DSP_MIX_OFF , 0 , " DSP-TXMIX " , 0 ) ;
2007-05-06 13:54:52 +00:00
}
2007-05-15 20:59:29 +00:00
# endif
2007-05-06 13:54:52 +00:00
break ;
default :
PERROR ( " PmISDN(%s) unknown crypt message %d \n " , p_name , param - > crypt . type ) ;
}
}
/*
* endpoint sends messages to the port
*/
2008-06-14 06:34:50 +00:00
int PmISDN : : message_epoint ( unsigned int epoint_id , int message_id , union parameter * param )
2007-05-06 13:54:52 +00:00
{
if ( Port : : message_epoint ( epoint_id , message_id , param ) )
return ( 1 ) ;
2009-05-14 18:31:43 +00:00
switch ( message_id ) {
2007-06-27 06:23:50 +00:00
case MESSAGE_DATA : /* tx-data from upper layer */
txfromup ( param - > data . data , param - > data . len ) ;
return ( 1 ) ;
2007-05-06 13:54:52 +00:00
case MESSAGE_mISDNSIGNAL : /* user command */
PDEBUG ( DEBUG_ISDN , " PmISDN(%s) received special ISDN SIGNAL %d. \n " , p_name , param - > mISDNsignal . message ) ;
message_mISDNsignal ( epoint_id , message_id , param ) ;
return ( 1 ) ;
case MESSAGE_CRYPT : /* crypt control command */
PDEBUG ( DEBUG_ISDN , " PmISDN(%s) received encryption command '%d'. \n " , p_name , param - > crypt . type ) ;
message_crypt ( epoint_id , message_id , param ) ;
return ( 1 ) ;
}
return ( 0 ) ;
}
2010-01-16 10:20:23 +00:00
void PmISDN : : update_rxoff ( void )
{
/* call bridges in user space OR crypto OR recording */
if ( p_m_joindata | | p_m_crypt_msg_loops | | p_m_crypt_listen | | p_record | | p_m_inband_receive_on ) {
/* rx IS required */
if ( p_m_rxoff ) {
/* turn on RX */
p_m_rxoff = 0 ;
PDEBUG ( DEBUG_BCHANNEL , " %s: receive data is required, so we turn them on \n " , __FUNCTION__ ) ;
if ( p_m_b_index > - 1 )
if ( p_m_mISDNport - > b_port [ p_m_b_index ] & & p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE )
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , DSP_RECEIVE_ON , 0 , " DSP-RXOFF " , 0 ) ;
}
} else {
/* rx NOT required */
if ( ! p_m_rxoff ) {
/* turn off RX */
p_m_rxoff = 1 ;
PDEBUG ( DEBUG_BCHANNEL , " %s: receive data is not required, so we turn them off \n " , __FUNCTION__ ) ;
if ( p_m_b_index > - 1 )
if ( p_m_mISDNport - > b_port [ p_m_b_index ] & & p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE )
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , DSP_RECEIVE_OFF , 0 , " DSP-RXOFF " , 1 ) ;
}
}
/* recording */
if ( p_record ) {
/* txdata IS required */
if ( ! p_m_txdata ) {
/* turn on RX */
p_m_txdata = 1 ;
PDEBUG ( DEBUG_BCHANNEL , " %s: transmit data is required, so we turn them on \n " , __FUNCTION__ ) ;
if ( p_m_b_index > - 1 )
if ( p_m_mISDNport - > b_port [ p_m_b_index ] & & p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE )
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , DSP_TXDATA_ON , 0 , " DSP-TXDATA " , 1 ) ;
}
} else {
/* txdata NOT required */
if ( p_m_txdata ) {
/* turn off RX */
p_m_txdata = 0 ;
PDEBUG ( DEBUG_BCHANNEL , " %s: transmit data is not required, so we turn them off \n " , __FUNCTION__ ) ;
if ( p_m_b_index > - 1 )
if ( p_m_mISDNport - > b_port [ p_m_b_index ] & & p_m_mISDNport - > b_state [ p_m_b_index ] = = B_STATE_ACTIVE )
ph_control ( p_m_mISDNport , this , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , DSP_TXDATA_OFF , 0 , " DSP-TXDATA " , 0 ) ;
}
}
}
2007-05-06 13:54:52 +00:00
2010-01-16 10:20:23 +00:00
static int mISDN_upqueue ( struct lcr_fd * fd , unsigned int what , void * instance , int i )
2007-05-06 13:54:52 +00:00
{
struct mISDNport * mISDNport ;
2008-04-24 07:24:04 +00:00
struct mbuffer * mb ;
struct l3_msg * l3m ;
2010-01-16 10:20:23 +00:00
char byte ;
2010-03-11 13:07:20 +00:00
int ret ;
2010-01-16 10:20:23 +00:00
/* unset global semaphore */
upqueue_avail = 0 ;
2010-01-16 10:42:46 +00:00
// with a very small incident, upqueue_avail may be set by mISDN thread and
// another byte may be sent to the pipe, which causes a call to this function
// again with nothing in the upqueue. this is no problem.
2010-03-11 13:07:20 +00:00
ret = read ( fd - > fd , & byte , 1 ) ;
2007-08-29 16:56:03 +00:00
/* process all ports */
mISDNport = mISDNport_first ;
2009-05-14 18:31:43 +00:00
while ( mISDNport ) {
2008-04-24 07:24:04 +00:00
/* handle queued up-messages (d-channel) */
2010-12-13 08:22:49 +00:00
if ( ! mISDNport - > isloopback ) {
2009-05-14 18:31:43 +00:00
while ( ( mb = mdequeue ( & mISDNport - > upqueue ) ) ) {
2009-05-11 09:07:58 +00:00
l3m = & mb - > l3 ;
2009-05-14 18:31:43 +00:00
switch ( l3m - > type ) {
2009-05-11 09:07:58 +00:00
case MPH_ACTIVATE_IND :
2009-05-14 18:31:43 +00:00
if ( mISDNport - > l1link ! = 1 ) {
2009-05-11 09:07:58 +00:00
l1l2l3_trace_header ( mISDNport , NULL , L1_ACTIVATE_IND , DIRECTION_IN ) ;
end_trace ( ) ;
mISDNport - > l1link = 1 ;
}
2008-05-02 19:19:06 +00:00
break ;
2009-05-11 09:07:58 +00:00
case MPH_DEACTIVATE_IND :
2009-05-14 18:31:43 +00:00
if ( mISDNport - > l1link ! = 0 ) {
2009-05-11 09:07:58 +00:00
l1l2l3_trace_header ( mISDNport , NULL , L1_DEACTIVATE_IND , DIRECTION_IN ) ;
end_trace ( ) ;
mISDNport - > l1link = 0 ;
}
2008-05-02 19:19:06 +00:00
break ;
2008-04-24 07:24:04 +00:00
2009-05-11 09:07:58 +00:00
case MPH_INFORMATION_IND :
PDEBUG ( DEBUG_ISDN , " Received MPH_INFORMATION_IND for port %d (%s). \n " , mISDNport - > portnum , mISDNport - > ifport - > interface - > name ) ;
2009-05-14 18:31:43 +00:00
switch ( l3m - > pid ) {
2009-05-11 09:07:58 +00:00
case L1_SIGNAL_LOS_ON :
mISDNport - > los = 1 ;
break ;
case L1_SIGNAL_LOS_OFF :
mISDNport - > los = 0 ;
break ;
case L1_SIGNAL_AIS_ON :
mISDNport - > ais = 1 ;
break ;
case L1_SIGNAL_AIS_OFF :
mISDNport - > ais = 0 ;
break ;
case L1_SIGNAL_RDI_ON :
mISDNport - > rdi = 1 ;
break ;
case L1_SIGNAL_RDI_OFF :
mISDNport - > rdi = 0 ;
break ;
case L1_SIGNAL_SLIP_TX :
mISDNport - > slip_tx + + ;
break ;
case L1_SIGNAL_SLIP_RX :
mISDNport - > slip_rx + + ;
break ;
2008-04-24 07:24:04 +00:00
}
2009-05-11 09:07:58 +00:00
break ;
2008-04-24 07:24:04 +00:00
2009-05-11 09:07:58 +00:00
case MT_L2ESTABLISH :
l1l2l3_trace_header ( mISDNport , NULL , L2_ESTABLISH_IND , DIRECTION_IN ) ;
2008-06-15 12:38:35 +00:00
add_trace ( " tei " , NULL , " %d " , l3m - > pid ) ;
end_trace ( ) ;
2009-05-11 09:07:58 +00:00
mISDNport - > l2link = 1 ;
if ( l3m - > pid < 128 )
mISDNport - > l2mask [ l3m - > pid > > 3 ] | = ( 1 < < ( l3m - > pid & 7 ) ) ;
2009-05-14 18:31:43 +00:00
if ( ( ! mISDNport - > ntmode | | mISDNport - > ptp ) & & l3m - > pid < 127 ) {
2010-01-16 10:20:23 +00:00
if ( mISDNport - > l2establish . active ) {
unsched_timer ( & mISDNport - > l2establish ) ;
2009-05-11 09:07:58 +00:00
PDEBUG ( DEBUG_ISDN , " the link became active before l2establish timer expiry. \n " ) ;
}
2008-04-24 07:24:04 +00:00
}
2009-05-11 09:07:58 +00:00
break ;
2008-04-24 07:24:04 +00:00
2009-05-11 09:07:58 +00:00
case MT_L2RELEASE :
if ( l3m - > pid < 128 )
mISDNport - > l2mask [ l3m - > pid > > 3 ] & = ~ ( 1 < < ( l3m - > pid & 7 ) ) ;
2010-01-16 10:20:23 +00:00
if ( ! mISDNport - > l2establish . active ) {
2009-05-11 09:07:58 +00:00
l1l2l3_trace_header ( mISDNport , NULL , L2_RELEASE_IND , DIRECTION_IN ) ;
add_trace ( " tei " , NULL , " %d " , l3m - > pid ) ;
end_trace ( ) ;
/* down if not nt-ptmp */
if ( ! mISDNport - > ntmode | | mISDNport - > ptp )
mISDNport - > l2link = 0 ;
}
2010-12-13 08:22:49 +00:00
if ( ! mISDNport - > isloopback & & ( ! mISDNport - > ntmode | | mISDNport - > ptp ) & & l3m - > pid < 127 ) {
2010-01-16 10:20:23 +00:00
if ( ! mISDNport - > l2establish . active & & mISDNport - > l2hold ) {
2009-05-11 09:07:58 +00:00
PDEBUG ( DEBUG_ISDN , " set timer and establish. \n " ) ;
2010-01-16 10:20:23 +00:00
schedule_timer ( & mISDNport - > l2establish , 5 , 0 ) ;
2009-05-11 09:07:58 +00:00
mISDNport - > ml3 - > to_layer3 ( mISDNport - > ml3 , MT_L2ESTABLISH , 0 , NULL ) ;
}
}
break ;
default :
/* l3-data is sent to LCR */
stack2manager ( mISDNport , l3m - > type , l3m - > pid , l3m ) ;
}
/* free message */
free_l3_msg ( l3m ) ;
2008-04-24 07:24:04 +00:00
}
}
2010-01-16 10:20:23 +00:00
mISDNport = mISDNport - > next ;
}
return 0 ;
}
2008-04-24 07:24:04 +00:00
2010-01-16 10:20:23 +00:00
/* l2 establish timer fires */
static int l2establish_timeout ( struct lcr_timer * timer , void * instance , int i )
{
struct mISDNport * mISDNport = ( struct mISDNport * ) instance ;
2007-08-29 16:56:03 +00:00
2010-12-13 08:22:49 +00:00
if ( ! mISDNport - > isloopback & & mISDNport - > l2hold & & ( mISDNport - > ptp | | ! mISDNport - > ntmode ) ) {
2010-01-16 10:20:23 +00:00
// PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
mISDNport - > ml3 - > to_layer3 ( mISDNport - > ml3 , MT_L2ESTABLISH , 0 , NULL ) ;
schedule_timer ( & mISDNport - > l2establish , 5 , 0 ) ; /* 5 seconds */
}
2007-08-29 16:56:03 +00:00
2010-01-16 10:20:23 +00:00
return 0 ;
}
/* handle frames from bchannel */
static int b_sock_callback ( struct lcr_fd * fd , unsigned int what , void * instance , int i )
{
struct mISDNport * mISDNport = ( struct mISDNport * ) instance ;
unsigned char buffer [ 2048 + MISDN_HEADER_LEN ] ;
struct mISDNhead * hh = ( struct mISDNhead * ) buffer ;
int ret ;
2007-08-29 16:56:03 +00:00
2010-01-16 10:20:23 +00:00
ret = recv ( fd - > fd , buffer , sizeof ( buffer ) , 0 ) ;
if ( ret < 0 ) {
PERROR ( " read error frame, errno %d \n " , errno ) ;
return 0 ;
}
if ( ret < ( int ) MISDN_HEADER_LEN ) {
PERROR ( " read short frame, got %d, expected %d \n " , ret , ( int ) MISDN_HEADER_LEN ) ;
return 0 ;
}
switch ( hh - > prim ) {
/* we don't care about confirms, we use rx data to sync tx */
case PH_DATA_CNF :
break ;
2007-08-29 16:56:03 +00:00
2010-01-16 10:20:23 +00:00
/* we receive audio data, we respond to it AND we send tones */
case PH_DATA_IND :
case DL_DATA_IND :
case PH_DATA_REQ :
case DL_DATA_REQ :
case PH_CONTROL_IND :
if ( mISDNport - > b_port [ i ] )
mISDNport - > b_port [ i ] - > bchannel_receive ( hh , buffer + MISDN_HEADER_LEN , ret - MISDN_HEADER_LEN ) ;
else
PDEBUG ( DEBUG_BCHANNEL , " b-channel is not associated to an ISDNPort (socket %d), ignoring. \n " , fd - > fd ) ;
break ;
case PH_ACTIVATE_IND :
case DL_ESTABLISH_IND :
case PH_ACTIVATE_CNF :
case DL_ESTABLISH_CNF :
PDEBUG ( DEBUG_BCHANNEL , " DL_ESTABLISH confirm: bchannel is now activated (socket %d). \n " , fd - > fd ) ;
bchannel_event ( mISDNport , i , B_EVENT_ACTIVATED ) ;
break ;
case PH_DEACTIVATE_IND :
case DL_RELEASE_IND :
case PH_DEACTIVATE_CNF :
case DL_RELEASE_CNF :
PDEBUG ( DEBUG_BCHANNEL , " DL_RELEASE confirm: bchannel is now de-activated (socket %d). \n " , fd - > fd ) ;
bchannel_event ( mISDNport , i , B_EVENT_DEACTIVATED ) ;
break ;
default :
PERROR ( " child message not handled: prim(0x%x) socket(%d) msg->len(%d) \n " , hh - > prim , fd - > fd , ret - MISDN_HEADER_LEN ) ;
2007-08-29 16:56:03 +00:00
}
2010-01-16 10:20:23 +00:00
return 0 ;
}
/* process timer events for bchannel handling */
static int b_timer_timeout ( struct lcr_timer * timer , void * instance , int i )
{
struct mISDNport * mISDNport = ( struct mISDNport * ) instance ;
puts ( " fires " ) ;
bchannel_event ( mISDNport , i , B_EVENT_TIMEOUT ) ;
return 0 ;
2007-08-29 16:56:03 +00:00
}
2010-01-16 10:20:23 +00:00
2007-08-29 16:56:03 +00:00
int do_layer3 ( struct mlayer3 * ml3 , unsigned int cmd , unsigned int pid , struct l3_msg * l3m )
{
2008-04-13 17:52:42 +00:00
/* IMPORTAINT:
*
2008-04-24 07:24:04 +00:00
* l3m must be queued , except for MT_ASSIGN
2008-04-13 17:52:42 +00:00
*
*/
struct mISDNport * mISDNport = ( struct mISDNport * ) ml3 - > priv ;
2008-04-24 07:24:04 +00:00
struct mbuffer * mb ;
2008-04-13 17:52:42 +00:00
/* special MT_ASSIGN handling:
*
* if we request a PID from mlayer , we always do it while lcr is locked .
* therefore we must check the MT_ASSIGN reply first before we lock .
* this is because the MT_ASSIGN reply is received with the requesting
* process , not by the mlayer thread !
* this means , that the reply is sent during call of the request .
* we must check if we get a reply and we know that we lcr is currently
* locked .
*/
2009-05-14 18:31:43 +00:00
if ( cmd = = MT_ASSIGN & & ( pid & MISDN_PID_CR_FLAG ) & & ( pid > > 16 ) = = MISDN_CES_MASTER ) {
2008-04-13 17:52:42 +00:00
/* let's do some checking if someone changes stack behaviour */
if ( mt_assign_pid ! = 0 )
FATAL ( " someone played with the mISDNuser stack. MT_ASSIGN not currently expected. \n " ) ;
mt_assign_pid = pid ;
return ( 0 ) ;
2007-08-29 16:56:03 +00:00
}
2008-04-24 07:24:04 +00:00
/* queue message, create, if required */
2009-05-14 18:31:43 +00:00
if ( ! l3m ) {
2008-04-24 07:24:04 +00:00
l3m = alloc_l3_msg ( ) ;
if ( ! l3m )
FATAL ( " No memory for layer 3 message \n " ) ;
}
mb = container_of ( l3m , struct mbuffer , l3 ) ;
l3m - > type = cmd ;
l3m - > pid = pid ;
mqueue_tail ( & mISDNport - > upqueue , mb ) ;
2010-01-16 10:20:23 +00:00
if ( ! upqueue_avail ) {
2010-01-16 10:42:46 +00:00
// multiple threads may cause multiple calls of this section, but this
// results only in multiple processing of the upqueue read.
// this is no problem.
2010-01-16 10:20:23 +00:00
upqueue_avail = 1 ;
char byte = 0 ;
2010-03-11 13:07:20 +00:00
int ret ;
ret = write ( upqueue_pipe [ 1 ] , & byte , 1 ) ;
2010-01-16 10:20:23 +00:00
}
2008-04-24 07:24:04 +00:00
return 0 ;
2007-08-29 16:56:03 +00:00
}
2008-04-24 07:24:04 +00:00
2009-05-11 09:07:58 +00:00
int mISDN_getportbyname ( int sock , int cnt , char * portname )
{
struct mISDN_devinfo devinfo ;
int port = 0 , ret ;
/* resolve name */
2009-05-14 18:31:43 +00:00
while ( port < cnt ) {
2009-05-11 09:07:58 +00:00
devinfo . id = port ;
ret = ioctl ( sock , IMGETDEVINFO , & devinfo ) ;
if ( ret < 0 )
return ret ;
if ( ! strcasecmp ( devinfo . name , portname ) )
break ;
port + + ;
}
if ( port = = cnt )
return - EIO ;
return ( port ) ;
}
2007-05-06 13:54:52 +00:00
/*
* global function to add a new card ( port )
*/
2010-01-15 20:55:25 +00:00
struct mISDNport * mISDNport_open ( struct interface_port * ifport )
2007-05-06 13:54:52 +00:00
{
int ret ;
struct mISDNport * mISDNport , * * mISDNportp ;
2010-01-15 20:55:25 +00:00
int port = ifport - > portnum ;
int ptp = ifport - > ptp ;
int force_nt = ifport - > nt ;
int l1hold = ifport - > l1hold ;
int l2hold = ifport - > l2hold ;
2010-12-13 08:22:49 +00:00
int loop = 0 ;
2010-01-15 20:55:25 +00:00
int ss5 = ifport - > ss5 ;
2007-05-06 13:54:52 +00:00
int i , cnt ;
2008-04-13 17:52:42 +00:00
int pri , bri , pots ;
2007-08-26 13:23:58 +00:00
int nt , te ;
2008-04-13 17:52:42 +00:00
// struct mlayer3 *ml3;
2007-08-26 13:23:58 +00:00
struct mISDN_devinfo devinfo ;
2008-04-13 17:52:42 +00:00
unsigned int protocol , prop ;
2007-08-26 13:23:58 +00:00
2010-05-31 16:45:02 +00:00
# if defined WITH_GSM_BS && defined WITH_GSM_MS
2010-12-13 08:22:49 +00:00
loop = ifport - > gsm_ms | ifport - > gsm_bs ;
2010-05-31 16:45:02 +00:00
# else
# ifdef WITH_GSM_BS
2010-12-13 08:22:49 +00:00
loop = ifport - > gsm_bs ;
2010-05-31 16:45:02 +00:00
# endif
# ifdef WITH_GSM_MS
2010-12-13 08:22:49 +00:00
loop = ifport - > gsm_ms ;
2010-05-31 16:45:02 +00:00
# endif
# endif
2010-12-13 08:22:49 +00:00
//printf("%s == %s\n", ifport->portname, options.loopback_int);
if ( ! strcmp ( ifport - > portname , options . loopback_lcr ) )
loop = 1 ;
if ( loop ) {
if ( mISDNloop_open ( ) )
return NULL ;
}
2010-05-31 16:45:02 +00:00
2008-09-07 08:31:58 +00:00
/* check port counts */
2007-08-26 13:23:58 +00:00
ret = ioctl ( mISDNsocket , IMGETCOUNT , & cnt ) ;
2009-05-14 18:31:43 +00:00
if ( ret < 0 ) {
2007-08-26 13:23:58 +00:00
fprintf ( stderr , " Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d) \n " , ret ) ;
return ( NULL ) ;
}
2009-05-14 18:31:43 +00:00
if ( cnt < = 0 ) {
2007-07-31 05:34:18 +00:00
PERROR_RUNTIME ( " Found no card. Please be sure to load card drivers. \n " ) ;
2007-05-06 13:54:52 +00:00
return ( NULL ) ;
}
2009-05-14 18:31:43 +00:00
if ( port < 0 ) {
2010-01-15 20:55:25 +00:00
port = mISDN_getportbyname ( mISDNsocket , cnt , ifport - > portname ) ;
2009-05-14 18:31:43 +00:00
if ( port < 0 ) {
2010-12-13 08:22:49 +00:00
if ( loop )
PERROR_RUNTIME ( " Port name '%s' not found, did you load loopback interface?. \n " , ifport - > portname ) ;
2009-05-11 09:07:58 +00:00
else
2010-01-15 20:55:25 +00:00
PERROR_RUNTIME ( " Port name '%s' not found, use 'misdn_info' tool to list all existing ports. \n " , ifport - > portname ) ;
2008-09-07 08:31:58 +00:00
return ( NULL ) ;
}
// note: 'port' has still the port number
}
2009-05-14 18:31:43 +00:00
if ( port > cnt | | port < 0 ) {
2008-09-06 11:59:48 +00:00
PERROR_RUNTIME ( " Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d) \n " , port , 0 , cnt ) ;
2007-05-06 13:54:52 +00:00
return ( NULL ) ;
}
2007-08-26 13:23:58 +00:00
2008-09-07 08:31:58 +00:00
/* get port attributes */
2008-04-13 17:52:42 +00:00
pri = bri = pots = nt = te = 0 ;
2008-09-06 11:59:48 +00:00
devinfo . id = port ;
2008-04-13 17:52:42 +00:00
ret = ioctl ( mISDNsocket , IMGETDEVINFO , & devinfo ) ;
2009-05-14 18:31:43 +00:00
if ( ret < 0 ) {
2008-09-07 08:31:58 +00:00
PERROR_RUNTIME ( " Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d) \n " , port , ret ) ;
2008-04-13 17:52:42 +00:00
return ( NULL ) ;
2007-08-26 13:23:58 +00:00
}
2009-05-14 18:31:43 +00:00
if ( devinfo . Dprotocols & ( 1 < < ISDN_P_TE_S0 ) ) {
2007-08-26 13:23:58 +00:00
bri = 1 ;
te = 1 ;
}
2009-05-14 18:31:43 +00:00
if ( devinfo . Dprotocols & ( 1 < < ISDN_P_NT_S0 ) ) {
2007-08-26 13:23:58 +00:00
bri = 1 ;
nt = 1 ;
}
2009-05-14 18:31:43 +00:00
if ( devinfo . Dprotocols & ( 1 < < ISDN_P_TE_E1 ) ) {
2007-08-26 13:23:58 +00:00
pri = 1 ;
te = 1 ;
}
2009-05-14 18:31:43 +00:00
if ( devinfo . Dprotocols & ( 1 < < ISDN_P_NT_E1 ) ) {
2007-08-26 13:23:58 +00:00
pri = 1 ;
nt = 1 ;
}
# ifdef ISDN_P_FXS
2009-05-14 18:31:43 +00:00
if ( devinfo . Dprotocols & ( 1 < < ISDN_P_FXS ) ) {
2007-08-26 13:23:58 +00:00
pots = 1 ;
te = 1 ;
}
# endif
# ifdef ISDN_P_FXO
2009-05-14 18:31:43 +00:00
if ( devinfo . Dprotocols & ( 1 < < ISDN_P_FXO ) ) {
2007-08-26 13:23:58 +00:00
pots = 1 ;
nt = 1 ;
}
# endif
2009-05-14 18:31:43 +00:00
if ( force_nt & & ! nt ) {
2008-04-24 07:24:04 +00:00
PERROR_RUNTIME ( " Port %d does not support NT-mode \n " , port ) ;
2007-08-26 13:23:58 +00:00
return ( NULL ) ;
}
2009-05-14 18:31:43 +00:00
if ( bri & & pri ) {
2007-08-26 13:23:58 +00:00
PERROR_RUNTIME ( " Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!) \n " , port ) ;
return ( NULL ) ;
}
2009-05-14 18:31:43 +00:00
if ( pots & & ! bri & & ! pri ) {
2007-08-26 13:23:58 +00:00
PERROR_RUNTIME ( " Port %d supports POTS, LCR does not! \n " , port ) ;
return ( NULL ) ;
}
2009-05-14 18:31:43 +00:00
if ( ! bri & & ! pri ) {
2007-08-26 13:23:58 +00:00
PERROR_RUNTIME ( " Port %d does not support BRI nor PRI! \n " , port ) ;
return ( NULL ) ;
}
2009-05-14 18:31:43 +00:00
if ( ! nt & & ! te ) {
2007-08-26 13:23:58 +00:00
PERROR_RUNTIME ( " Port %d does not support NT-mode nor TE-mode! \n " , port ) ;
return ( NULL ) ;
}
2008-04-24 07:24:04 +00:00
/* set NT by turning off TE */
2007-08-26 13:23:58 +00:00
if ( force_nt & & nt )
te = 0 ;
/* if TE an NT is supported (and not forced to NT), turn off NT */
if ( te & & nt )
nt = 0 ;
2007-05-06 13:54:52 +00:00
2008-09-07 08:31:58 +00:00
/* check for double use of port */
2009-05-14 18:31:43 +00:00
if ( nt ) {
2008-09-07 08:31:58 +00:00
mISDNport = mISDNport_first ;
2009-05-14 18:31:43 +00:00
while ( mISDNport ) {
2008-09-07 08:31:58 +00:00
if ( mISDNport - > portnum = = port )
break ;
mISDNport = mISDNport - > next ;
}
2009-05-14 18:31:43 +00:00
if ( mISDNport ) {
2008-09-07 08:31:58 +00:00
PERROR_RUNTIME ( " Port %d already in use by LCR. You can't use a NT port multiple times. \n " , port ) ;
return ( NULL ) ;
}
}
2009-05-11 09:07:58 +00:00
/* check for continous channelmap with no bchannel on slot 16 */
2009-05-14 18:31:43 +00:00
if ( test_channelmap ( 0 , devinfo . channelmap ) ) {
2009-05-11 09:07:58 +00:00
PERROR_RUNTIME ( " Port %d provides channel 0, but we cannot access it! \n " , port ) ;
return ( NULL ) ;
}
i = 1 ;
2009-05-14 18:31:43 +00:00
while ( i < ( int ) devinfo . nrbchan + 1 ) {
2009-05-11 09:07:58 +00:00
if ( i = = 16 ) {
2009-05-14 18:31:43 +00:00
if ( test_channelmap ( i , devinfo . channelmap ) ) {
2009-05-11 09:07:58 +00:00
PERROR ( " Port %d provides bchannel 16. Pleas upgrade mISDN, if this port is mISDN loopback interface. \n " , port ) ;
return ( NULL ) ;
}
2009-05-14 18:31:43 +00:00
} else {
if ( ! test_channelmap ( i , devinfo . channelmap ) ) {
2009-05-11 09:07:58 +00:00
PERROR_RUNTIME ( " Port %d has no channel on slot %d! \n " , port , i ) ;
return ( NULL ) ;
}
}
i + + ;
}
2008-09-07 08:31:58 +00:00
2007-05-06 13:54:52 +00:00
/* add mISDNport structure */
mISDNportp = & mISDNport_first ;
while ( * mISDNportp )
2007-07-07 15:13:20 +00:00
mISDNportp = & ( ( * mISDNportp ) - > next ) ;
2007-07-15 10:01:27 +00:00
mISDNport = ( struct mISDNport * ) MALLOC ( sizeof ( struct mISDNport ) ) ;
2010-01-16 10:20:23 +00:00
add_timer ( & mISDNport - > l2establish , l2establish_timeout , mISDNport , 0 ) ;
2010-12-13 08:22:49 +00:00
if ( loop | ss5 ) {
/* loop/ss5 link is always active */
2009-05-11 09:07:58 +00:00
mISDNport - > l1link = 1 ;
mISDNport - > l2link = 1 ;
2009-05-14 18:31:43 +00:00
} else {
2009-05-11 09:07:58 +00:00
mISDNport - > l1link = - 1 ;
mISDNport - > l2link = - 1 ;
}
2010-05-31 16:45:02 +00:00
# ifdef WITH_GSM_BS
mISDNport - > gsm_bs = ifport - > gsm_bs ;
# endif
# ifdef WITH_GSM_MS
mISDNport - > gsm_ms = ifport - > gsm_ms ;
# endif
2010-12-13 08:22:49 +00:00
mISDNport - > isloopback = loop ;
2007-05-06 13:54:52 +00:00
pmemuse + + ;
* mISDNportp = mISDNport ;
2008-05-09 19:31:58 +00:00
/* if pri, must set PTP */
2008-04-24 07:24:04 +00:00
if ( pri )
ptp = 1 ;
2009-09-26 11:20:29 +00:00
/* set ss5 params */
if ( ss5 ) {
/* try to keep interface enabled */
l1hold = 1 ;
l2hold = 1 ;
}
2008-04-24 07:24:04 +00:00
/* set l2hold */
2009-05-14 18:31:43 +00:00
switch ( l2hold ) {
2008-04-24 07:24:04 +00:00
case - 1 : // off
l2hold = 0 ;
break ;
case 1 : // on
2008-05-09 19:31:58 +00:00
l2hold = 1 ;
2008-04-24 07:24:04 +00:00
break ;
default :
if ( ptp )
l2hold = 1 ;
else
l2hold = 0 ;
break ;
}
2007-05-06 13:54:52 +00:00
/* allocate ressources of port */
2008-05-09 19:31:58 +00:00
protocol = ( nt ) ? L3_PROTOCOL_DSS1_NET : L3_PROTOCOL_DSS1_USER ;
prop = ( 1 < < MISDN_FLG_L2_CLEAN ) ;
2008-04-13 17:52:42 +00:00
if ( ptp ) // ptp forced
2008-04-24 07:24:04 +00:00
prop | = ( 1 < < MISDN_FLG_PTP ) ;
2008-04-13 17:52:42 +00:00
if ( nt ) // supports hold/retrieve on nt-mode
2008-04-24 07:24:04 +00:00
prop | = ( 1 < < MISDN_FLG_NET_HOLD ) ;
2009-03-20 19:46:25 +00:00
if ( l1hold ) // supports layer 1 hold
prop | = ( 1 < < MISDN_FLG_L1_HOLD ) ;
2008-04-24 07:24:04 +00:00
if ( l2hold ) // supports layer 2 hold
prop | = ( 1 < < MISDN_FLG_L2_HOLD ) ;
2009-05-11 09:07:58 +00:00
/* open layer 3 and init upqueue */
2010-12-13 08:22:49 +00:00
if ( loop ) {
2009-05-11 09:07:58 +00:00
unsigned long on = 1 ;
struct sockaddr_mISDN addr ;
2007-07-31 05:34:18 +00:00
2009-05-14 18:31:43 +00:00
if ( devinfo . nrbchan < 8 ) {
2010-12-13 08:22:49 +00:00
printf ( " loop port %d has a low number of bchannels. (only %d) remember that all interfaces that requires a loopback could run out of channels \n " , port , devinfo . nrbchan ) ;
// mISDNport_close(mISDNport);
// return(NULL);
2009-05-11 09:07:58 +00:00
}
2010-12-13 08:22:49 +00:00
if ( ( mISDNport - > lcr_sock = socket ( PF_ISDN , SOCK_DGRAM , ( bri ) ? ISDN_P_TE_S0 : ISDN_P_TE_E1 ) ) < 0 ) {
PERROR_RUNTIME ( " loop port %d failed to open socket. \n " , port ) ;
2009-05-11 09:07:58 +00:00
mISDNport_close ( mISDNport ) ;
return ( NULL ) ;
}
/* set nonblocking io */
2009-05-14 18:31:43 +00:00
if ( ioctl ( mISDNport - > lcr_sock , FIONBIO , & on ) < 0 ) {
2010-12-13 08:22:49 +00:00
PERROR_RUNTIME ( " loop port %d failed to set socket into nonblocking io. \n " , port ) ;
2009-05-11 09:07:58 +00:00
mISDNport_close ( mISDNport ) ;
return ( NULL ) ;
}
/* bind socket to dchannel */
memset ( & addr , 0 , sizeof ( addr ) ) ;
addr . family = AF_ISDN ;
addr . dev = port ;
addr . channel = 0 ;
2009-05-14 18:31:43 +00:00
if ( bind ( mISDNport - > lcr_sock , ( struct sockaddr * ) & addr , sizeof ( addr ) ) < 0 ) {
2010-12-13 08:22:49 +00:00
PERROR_RUNTIME ( " loop port %d failed to bind socket. (errno %d) \n " , port , errno ) ;
2009-05-11 09:07:58 +00:00
mISDNport_close ( mISDNport ) ;
return ( NULL ) ;
}
2009-05-14 18:31:43 +00:00
} else {
2009-05-11 09:07:58 +00:00
/* queue must be initializes, because l3-thread may send messages during open_layer3() */
mqueue_init ( & mISDNport - > upqueue ) ;
mISDNport - > ml3 = open_layer3 ( port , protocol , prop , do_layer3 , mISDNport ) ;
2009-05-14 18:31:43 +00:00
if ( ! mISDNport - > ml3 ) {
2009-05-11 09:07:58 +00:00
mqueue_purge ( & mISDNport - > upqueue ) ;
PERROR_RUNTIME ( " open_layer3() failed for port %d \n " , port ) ;
start_trace ( port ,
2010-01-15 20:55:25 +00:00
ifport - > interface ,
2009-05-11 09:07:58 +00:00
NULL ,
NULL ,
DIRECTION_NONE ,
CATEGORY_CH ,
0 ,
" PORT (open failed) " ) ;
end_trace ( ) ;
mISDNport_close ( mISDNport ) ;
return ( NULL ) ;
}
2007-07-31 05:34:18 +00:00
}
2007-08-26 13:23:58 +00:00
SCPY ( mISDNport - > name , devinfo . name ) ;
mISDNport - > b_num = devinfo . nrbchan ;
2007-07-31 05:34:18 +00:00
mISDNport - > portnum = port ;
mISDNport - > ntmode = nt ;
2010-01-15 20:55:25 +00:00
mISDNport - > tespecial = ifport - > tespecial ;
2007-07-31 05:34:18 +00:00
mISDNport - > pri = pri ;
mISDNport - > ptp = ptp ;
2009-03-20 19:46:25 +00:00
mISDNport - > l1hold = l1hold ;
2008-04-24 07:24:04 +00:00
mISDNport - > l2hold = l2hold ;
2009-09-26 11:20:29 +00:00
mISDNport - > ss5 = ss5 ;
2007-07-31 05:34:18 +00:00
PDEBUG ( DEBUG_ISDN , " Port has %d b-channels. \n " , mISDNport - > b_num ) ;
i = 0 ;
2009-05-14 18:31:43 +00:00
while ( i < mISDNport - > b_num ) {
2007-07-31 05:34:18 +00:00
mISDNport - > b_state [ i ] = B_STATE_IDLE ;
2010-01-16 10:20:23 +00:00
add_timer ( & mISDNport - > b_timer [ i ] , b_timer_timeout , mISDNport , i ) ;
2007-07-31 05:34:18 +00:00
i + + ;
}
2008-04-13 17:52:42 +00:00
/* if ptp, pull up the link */
2010-12-13 08:22:49 +00:00
if ( ! mISDNport - > isloopback & & mISDNport - > l2hold & & ( mISDNport - > ptp | | ! mISDNport - > ntmode ) ) {
2008-04-24 07:24:04 +00:00
mISDNport - > ml3 - > to_layer3 ( mISDNport - > ml3 , MT_L2ESTABLISH , 0 , NULL ) ;
l1l2l3_trace_header ( mISDNport , NULL , L2_ESTABLISH_REQ , DIRECTION_OUT ) ;
2008-05-12 09:39:44 +00:00
add_trace ( " tei " , NULL , " %d " , 0 ) ;
2008-04-24 07:24:04 +00:00
end_trace ( ) ;
2010-01-16 10:20:23 +00:00
schedule_timer ( & mISDNport - > l2establish , 5 , 0 ) ; /* 5 seconds */
2008-04-13 17:52:42 +00:00
}
2008-04-24 07:24:04 +00:00
2008-09-14 12:37:51 +00:00
/* for nt-mode ptmp the link is always up */
if ( mISDNport - > ntmode & & ! mISDNport - > ptp )
mISDNport - > l2link = 1 ;
2007-05-06 13:54:52 +00:00
PDEBUG ( DEBUG_BCHANNEL , " using 'mISDN_dsp.o' module \n " ) ;
2007-06-27 06:23:50 +00:00
start_trace ( mISDNport - > portnum ,
2010-01-15 20:55:25 +00:00
ifport - > interface ,
2007-06-27 06:23:50 +00:00
NULL ,
NULL ,
DIRECTION_NONE ,
CATEGORY_CH ,
0 ,
" PORT (open) " ) ;
2008-05-09 19:31:58 +00:00
add_trace ( " mode " , NULL , ( mISDNport - > ntmode ) ? " network " : " terminal " ) ;
2007-06-27 06:23:50 +00:00
add_trace ( " channels " , NULL , " %d " , mISDNport - > b_num ) ;
2009-09-26 11:20:29 +00:00
if ( mISDNport - > ss5 )
add_trace ( " ccitt#5 " , NULL , " enabled " ) ;
2007-06-27 06:23:50 +00:00
end_trace ( ) ;
2009-09-26 11:20:29 +00:00
2007-05-06 13:54:52 +00:00
return ( mISDNport ) ;
}
2009-09-26 11:20:29 +00:00
/*
* load static port instances , if required by mISDNport
*/
void mISDNport_static ( struct mISDNport * mISDNport )
{
int i ;
i = 0 ;
while ( i < mISDNport - > b_num ) {
# ifdef WITH_SS5
if ( mISDNport - > ss5 )
ss5_create_channel ( mISDNport , i ) ;
# endif
i + + ;
}
}
2007-05-06 13:54:52 +00:00
/*
* function to free ALL cards ( ports )
*/
void mISDNport_close_all ( void )
{
/* free all ports */
while ( mISDNport_first )
mISDNport_close ( mISDNport_first ) ;
}
/*
* free only one port
*/
void mISDNport_close ( struct mISDNport * mISDNport )
{
struct mISDNport * * mISDNportp ;
class Port * port ;
2007-06-27 06:23:50 +00:00
class PmISDN * isdnport ;
2007-05-06 13:54:52 +00:00
int i ;
/* remove all port instance that are linked to this mISDNport */
2009-09-30 12:23:23 +00:00
again :
2007-05-06 13:54:52 +00:00
port = port_first ;
2009-05-14 18:31:43 +00:00
while ( port ) {
if ( ( port - > p_type & PORT_CLASS_MASK ) = = PORT_CLASS_mISDN ) {
2007-06-27 06:23:50 +00:00
isdnport = ( class PmISDN * ) port ;
2009-09-30 12:23:23 +00:00
if ( isdnport - > p_m_mISDNport & & isdnport - > p_m_mISDNport = = mISDNport ) {
2007-06-27 06:23:50 +00:00
PDEBUG ( DEBUG_ISDN , " port %s uses mISDNport %d, destroying it. \n " , isdnport - > p_name , mISDNport - > portnum ) ;
delete isdnport ;
2009-09-30 12:23:23 +00:00
goto again ;
2007-05-06 13:54:52 +00:00
}
}
port = port - > next ;
}
2007-07-07 15:13:20 +00:00
/* only if we are already part of interface */
2009-05-14 18:31:43 +00:00
if ( mISDNport - > ifport ) {
2007-07-07 15:13:20 +00:00
start_trace ( mISDNport - > portnum ,
mISDNport - > ifport - > interface ,
NULL ,
NULL ,
DIRECTION_NONE ,
CATEGORY_CH ,
0 ,
" PORT (close) " ) ;
end_trace ( ) ;
}
2007-05-06 13:54:52 +00:00
/* free bchannels */
i = 0 ;
2009-05-14 18:31:43 +00:00
while ( i < mISDNport - > b_num ) {
2010-01-16 10:20:23 +00:00
if ( mISDNport - > b_sock [ i ] . inuse ) {
2007-06-27 06:23:50 +00:00
_bchannel_destroy ( mISDNport , i ) ;
PDEBUG ( DEBUG_BCHANNEL , " freeing %s port %d bchannel (index %d). \n " , ( mISDNport - > ntmode ) ? " NT " : " TE " , mISDNport - > portnum , i ) ;
2007-05-06 13:54:52 +00:00
}
2010-01-16 10:20:23 +00:00
if ( mISDNport - > b_timer [ i ] . inuse ) {
del_timer ( & mISDNport - > b_timer [ i ] ) ;
}
2007-05-06 13:54:52 +00:00
i + + ;
}
2010-01-16 10:20:23 +00:00
del_timer ( & mISDNport - > l2establish ) ;
2007-05-06 13:54:52 +00:00
2009-05-11 09:07:58 +00:00
/* close layer 3, if open */
2010-12-13 08:22:49 +00:00
if ( ! mISDNport - > isloopback & & mISDNport - > ml3 ) {
2008-05-02 19:40:31 +00:00
close_layer3 ( mISDNport - > ml3 ) ;
}
2007-05-06 13:54:52 +00:00
2009-05-11 09:07:58 +00:00
/* close gsm socket, if open */
2010-12-13 08:22:49 +00:00
if ( mISDNport - > isloopback & & mISDNport - > lcr_sock > - 1 ) {
2009-05-11 09:07:58 +00:00
close ( mISDNport - > lcr_sock ) ;
}
/* purge upqueue */
2010-12-13 08:22:49 +00:00
if ( ! mISDNport - > isloopback )
2009-05-11 09:07:58 +00:00
mqueue_purge ( & mISDNport - > upqueue ) ;
2007-05-06 13:54:52 +00:00
/* remove from list */
mISDNportp = & mISDNport_first ;
2009-05-14 18:31:43 +00:00
while ( * mISDNportp ) {
if ( * mISDNportp = = mISDNport ) {
2007-05-06 13:54:52 +00:00
* mISDNportp = ( * mISDNportp ) - > next ;
2007-07-07 15:13:20 +00:00
mISDNportp = NULL ;
2007-05-06 13:54:52 +00:00
break ;
}
mISDNportp = & ( ( * mISDNportp ) - > next ) ;
}
2007-07-07 15:13:20 +00:00
if ( mISDNportp )
2007-07-15 10:01:27 +00:00
FATAL ( " mISDNport not in list \n " ) ;
2007-05-06 13:54:52 +00:00
2007-07-15 10:01:27 +00:00
FREE ( mISDNport , sizeof ( struct mISDNport ) ) ;
2007-05-06 13:54:52 +00:00
pmemuse - - ;
}
2007-06-27 06:23:50 +00:00
/*
* enque data from upper buffer
*/
void PmISDN : : txfromup ( unsigned char * data , int length )
{
2007-08-29 16:56:03 +00:00
unsigned char buf [ MISDN_HEADER_LEN + ( ( length > ISDN_LOAD ) ? length : ISDN_LOAD ) ] ;
2008-04-13 17:52:42 +00:00
struct mISDNhead * hh = ( struct mISDNhead * ) buf ;
int ret ;
2007-08-29 16:56:03 +00:00
if ( p_m_b_index < 0 )
return ;
2008-05-09 19:31:58 +00:00
if ( p_m_mISDNport - > b_state [ p_m_b_index ] ! = B_STATE_ACTIVE )
2007-08-29 16:56:03 +00:00
return ;
2007-07-15 10:01:27 +00:00
/* check if high priority tones exist
* ignore data in this case
*/
2009-09-26 11:20:29 +00:00
if ( p_tone_name [ 0 ] | | p_m_crypt_msg_loops | | p_m_inband_send_on )
2007-06-27 06:23:50 +00:00
return ;
2007-07-15 10:01:27 +00:00
/* preload procedure
* if transmit buffer in DSP module is empty ,
* preload it to DSP_LOAD to prevent jitter gaps .
*/
2010-01-16 10:20:23 +00:00
if ( p_m_load = = 0 & & ISDN_LOAD > 0 ) {
2008-05-09 19:31:58 +00:00
hh - > prim = PH_DATA_REQ ;
2008-04-13 17:52:42 +00:00
hh - > id = 0 ;
2008-04-24 17:14:09 +00:00
memset ( buf + MISDN_HEADER_LEN , ( options . law = = ' a ' ) ? 0x2a : 0xff , ISDN_LOAD ) ;
2010-01-16 10:20:23 +00:00
ret = sendto ( p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , buf , MISDN_HEADER_LEN + ISDN_LOAD , 0 , NULL , 0 ) ;
2008-05-10 19:40:23 +00:00
if ( ret < = 0 )
2010-01-16 10:20:23 +00:00
PERROR ( " Failed to send to socket %d \n " , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd ) ;
2008-04-13 17:52:42 +00:00
p_m_load + = ISDN_LOAD ;
2010-01-16 10:20:23 +00:00
schedule_timer ( & p_m_loadtimer , 0 , ISDN_TRANSMIT * 125 ) ;
2007-06-27 06:23:50 +00:00
}
2007-07-15 10:01:27 +00:00
/* drop if load would exceed ISDN_MAXLOAD
* this keeps the delay not too high
*/
if ( p_m_load + length > ISDN_MAXLOAD )
return ;
2007-08-29 16:56:03 +00:00
/* make and send frame */
2008-05-09 19:31:58 +00:00
hh - > prim = PH_DATA_REQ ;
2008-04-13 17:52:42 +00:00
hh - > id = 0 ;
2007-08-29 16:56:03 +00:00
memcpy ( buf + MISDN_HEADER_LEN , data , length ) ;
2010-01-16 10:20:23 +00:00
ret = sendto ( p_m_mISDNport - > b_sock [ p_m_b_index ] . fd , buf , MISDN_HEADER_LEN + length , 0 , NULL , 0 ) ;
2008-05-10 19:40:23 +00:00
if ( ret < = 0 )
2010-01-16 10:20:23 +00:00
PERROR ( " Failed to send to socket %d \n " , p_m_mISDNport - > b_sock [ p_m_b_index ] . fd ) ;
2007-08-29 16:56:03 +00:00
p_m_load + = length ;
2007-06-27 06:23:50 +00:00
}
2009-09-26 11:20:29 +00:00
int PmISDN : : inband_send ( unsigned char * buffer , int len )
{
PERROR ( " this function must be derived to function! \n " ) ;
return 0 ;
}
void PmISDN : : inband_send_on ( void )
{
PDEBUG ( DEBUG_PORT , " turning inband signalling send on. \n " ) ;
p_m_inband_send_on = 1 ;
2010-01-16 10:20:23 +00:00
/* trigger inband transmit */
update_load ( ) ;
2009-09-26 11:20:29 +00:00
}
void PmISDN : : inband_send_off ( void )
{
PDEBUG ( DEBUG_PORT , " turning inband signalling send off. \n " ) ;
p_m_inband_send_on = 0 ;
}
void PmISDN : : inband_receive ( unsigned char * buffer , int len )
{
//
// if (len >= SS5_DECODER_NPOINTS)
// ss5_decode(buffer, SS5_DECODER_NPOINTS);
PERROR ( " this function must be derived to function! \n " ) ;
}
void PmISDN : : inband_receive_on ( void )
{
/* this must work during constructor, see ss5.cpp */
PDEBUG ( DEBUG_PORT , " turning inband signalling receive on. \n " ) ;
p_m_inband_receive_on = 1 ;
2010-01-16 10:20:23 +00:00
update_rxoff ( ) ;
2009-09-26 11:20:29 +00:00
}
void PmISDN : : inband_receive_off ( void )
{
PDEBUG ( DEBUG_PORT , " turning inband signalling receive off. \n " ) ;
p_m_inband_receive_on = 0 ;
2010-01-16 10:20:23 +00:00
update_rxoff ( ) ;
2009-09-26 11:20:29 +00:00
}
void PmISDN : : mute_on ( void )
{
if ( p_m_mute )
return ;
PDEBUG ( DEBUG_PORT , " turning mute on. \n " ) ;
p_m_mute = 1 ;
set_conf ( p_m_conf , 0 ) ;
}
void PmISDN : : mute_off ( void )
{
if ( ! p_m_mute )
return ;
PDEBUG ( DEBUG_PORT , " turning mute off. \n " ) ;
p_m_mute = 0 ;
set_conf ( 0 , p_m_conf ) ;
}