2008-01-19 17:10:46 +00:00
/*****************************************************************************\
* * * *
* * Linux Call Router * *
* * * *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * *
* * Copyright : Andreas Eversberg * *
* * * *
* * mISDN channel handlin for remote application * *
* * * *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <poll.h>
# include <errno.h>
# include <sys/ioctl.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <netinet/udp.h>
# include <netinet/in.h>
# include <netdb.h>
# include <sys/socket.h>
2010-03-17 07:31:07 +00:00
# include <mISDN/mISDNif.h>
2008-05-01 18:07:02 +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-08-12 14:16:54 +00:00
2009-01-06 17:34:05 +00:00
# define HAVE_ATTRIBUTE_always_inline 1
# define HAVE_ARPA_INET_H 1
# define HAVE_TIMERSUB 1
# include <asterisk/compiler.h>
2008-05-25 14:12:20 +00:00
# include <asterisk/frame.h>
2009-03-15 08:31:23 +00:00
/* Choose if you want to have chan_lcr for Asterisk 1.4.x or CallWeaver 1.2.x */
/* #define LCR_FOR_CALLWEAVER */
# ifdef LCR_FOR_CALLWEAVER
# include <asterisk/phone_no_utils.h>
# include <asterisk/logger.h>
# include <asterisk/module.h>
# include <asterisk/channel.h>
# endif
2008-05-25 14:12:20 +00:00
2008-05-01 18:07:02 +00:00
# include "extension.h"
# include "message.h"
# include "lcrsocket.h"
# include "cause.h"
2010-01-16 10:20:23 +00:00
# include "select.h"
2008-01-19 17:10:46 +00:00
# include "bchannel.h"
2008-05-01 18:07:02 +00:00
# include "chan_lcr.h"
# include "callerid.h"
2010-01-24 13:22:34 +00:00
# include "options.h"
2008-05-01 18:07:02 +00:00
2008-01-19 17:10:46 +00:00
# ifndef ISDN_PID_L4_B_USER
# define ISDN_PID_L4_B_USER 0x440000ff
# endif
pid_t bchannel_pid ;
enum {
BSTATE_IDLE ,
BSTATE_ACTIVATING ,
BSTATE_ACTIVE ,
2008-06-01 16:52:10 +00:00
BSTATE_DEACTIVATING ,
2008-01-19 17:10:46 +00:00
} ;
2010-01-24 13:22:34 +00:00
static void bchannel_send_queue ( struct bchannel * bchannel ) ;
2008-01-19 17:10:46 +00:00
int bchannel_initialize ( void )
{
2010-01-16 10:20:23 +00:00
return 0 ;
2008-01-19 17:10:46 +00:00
}
void bchannel_deinitialize ( void )
{
}
/*
* send control information to the channel ( dsp - module )
*/
2008-06-17 19:13:22 +00:00
static void ph_control ( int sock , unsigned int c1 , unsigned int c2 , char * trace_name , int trace_value , int b_mode )
2008-01-19 17:10:46 +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 ) ;
2008-01-19 17:10:46 +00:00
int ret ;
2008-06-07 09:49:28 +00:00
if ( b_mode ! = 0 & & b_mode ! = 2 )
return ;
2008-06-06 13:18:59 +00:00
CDEBUG ( NULL , NULL , " Sending PH_CONTROL %s %x,%x \n " , trace_name , c1 , c2 ) ;
2008-01-19 17:10:46 +00:00
ctrl - > prim = PH_CONTROL_REQ ;
ctrl - > id = 0 ;
* d + + = c1 ;
* d + + = c2 ;
2008-06-17 19:13:22 +00:00
ret = sendto ( sock , buffer , MISDN_HEADER_LEN + sizeof ( int ) * 2 , 0 , NULL , 0 ) ;
2008-06-01 16:52:10 +00:00
if ( ret < 0 )
2008-06-17 19:13:22 +00:00
CERROR ( NULL , NULL , " Failed to send to socket %d \n " , sock ) ;
2008-01-19 17:10:46 +00:00
}
2008-06-17 19:13:22 +00:00
static void ph_control_block ( int sock , unsigned int c1 , void * c2 , int c2_len , char * trace_name , int trace_value , int b_mode )
2008-01-19 17:10:46 +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 ) ;
2008-01-19 17:10:46 +00:00
int ret ;
2008-06-07 09:49:28 +00:00
if ( b_mode ! = 0 & & b_mode ! = 2 )
return ;
2008-06-06 13:18:59 +00:00
CDEBUG ( NULL , NULL , " Sending PH_CONTROL (block) %s %x \n " , trace_name , c1 ) ;
2008-01-19 17:10:46 +00:00
ctrl - > prim = PH_CONTROL_REQ ;
ctrl - > id = 0 ;
* d + + = c1 ;
memcpy ( d , c2 , c2_len ) ;
2008-06-17 19:13:22 +00:00
ret = sendto ( sock , buffer , MISDN_HEADER_LEN + sizeof ( int ) + c2_len , 0 , NULL , 0 ) ;
2008-06-01 16:52:10 +00:00
if ( ret < 0 )
2008-06-17 19:13:22 +00:00
CERROR ( NULL , NULL , " Failed to send to socket %d \n " , sock ) ;
2008-01-19 17:10:46 +00:00
}
2010-01-16 10:20:23 +00:00
static int bchannel_handle ( struct lcr_fd * fd , unsigned int what , void * instance , int index ) ;
2008-01-19 17:10:46 +00:00
/*
* create stack
*/
2010-01-24 13:22:34 +00:00
int bchannel_create ( struct bchannel * bchannel , int mode , int queue )
2008-01-19 17:10:46 +00:00
{
int ret ;
2008-05-25 14:12:20 +00:00
struct sockaddr_mISDN addr ;
2008-01-19 17:10:46 +00:00
2009-06-06 21:46:21 +00:00
if ( bchannel - > b_sock > - 1 ) {
2008-07-26 11:49:23 +00:00
CERROR ( bchannel - > call , NULL , " Socket already created for handle 0x%x \n " , bchannel - > handle ) ;
2010-01-16 10:20:23 +00:00
return 0 ;
2008-01-19 17:10:46 +00:00
}
/* open socket */
2010-01-24 13:22:34 +00:00
bchannel - > b_mode = ( mode & 3 ) ;
2009-06-06 21:46:21 +00:00
switch ( bchannel - > b_mode ) {
2008-06-07 09:49:28 +00:00
case 0 :
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " Open DSP audio \n " ) ;
2008-06-07 09:49:28 +00:00
bchannel - > b_sock = socket ( PF_ISDN , SOCK_DGRAM , ISDN_P_B_L2DSP ) ;
break ;
case 1 :
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " Open audio \n " ) ;
2008-06-07 09:49:28 +00:00
bchannel - > b_sock = socket ( PF_ISDN , SOCK_DGRAM , ISDN_P_B_RAW ) ;
break ;
case 2 :
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " Open DSP HDLC \n " ) ;
2008-06-07 09:49:28 +00:00
bchannel - > b_sock = socket ( PF_ISDN , SOCK_DGRAM , ISDN_P_B_L2DSPHDLC ) ;
break ;
case 3 :
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " Open HDLC \n " ) ;
2008-06-07 09:49:28 +00:00
bchannel - > b_sock = socket ( PF_ISDN , SOCK_DGRAM , ISDN_P_B_HDLC ) ;
break ;
}
2009-06-06 21:46:21 +00:00
if ( bchannel - > b_sock < 0 ) {
2008-09-12 05:43:21 +00:00
CERROR ( bchannel - > call , NULL , " Failed to open bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDN_dsp.ko? \n " , bchannel - > handle ) ;
2010-01-16 10:20:23 +00:00
return 0 ;
2008-01-19 17:10:46 +00:00
}
2010-01-16 10:20:23 +00:00
/* register fd */
memset ( & bchannel - > lcr_fd , 0 , sizeof ( bchannel - > lcr_fd ) ) ;
bchannel - > lcr_fd . fd = bchannel - > b_sock ;
register_fd ( & bchannel - > lcr_fd , LCR_FD_READ | LCR_FD_EXCEPT , bchannel_handle , bchannel , 0 ) ;
2008-01-19 17:10:46 +00:00
/* bind socket to bchannel */
addr . family = AF_ISDN ;
2008-09-06 11:59:48 +00:00
addr . dev = ( bchannel - > handle > > 8 ) ;
2008-06-04 16:09:43 +00:00
addr . channel = bchannel - > handle & 0xff ;
2008-05-01 18:07:02 +00:00
ret = bind ( bchannel - > b_sock , ( struct sockaddr * ) & addr , sizeof ( addr ) ) ;
2009-06-06 21:46:21 +00:00
if ( ret < 0 ) {
2008-09-12 05:43:21 +00:00
CERROR ( bchannel - > call , NULL , " Failed to bind bchannel-socket for handle 0x%x with mISDN-DSP layer. (port %d, channel %d) Did you load mISDN_dsp.ko? \n " , bchannel - > handle , addr . dev , addr . channel ) ;
2010-01-16 10:20:23 +00:00
unregister_fd ( & bchannel - > lcr_fd ) ;
2008-05-01 18:07:02 +00:00
close ( bchannel - > b_sock ) ;
2008-05-25 14:12:20 +00:00
bchannel - > b_sock = - 1 ;
2010-01-16 10:20:23 +00:00
return 0 ;
2008-01-19 17:10:46 +00:00
}
2010-01-24 13:22:34 +00:00
/* queue */
if ( bchannel - > b_mode = = 1 & & queue ) {
bchannel - > nodsp_queue_out = 0 ;
bchannel - > nodsp_queue_in = queue * 8 ;
if ( bchannel - > nodsp_queue_in > QUEUE_BUFFER_MAX - 1 )
bchannel - > nodsp_queue_in = QUEUE_BUFFER_MAX - 1 ;
bchannel - > nodsp_queue = bchannel - > nodsp_queue_in ; /* store initial load */
memset ( & bchannel - > nodsp_queue_buffer , ( options . law = = ' a ' ) ? 0x2a : 0xff , QUEUE_BUFFER_SIZE ) ;
bchannel - > queue_sent = 0 ;
} else
bchannel - > nodsp_queue = 0 ;
2010-01-16 10:20:23 +00:00
return 1 ;
2008-05-25 14:12:20 +00:00
}
2008-01-19 17:10:46 +00:00
/*
* activate / deactivate request
*/
2008-05-01 18:07:02 +00:00
void bchannel_activate ( struct bchannel * bchannel , int activate )
2008-01-19 17:10:46 +00:00
{
struct mISDNhead act ;
int ret ;
2008-06-01 16:52:10 +00:00
/* activate bchannel */
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " %sActivating B-channel. \n " , activate ? " " : " De- " ) ;
2009-06-06 21:46:21 +00:00
switch ( bchannel - > b_mode ) {
2008-06-07 09:49:28 +00:00
case 0 :
case 2 :
act . prim = ( activate ) ? DL_ESTABLISH_REQ : DL_RELEASE_REQ ;
break ;
case 1 :
case 3 :
act . prim = ( activate ) ? PH_ACTIVATE_REQ : PH_DEACTIVATE_REQ ;
break ;
}
2008-01-19 17:10:46 +00:00
act . id = 0 ;
2008-05-01 18:07:02 +00:00
ret = sendto ( bchannel - > b_sock , & act , MISDN_HEADER_LEN , 0 , NULL , 0 ) ;
2008-06-01 16:52:10 +00:00
if ( ret < 0 )
2008-07-26 11:49:23 +00:00
CERROR ( bchannel - > call , NULL , " Failed to send to socket %d \n " , bchannel - > b_sock ) ;
2008-01-19 17:10:46 +00:00
2008-06-01 16:52:10 +00:00
bchannel - > b_state = ( activate ) ? BSTATE_ACTIVATING : BSTATE_DEACTIVATING ;
2008-01-19 17:10:46 +00:00
}
/*
* set features
*/
2008-05-01 18:07:02 +00:00
static void bchannel_activated ( struct bchannel * bchannel )
2008-01-19 17:10:46 +00:00
{
2008-06-17 19:13:22 +00:00
int sock ;
2008-01-19 17:10:46 +00:00
2008-06-17 19:13:22 +00:00
sock = bchannel - > b_sock ;
2008-01-19 17:10:46 +00:00
/* set dsp features */
2008-05-01 18:07:02 +00:00
if ( bchannel - > b_txdata )
2008-06-17 19:13:22 +00:00
ph_control ( sock , ( bchannel - > b_txdata ) ? DSP_TXDATA_ON : DSP_TXDATA_OFF , 0 , " DSP-TXDATA " , bchannel - > b_txdata , bchannel - > b_mode ) ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_delay & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_DELAY , bchannel - > b_delay , " DSP-DELAY " , bchannel - > b_delay , bchannel - > b_mode ) ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_tx_dejitter & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control ( sock , ( bchannel - > b_tx_dejitter ) ? DSP_TX_DEJITTER : DSP_TX_DEJ_OFF , 0 , " DSP-TX_DEJITTER " , bchannel - > b_tx_dejitter , bchannel - > b_mode ) ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_tx_gain & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_VOL_CHANGE_TX , bchannel - > b_tx_gain , " DSP-TX_GAIN " , bchannel - > b_tx_gain , bchannel - > b_mode ) ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_rx_gain & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_VOL_CHANGE_RX , bchannel - > b_rx_gain , " DSP-RX_GAIN " , bchannel - > b_rx_gain , bchannel - > b_mode ) ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_pipeline [ 0 ] & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control_block ( sock , DSP_PIPELINE_CFG , bchannel - > b_pipeline , strlen ( bchannel - > b_pipeline ) + 1 , " DSP-PIPELINE " , 0 , bchannel - > b_mode ) ;
2008-05-01 18:07:02 +00:00
if ( bchannel - > b_conf )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_CONF_JOIN , bchannel - > b_conf , " DSP-CONF " , bchannel - > b_conf , bchannel - > b_mode ) ;
2008-05-01 18:07:02 +00:00
if ( bchannel - > b_echo )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_ECHO_ON , 0 , " DSP-ECHO " , 1 , bchannel - > b_mode ) ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_tone & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_TONE_PATT_ON , bchannel - > b_tone , " DSP-TONE " , bchannel - > b_tone , bchannel - > b_mode ) ;
2008-05-01 18:07:02 +00:00
if ( bchannel - > b_rxoff )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_RECEIVE_OFF , 0 , " DSP-RXOFF " , 1 , bchannel - > b_mode ) ;
2008-07-26 11:49:23 +00:00
// if (bchannel->b_txmix && bchannel->b_mode == 0)
2008-06-17 19:13:22 +00:00
// ph_control(sock, DSP_MIX_ON, 0, "DSP-MIX", 1, bchannel->b_mode);
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_dtmf & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DTMF_TONE_START , 0 , " DSP-DTMF " , 1 , bchannel - > b_mode ) ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_bf_len & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control_block ( sock , DSP_BF_ENABLE_KEY , bchannel - > b_bf_key , bchannel - > b_bf_len , " DSP-CRYPT " , bchannel - > b_bf_len , bchannel - > b_mode ) ;
2008-05-01 18:07:02 +00:00
if ( bchannel - > b_conf )
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_CONF_JOIN , bchannel - > b_conf , " DSP-CONF " , bchannel - > b_conf , bchannel - > b_mode ) ;
2008-01-19 17:10:46 +00:00
2008-05-01 18:07:02 +00:00
bchannel - > b_state = BSTATE_ACTIVE ;
2008-01-19 17:10:46 +00:00
}
/*
* destroy stack
*/
2008-06-07 09:49:28 +00:00
void bchannel_destroy ( struct bchannel * bchannel )
2008-01-19 17:10:46 +00:00
{
2009-06-06 21:46:21 +00:00
if ( bchannel - > b_sock > - 1 ) {
2010-01-16 10:20:23 +00:00
unregister_fd ( & bchannel - > lcr_fd ) ;
2008-05-01 18:07:02 +00:00
close ( bchannel - > b_sock ) ;
bchannel - > b_sock = - 1 ;
2008-01-19 17:10:46 +00:00
}
2008-05-01 18:07:02 +00:00
bchannel - > b_state = BSTATE_IDLE ;
2008-01-19 17:10:46 +00:00
}
/*
* whenever we get audio data from bchannel , we process it here
*/
2008-06-07 09:49:28 +00:00
static void bchannel_receive ( struct bchannel * bchannel , unsigned char * buffer , int len )
2008-01-19 17:10:46 +00:00
{
2008-06-07 09:49:28 +00:00
struct mISDNhead * hh = ( struct mISDNhead * ) buffer ;
unsigned char * data = buffer + MISDN_HEADER_LEN ;
2008-06-14 06:34:50 +00:00
unsigned int cont = * ( ( unsigned int * ) data ) ;
2008-07-26 11:49:23 +00:00
unsigned char * d ;
int i ;
2008-06-07 09:49:28 +00:00
struct bchannel * remote_bchannel ;
int ret ;
2008-01-19 17:10:46 +00:00
2009-06-06 21:46:21 +00:00
if ( hh - > prim = = PH_CONTROL_IND ) {
2008-07-26 11:49:23 +00:00
/* non dsp -> ignore ph_control */
if ( bchannel - > b_mode = = 1 | | bchannel - > b_mode = = 3 )
return ;
2009-06-06 21:46:21 +00:00
if ( len < 4 ) {
2008-07-26 11:49:23 +00:00
CERROR ( bchannel - > call , NULL , " SHORT READ OF PH_CONTROL INDICATION \n " ) ;
2008-01-19 17:10:46 +00:00
return ;
}
2009-06-06 21:46:21 +00:00
if ( ( cont & ( ~ DTMF_TONE_MASK ) ) = = DTMF_TONE_VAL ) {
2008-06-06 13:18:59 +00:00
if ( bchannel - > call )
lcr_in_dtmf ( bchannel - > call , cont & DTMF_TONE_MASK ) ;
2008-01-19 17:10:46 +00:00
return ;
}
2009-06-06 21:46:21 +00:00
switch ( cont ) {
2008-05-25 14:12:20 +00:00
case DSP_BF_REJECT :
2008-07-26 11:49:23 +00:00
CERROR ( bchannel - > call , NULL , " Blowfish crypt rejected. \n " ) ;
2008-01-19 17:10:46 +00:00
break ;
2008-05-25 14:12:20 +00:00
case DSP_BF_ACCEPT :
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " Blowfish crypt enabled. \n " ) ;
2008-01-19 17:10:46 +00:00
break ;
default :
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " Unhandled bchannel control 0x%x. \n " , cont ) ;
2008-01-19 17:10:46 +00:00
}
return ;
}
2009-06-06 21:46:21 +00:00
if ( hh - > prim = = PH_DATA_REQ ) {
if ( ! bchannel - > b_txdata ) {
2008-05-25 14:12:20 +00:00
/* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " ignoring tx data, because 'txdata' is turned off \n " ) ;
2008-05-25 14:12:20 +00:00
return ;
}
return ;
}
2009-06-06 21:46:21 +00:00
if ( hh - > prim ! = PH_DATA_IND & & hh - > prim ! = DL_DATA_IND ) {
2008-07-26 11:49:23 +00:00
CERROR ( bchannel - > call , NULL , " Bchannel received unknown primitve: 0x%lx \n " , hh - > prim ) ;
2008-01-19 17:10:46 +00:00
return ;
}
2008-07-26 11:49:23 +00:00
/* if calls are bridged, but not via dsp (no b_conf), forward here */
if ( ! bchannel - > b_conf
2008-06-07 09:49:28 +00:00
& & bchannel - > call
& & bchannel - > call - > bridge_call
2008-07-26 11:49:23 +00:00
& & bchannel - > call - > bridge_call - > bchannel ) {
2008-06-07 09:49:28 +00:00
remote_bchannel = bchannel - > call - > bridge_call - > bchannel ;
2008-07-26 11:49:23 +00:00
#if 0
int i = 0 ;
char string [ 4096 ] = " " ;
while ( i < len ) {
sprintf ( string + strlen ( string ) , " %02x " , data [ i ] ) ;
i + + ;
2008-06-07 09:49:28 +00:00
}
2008-07-26 11:49:23 +00:00
CDEBUG ( remote_bchannel - > call , NULL , " Forwarding packet%s \n " , string ) ;
# endif
hh - > prim = PH_DATA_REQ ;
hh - > id = 0 ;
ret = sendto ( remote_bchannel - > b_sock , buffer , MISDN_HEADER_LEN + len , 0 , NULL , 0 ) ;
if ( ret < 0 )
CERROR ( remote_bchannel - > call , NULL , " Failed to send to socket %d \n " , bchannel - > b_sock ) ;
return ;
2008-06-07 09:49:28 +00:00
}
2008-01-19 17:10:46 +00:00
/* calls will not process any audio data unless
* the call is connected OR interface features audio during call setup .
*/
/* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
2009-06-06 21:46:21 +00:00
if ( bchannel - > b_rxoff ) {
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " ignoring data, because rx is turned off \n " ) ;
2008-01-19 17:10:46 +00:00
return ;
}
2009-06-06 21:46:21 +00:00
if ( ! bchannel - > call ) {
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " ignoring data, because no call associated with bchannel \n " ) ;
2008-05-18 07:23:10 +00:00
return ;
}
2009-06-06 21:46:21 +00:00
if ( ! bchannel - > call - > audiopath ) {
2008-05-19 17:39:39 +00:00
/* return, because we have no audio from port */
return ;
}
2008-07-20 17:33:28 +00:00
2009-06-06 21:46:21 +00:00
if ( bchannel - > call - > pipe [ 1 ] < 0 ) {
2008-07-20 17:33:28 +00:00
/* nobody there */
return ;
}
2008-07-26 11:49:23 +00:00
/* if no hdlc */
2009-06-06 21:46:21 +00:00
if ( bchannel - > b_mode = = 0 | | bchannel - > b_mode = = 1 ) {
2008-07-26 11:49:23 +00:00
d = data ;
for ( i = 0 ; i < len ; i + + ) {
* d = flip_bits [ * d ] ;
d + + ;
}
}
2008-07-20 17:33:28 +00:00
2009-03-09 08:25:26 +00:00
len = write ( bchannel - > call - > pipe [ 1 ] , data , len ) ;
if ( len < 0 )
goto errout ;
2008-07-20 17:33:28 +00:00
return ;
errout :
close ( bchannel - > call - > pipe [ 1 ] ) ;
bchannel - > call - > pipe [ 1 ] = - 1 ;
2008-07-26 11:49:23 +00:00
CDEBUG ( bchannel - > call , NULL , " broken pipe on bchannel pipe \n " ) ;
2008-01-19 17:10:46 +00:00
}
/*
* transmit data to bchannel
*/
2008-05-01 18:07:02 +00:00
void bchannel_transmit ( struct bchannel * bchannel , unsigned char * data , int len )
2008-01-19 17:10:46 +00:00
{
2008-06-01 16:52:10 +00:00
unsigned char buff [ 1024 + MISDN_HEADER_LEN ] , * p = buff + MISDN_HEADER_LEN ;
2008-05-25 14:12:20 +00:00
struct mISDNhead * frm = ( struct mISDNhead * ) buff ;
int ret ;
2008-06-01 16:52:10 +00:00
int i ;
2010-01-24 13:22:34 +00:00
int space , in ;
2008-01-19 17:10:46 +00:00
2008-05-01 18:07:02 +00:00
if ( bchannel - > b_state ! = BSTATE_ACTIVE )
2008-01-19 17:10:46 +00:00
return ;
2008-06-01 16:52:10 +00:00
if ( len > 1024 | | len < 1 )
return ;
2010-03-18 08:13:38 +00:00
if ( data ) {
switch ( bchannel - > b_mode ) {
case 0 :
for ( i = 0 ; i < len ; i + + )
* p + + = flip_bits [ * data + + ] ;
frm - > prim = DL_DATA_REQ ;
break ;
case 1 :
for ( i = 0 ; i < len ; i + + )
* p + + = flip_bits [ * data + + ] ;
frm - > prim = PH_DATA_REQ ;
break ;
case 2 :
memcpy ( p , data , len ) ;
frm - > prim = DL_DATA_REQ ;
break ;
case 3 :
memcpy ( p , data , len ) ;
frm - > prim = PH_DATA_REQ ;
break ;
}
} else
memset ( p , flip_bits [ ( options . law = = ' a ' ) ? 0x2a : 0xff ] , len ) ;
2008-01-19 17:10:46 +00:00
frm - > id = 0 ;
2010-01-24 13:22:34 +00:00
# ifdef SEAMLESS_TEST
unsigned char test_tone [ 8 ] = { 0x2a , 0x24 , 0xb4 , 0x24 , 0x2a , 0x25 , 0xb5 , 0x25 } ;
p = buff + MISDN_HEADER_LEN ;
for ( i = 0 ; i < len ; i + + )
* p + + = test_tone [ ( bchannel - > test + i ) & 7 ] ;
bchannel - > test = ( bchannel - > test + len ) & 7 ;
# endif
if ( bchannel - > nodsp_queue ) {
2010-01-24 18:41:32 +00:00
space = ( bchannel - > nodsp_queue_out - bchannel - > nodsp_queue_in - 1 ) & ( QUEUE_BUFFER_SIZE - 1 ) ;
2010-01-24 13:22:34 +00:00
if ( len > space ) {
2010-01-24 18:41:32 +00:00
CERROR ( bchannel - > call , NULL , " Queue buffer overflow, space is %d, len is %d. \n " , space , len ) ;
2010-01-24 13:22:34 +00:00
return ;
}
p = buff + MISDN_HEADER_LEN ;
in = bchannel - > nodsp_queue_in ;
for ( i = 0 ; i < len ; i + + ) {
bchannel - > nodsp_queue_buffer [ in ] = * p + + ;
in = ( in + 1 ) & ( QUEUE_BUFFER_SIZE - 1 ) ;
}
bchannel - > nodsp_queue_in = in ;
if ( bchannel - > queue_sent = = 0 ) /* if there is no pending data */
bchannel_send_queue ( bchannel ) ;
return ;
}
ret = sendto ( bchannel - > b_sock , buff , MISDN_HEADER_LEN + len , 0 , NULL , 0 ) ;
if ( ret < 0 )
CERROR ( bchannel - > call , NULL , " Failed to send to socket %d \n " , bchannel - > b_sock ) ;
}
/*
* in case of a send queue , we send from that queue rather directly
*/
static void bchannel_send_queue ( struct bchannel * bchannel )
{
unsigned char buff [ 1024 + MISDN_HEADER_LEN ] , * p = buff + MISDN_HEADER_LEN ;
struct mISDNhead * frm = ( struct mISDNhead * ) buff ;
int ret ;
int i ;
int len , out ;
len = ( bchannel - > nodsp_queue_in - bchannel - > nodsp_queue_out ) & ( QUEUE_BUFFER_SIZE - 1 ) ;
if ( len = = 0 )
return ; /* mISDN driver received all load */
2010-01-24 18:41:32 +00:00
#if 0
printf ( " %4d:(%s|%s) \n " , bchannel - > nodsp_queue_out ,
" ---------------------------------------------------------------- " + 64 - len / ( 8192 / 64 ) ,
" " + len / ( 8192 / 64 ) ) ;
# endif
2010-01-24 13:22:34 +00:00
if ( len > 1024 )
len = 1024 ;
frm - > prim = PH_DATA_REQ ;
frm - > id = 0 ;
out = bchannel - > nodsp_queue_out ;
for ( i = 0 ; i < len ; i + + ) {
* p + + = bchannel - > nodsp_queue_buffer [ out ] ;
out = ( out + 1 ) & ( QUEUE_BUFFER_SIZE - 1 ) ;
}
bchannel - > nodsp_queue_out = out ;
2008-06-01 16:52:10 +00:00
ret = sendto ( bchannel - > b_sock , buff , MISDN_HEADER_LEN + len , 0 , NULL , 0 ) ;
if ( ret < 0 )
2008-07-26 11:49:23 +00:00
CERROR ( bchannel - > call , NULL , " Failed to send to socket %d \n " , bchannel - > b_sock ) ;
2010-01-24 13:22:34 +00:00
else
bchannel - > queue_sent = 1 ;
2008-01-19 17:10:46 +00:00
}
/*
* join bchannel
*/
2008-05-01 18:07:02 +00:00
void bchannel_join ( struct bchannel * bchannel , unsigned short id )
2008-01-19 17:10:46 +00:00
{
2008-06-17 19:13:22 +00:00
int sock ;
2008-01-19 17:10:46 +00:00
2008-06-17 19:13:22 +00:00
sock = bchannel - > b_sock ;
2008-05-18 07:23:10 +00:00
if ( id ) {
2008-05-01 18:07:02 +00:00
bchannel - > b_conf = ( id < < 16 ) + bchannel_pid ;
2008-05-18 07:23:10 +00:00
bchannel - > b_rxoff = 1 ;
} else {
2008-05-01 18:07:02 +00:00
bchannel - > b_conf = 0 ;
2008-05-18 07:23:10 +00:00
bchannel - > b_rxoff = 0 ;
}
2009-06-06 21:46:21 +00:00
if ( bchannel - > b_state = = BSTATE_ACTIVE ) {
2008-06-17 19:13:22 +00:00
ph_control ( sock , DSP_RECEIVE_OFF , bchannel - > b_rxoff , " DSP-RX_OFF " , bchannel - > b_conf , bchannel - > b_mode ) ;
ph_control ( sock , DSP_CONF_JOIN , bchannel - > b_conf , " DSP-CONF " , bchannel - > b_conf , bchannel - > b_mode ) ;
2008-05-18 07:23:10 +00:00
}
2008-01-19 17:10:46 +00:00
}
2008-06-06 13:18:59 +00:00
/*
* dtmf bchannel
*/
void bchannel_dtmf ( struct bchannel * bchannel , int on )
{
2008-06-17 19:13:22 +00:00
int sock ;
2008-06-06 13:18:59 +00:00
2008-06-17 19:13:22 +00:00
sock = bchannel - > b_sock ;
2009-05-21 17:11:39 +00:00
bchannel - > b_dtmf = on ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_state = = BSTATE_ACTIVE & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control ( sock , on ? DTMF_TONE_START : DTMF_TONE_STOP , 0 , " DSP-DTMF " , 1 , bchannel - > b_mode ) ;
2008-06-07 09:49:28 +00:00
}
/*
* blowfish bchannel
*/
void bchannel_blowfish ( struct bchannel * bchannel , unsigned char * key , int len )
{
2008-06-17 19:13:22 +00:00
int sock ;
2008-06-07 09:49:28 +00:00
2008-06-17 19:13:22 +00:00
sock = bchannel - > b_sock ;
2008-06-07 09:49:28 +00:00
memcpy ( bchannel - > b_bf_key , key , len ) ;
bchannel - > b_bf_len = len ;
if ( bchannel - > b_state = = BSTATE_ACTIVE )
2008-06-17 19:13:22 +00:00
ph_control_block ( sock , DSP_BF_ENABLE_KEY , bchannel - > b_bf_key , bchannel - > b_bf_len , " DSP-CRYPT " , bchannel - > b_bf_len , bchannel - > b_mode ) ;
2008-06-07 09:49:28 +00:00
}
/*
* pipeline bchannel
*/
void bchannel_pipeline ( struct bchannel * bchannel , char * pipeline )
{
2008-06-17 19:13:22 +00:00
int sock ;
2008-06-07 09:49:28 +00:00
2008-06-17 19:13:22 +00:00
sock = bchannel - > b_sock ;
2008-06-07 09:49:28 +00:00
strncpy ( bchannel - > b_pipeline , pipeline , sizeof ( bchannel - > b_pipeline ) - 1 ) ;
if ( bchannel - > b_state = = BSTATE_ACTIVE )
2008-06-17 19:13:22 +00:00
ph_control_block ( sock , DSP_PIPELINE_CFG , bchannel - > b_pipeline , strlen ( bchannel - > b_pipeline ) + 1 , " DSP-PIPELINE " , 0 , bchannel - > b_mode ) ;
2008-06-07 09:49:28 +00:00
}
/*
* gain bchannel
*/
void bchannel_gain ( struct bchannel * bchannel , int gain , int tx )
{
2008-06-17 19:13:22 +00:00
int sock ;
2008-06-07 09:49:28 +00:00
2008-06-17 19:13:22 +00:00
sock = bchannel - > b_sock ;
2008-06-07 09:49:28 +00:00
if ( tx )
bchannel - > b_tx_gain = gain ;
else
bchannel - > b_rx_gain = gain ;
2008-07-26 11:49:23 +00:00
if ( bchannel - > b_state = = BSTATE_ACTIVE & & bchannel - > b_mode = = 0 )
2008-06-17 19:13:22 +00:00
ph_control ( sock , ( tx ) ? DSP_VOL_CHANGE_TX : DSP_VOL_CHANGE_RX , gain , ( tx ) ? " DSP-TX_GAIN " : " DSP-RX_GAIN " , gain , bchannel - > b_mode ) ;
2008-06-06 13:18:59 +00:00
}
2008-01-19 17:10:46 +00:00
/*
* main loop for processing messages from mISDN
*/
2010-01-16 10:20:23 +00:00
static int bchannel_handle ( struct lcr_fd * fd , unsigned int what , void * instance , int index )
2008-01-19 17:10:46 +00:00
{
2010-01-16 10:20:23 +00:00
struct bchannel * bchannel = ( struct bchannel * ) instance ;
int ret ;
2008-07-29 17:00:12 +00:00
unsigned char buffer [ 2048 + MISDN_HEADER_LEN ] ;
2008-01-19 17:10:46 +00:00
struct mISDNhead * hh = ( struct mISDNhead * ) buffer ;
2010-01-16 10:20:23 +00:00
ret = recv ( bchannel - > b_sock , buffer , sizeof ( buffer ) , 0 ) ;
if ( ret > = ( int ) MISDN_HEADER_LEN ) {
switch ( hh - > prim ) {
2010-01-24 13:22:34 +00:00
/* after a confim, we can send more from queue */
2010-01-16 10:20:23 +00:00
case PH_DATA_CNF :
2010-01-24 13:22:34 +00:00
if ( bchannel - > nodsp_queue ) {
bchannel - > queue_sent = 0 ;
bchannel_send_queue ( bchannel ) ;
}
2010-01-16 10:20:23 +00:00
break ;
/* we receive audio data, we respond to it AND we send tones */
case PH_DATA_IND :
case PH_DATA_REQ :
case DL_DATA_IND :
case PH_CONTROL_IND :
bchannel_receive ( bchannel , buffer , ret - MISDN_HEADER_LEN ) ;
break ;
case PH_ACTIVATE_IND :
case DL_ESTABLISH_IND :
case PH_ACTIVATE_CNF :
case DL_ESTABLISH_CNF :
CDEBUG ( bchannel - > call , NULL , " DL_ESTABLISH confirm: bchannel is now activated (socket %d). \n " , bchannel - > b_sock ) ;
bchannel_activated ( bchannel ) ;
break ;
case PH_DEACTIVATE_IND :
case DL_RELEASE_IND :
case PH_DEACTIVATE_CNF :
case DL_RELEASE_CNF :
CDEBUG ( bchannel - > call , NULL , " DL_RELEASE confirm: bchannel is now de-activated (socket %d). \n " , bchannel - > b_sock ) ;
2008-05-01 18:07:02 +00:00
// bchannel_deactivated(bchannel);
2010-01-16 10:20:23 +00:00
break ;
default :
CERROR ( bchannel - > call , NULL , " child message not handled: prim(0x%x) socket(%d) data len(%d) \n " , hh - > prim , bchannel - > b_sock , ret - MISDN_HEADER_LEN ) ;
2008-01-19 17:10:46 +00:00
}
2010-01-16 10:20:23 +00:00
} else {
// if (ret < 0 && errno != EWOULDBLOCK)
CERROR ( bchannel - > call , NULL , " Read from socket %d failed with return code %d \n " , bchannel - > b_sock , ret ) ;
2008-01-19 17:10:46 +00:00
}
/* if we received at least one b-frame, we will return 1 */
2010-01-16 10:20:23 +00:00
return 0 ;
2008-01-19 17:10:46 +00:00
}
/*
* bchannel channel handling
*/
struct bchannel * bchannel_first = NULL ;
2008-06-14 06:34:50 +00:00
struct bchannel * find_bchannel_handle ( unsigned int handle )
2008-01-19 17:10:46 +00:00
{
2008-05-01 18:07:02 +00:00
struct bchannel * bchannel = bchannel_first ;
2008-01-19 17:10:46 +00:00
2009-06-06 21:46:21 +00:00
while ( bchannel ) {
2008-05-01 18:07:02 +00:00
if ( bchannel - > handle = = handle )
2008-01-19 17:10:46 +00:00
break ;
2008-05-01 18:07:02 +00:00
bchannel = bchannel - > next ;
2008-01-19 17:10:46 +00:00
}
2010-01-16 10:20:23 +00:00
return bchannel ;
2008-01-19 17:10:46 +00:00
}
2008-05-01 18:07:02 +00:00
#if 0
2008-06-14 06:34:50 +00:00
struct bchannel * find_bchannel_ref ( unsigned int ref )
2008-01-19 17:10:46 +00:00
{
2008-05-01 18:07:02 +00:00
struct bchannel * bchannel = bchannel_first ;
2008-01-19 17:10:46 +00:00
2009-06-06 21:46:21 +00:00
while ( bchannel ) {
2008-05-01 18:07:02 +00:00
if ( bchannel - > ref = = ref )
2008-01-19 17:10:46 +00:00
break ;
2008-05-01 18:07:02 +00:00
bchannel = bchannel - > next ;
2008-01-19 17:10:46 +00:00
}
2010-01-16 10:20:23 +00:00
return bchannel ;
2008-01-19 17:10:46 +00:00
}
2008-05-01 18:07:02 +00:00
# endif
2008-01-19 17:10:46 +00:00
2008-06-14 06:34:50 +00:00
struct bchannel * alloc_bchannel ( unsigned int handle )
2008-01-19 17:10:46 +00:00
{
2008-05-01 18:07:02 +00:00
struct bchannel * * bchannelp = & bchannel_first ;
2008-01-19 17:10:46 +00:00
2008-05-01 18:07:02 +00:00
while ( * bchannelp )
bchannelp = & ( ( * bchannelp ) - > next ) ;
2008-01-19 17:10:46 +00:00
2008-06-01 16:52:10 +00:00
* bchannelp = ( struct bchannel * ) calloc ( 1 , sizeof ( struct bchannel ) ) ;
2008-05-01 18:07:02 +00:00
if ( ! * bchannelp )
2010-01-16 10:20:23 +00:00
return NULL ;
2008-05-01 18:07:02 +00:00
( * bchannelp ) - > handle = handle ;
( * bchannelp ) - > b_state = BSTATE_IDLE ;
2008-06-17 10:41:10 +00:00
( * bchannelp ) - > b_sock = - 1 ;
2008-01-19 17:10:46 +00:00
2010-01-16 10:20:23 +00:00
return * bchannelp ;
2008-01-19 17:10:46 +00:00
}
2008-05-01 18:07:02 +00:00
void free_bchannel ( struct bchannel * bchannel )
2008-01-19 17:10:46 +00:00
{
struct bchannel * * temp = & bchannel_first ;
2009-06-06 21:46:21 +00:00
while ( * temp ) {
if ( * temp = = bchannel ) {
2008-01-19 17:10:46 +00:00
* temp = ( * temp ) - > next ;
2008-05-01 18:07:02 +00:00
if ( bchannel - > b_sock > - 1 )
bchannel_destroy ( bchannel ) ;
2009-06-06 21:46:21 +00:00
if ( bchannel - > call ) {
2008-05-01 18:07:02 +00:00
if ( bchannel - > call - > bchannel )
bchannel - > call - > bchannel = NULL ;
2008-05-01 08:35:20 +00:00
}
2008-05-01 18:07:02 +00:00
free ( bchannel ) ;
2008-01-19 17:10:46 +00:00
return ;
}
temp = & ( ( * temp ) - > next ) ;
}
}