2007-05-16 20:36:40 +00:00
/*
* Copyright ( c ) 2007 , Anthony Minessale II
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
*
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* * Neither the name of the original author ; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL ,
* EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO ,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR
* PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2010-04-19 11:39:03 -04:00
# include "private/ftdm_core.h"
2010-01-15 19:22:49 +00:00
# include "ftmod_zt.h"
2007-05-16 20:36:40 +00:00
2010-12-07 20:06:48 +01:00
/* used by dahdi to indicate there is no data available, but events to read */
# ifndef ELAST
# define ELAST 500
# endif
2009-06-08 20:01:29 +00:00
/**
* \ brief Zaptel globals
*/
2007-05-30 01:01:32 +00:00
static struct {
uint32_t codec_ms ;
uint32_t wink_ms ;
uint32_t flash_ms ;
2007-06-01 15:58:27 +00:00
uint32_t eclevel ;
2007-06-21 02:13:41 +00:00
uint32_t etlevel ;
2009-06-04 16:18:22 +00:00
float rxgain ;
float txgain ;
2007-05-30 01:01:32 +00:00
} zt_globals ;
2010-12-17 09:52:26 -05:00
# if defined(__FreeBSD__)
typedef unsigned long ioctlcmd ;
# else
typedef int ioctlcmd ;
# endif
2009-06-08 20:01:29 +00:00
/**
* \ brief General IOCTL codes
*/
2009-03-04 21:31:08 +00:00
struct ioctl_codes {
2010-12-17 09:52:26 -05:00
ioctlcmd GET_BLOCKSIZE ;
ioctlcmd SET_BLOCKSIZE ;
ioctlcmd FLUSH ;
ioctlcmd SYNC ;
ioctlcmd GET_PARAMS ;
ioctlcmd SET_PARAMS ;
ioctlcmd HOOK ;
ioctlcmd GETEVENT ;
ioctlcmd IOMUX ;
ioctlcmd SPANSTAT ;
ioctlcmd MAINT ;
ioctlcmd GETCONF ;
ioctlcmd SETCONF ;
ioctlcmd CONFLINK ;
ioctlcmd CONFDIAG ;
ioctlcmd GETGAINS ;
ioctlcmd SETGAINS ;
ioctlcmd SPANCONFIG ;
ioctlcmd CHANCONFIG ;
ioctlcmd SET_BUFINFO ;
ioctlcmd GET_BUFINFO ;
ioctlcmd AUDIOMODE ;
ioctlcmd ECHOCANCEL ;
ioctlcmd HDLCRAWMODE ;
ioctlcmd HDLCFCSMODE ;
ioctlcmd SPECIFY ;
ioctlcmd SETLAW ;
ioctlcmd SETLINEAR ;
ioctlcmd GETCONFMUTE ;
ioctlcmd ECHOTRAIN ;
ioctlcmd SETTXBITS ;
ioctlcmd GETRXBITS ;
2009-03-04 21:31:08 +00:00
} ;
2009-06-08 20:01:29 +00:00
/**
* \ brief Zaptel IOCTL codes
*/
2009-03-04 21:31:08 +00:00
static struct ioctl_codes zt_ioctl_codes = {
. GET_BLOCKSIZE = ZT_GET_BLOCKSIZE ,
. SET_BLOCKSIZE = ZT_SET_BLOCKSIZE ,
. FLUSH = ZT_FLUSH ,
. SYNC = ZT_SYNC ,
. GET_PARAMS = ZT_GET_PARAMS ,
. SET_PARAMS = ZT_SET_PARAMS ,
. HOOK = ZT_HOOK ,
. GETEVENT = ZT_GETEVENT ,
. IOMUX = ZT_IOMUX ,
. SPANSTAT = ZT_SPANSTAT ,
. MAINT = ZT_MAINT ,
. GETCONF = ZT_GETCONF ,
. SETCONF = ZT_SETCONF ,
. CONFLINK = ZT_CONFLINK ,
. CONFDIAG = ZT_CONFDIAG ,
. GETGAINS = ZT_GETGAINS ,
. SETGAINS = ZT_SETGAINS ,
. SPANCONFIG = ZT_SPANCONFIG ,
. CHANCONFIG = ZT_CHANCONFIG ,
. SET_BUFINFO = ZT_SET_BUFINFO ,
. GET_BUFINFO = ZT_GET_BUFINFO ,
. AUDIOMODE = ZT_AUDIOMODE ,
. ECHOCANCEL = ZT_ECHOCANCEL ,
. HDLCRAWMODE = ZT_HDLCRAWMODE ,
. HDLCFCSMODE = ZT_HDLCFCSMODE ,
. SPECIFY = ZT_SPECIFY ,
. SETLAW = ZT_SETLAW ,
. SETLINEAR = ZT_SETLINEAR ,
. GETCONFMUTE = ZT_GETCONFMUTE ,
. ECHOTRAIN = ZT_ECHOTRAIN ,
. SETTXBITS = ZT_SETTXBITS ,
. GETRXBITS = ZT_GETRXBITS
} ;
2009-06-08 20:01:29 +00:00
/**
* \ brief Dahdi IOCTL codes
*/
2009-03-04 21:31:08 +00:00
static struct ioctl_codes dahdi_ioctl_codes = {
. GET_BLOCKSIZE = DAHDI_GET_BLOCKSIZE ,
. SET_BLOCKSIZE = DAHDI_SET_BLOCKSIZE ,
. FLUSH = DAHDI_FLUSH ,
. SYNC = DAHDI_SYNC ,
. GET_PARAMS = DAHDI_GET_PARAMS ,
. SET_PARAMS = DAHDI_SET_PARAMS ,
. HOOK = DAHDI_HOOK ,
. GETEVENT = DAHDI_GETEVENT ,
. IOMUX = DAHDI_IOMUX ,
. SPANSTAT = DAHDI_SPANSTAT ,
. MAINT = DAHDI_MAINT ,
. GETCONF = DAHDI_GETCONF ,
. SETCONF = DAHDI_SETCONF ,
. CONFLINK = DAHDI_CONFLINK ,
. CONFDIAG = DAHDI_CONFDIAG ,
. GETGAINS = DAHDI_GETGAINS ,
. SETGAINS = DAHDI_SETGAINS ,
. SPANCONFIG = DAHDI_SPANCONFIG ,
. CHANCONFIG = DAHDI_CHANCONFIG ,
. SET_BUFINFO = DAHDI_SET_BUFINFO ,
. GET_BUFINFO = DAHDI_GET_BUFINFO ,
. AUDIOMODE = DAHDI_AUDIOMODE ,
. ECHOCANCEL = DAHDI_ECHOCANCEL ,
. HDLCRAWMODE = DAHDI_HDLCRAWMODE ,
. HDLCFCSMODE = DAHDI_HDLCFCSMODE ,
. SPECIFY = DAHDI_SPECIFY ,
. SETLAW = DAHDI_SETLAW ,
. SETLINEAR = DAHDI_SETLINEAR ,
. GETCONFMUTE = DAHDI_GETCONFMUTE ,
. ECHOTRAIN = DAHDI_ECHOTRAIN ,
. SETTXBITS = DAHDI_SETTXBITS ,
. GETRXBITS = DAHDI_GETRXBITS
} ;
2007-05-30 01:01:32 +00:00
# define ZT_INVALID_SOCKET -1
2009-03-04 21:31:08 +00:00
static struct ioctl_codes codes ;
static const char * ctlpath = NULL ;
static const char * chanpath = NULL ;
static const char dahdi_ctlpath [ ] = " /dev/dahdi/ctl " ;
static const char dahdi_chanpath [ ] = " /dev/dahdi/channel " ;
2010-09-27 21:38:42 -04:00
static const char zt_ctlpath [ ] = " /dev/zap/ctl " ;
static const char zt_chanpath [ ] = " /dev/zap/channel " ;
2009-03-04 21:31:08 +00:00
2010-01-15 19:22:49 +00:00
static ftdm_socket_t CONTROL_FD = ZT_INVALID_SOCKET ;
2007-05-30 01:01:32 +00:00
2010-01-15 20:35:11 +00:00
FIO_SPAN_NEXT_EVENT_FUNCTION ( zt_next_event ) ;
FIO_SPAN_POLL_EVENT_FUNCTION ( zt_poll_event ) ;
2010-12-09 12:48:33 -02:00
FIO_CHANNEL_NEXT_EVENT_FUNCTION ( zt_channel_next_event ) ;
2008-02-18 17:17:38 +00:00
2009-06-08 20:01:29 +00:00
/**
* \ brief Initialises codec , and rx / tx gains
* \ param g Structure for gains to be initialised
* \ param rxgain RX gain value
* \ param txgain TX gain value
* \ param codec Codec
*/
2009-06-04 16:18:22 +00:00
static void zt_build_gains ( struct zt_gains * g , float rxgain , float txgain , int codec )
{
int j ;
int k ;
float linear_rxgain = pow ( 10.0 , rxgain / 20.0 ) ;
float linear_txgain = pow ( 10.0 , txgain / 20.0 ) ;
switch ( codec ) {
2010-01-15 19:22:49 +00:00
case FTDM_CODEC_ALAW :
2009-06-04 16:18:22 +00:00
for ( j = 0 ; j < ( sizeof ( g - > receive_gain ) / sizeof ( g - > receive_gain [ 0 ] ) ) ; j + + ) {
if ( rxgain ) {
k = ( int ) ( ( ( float ) alaw_to_linear ( j ) ) * linear_rxgain ) ;
if ( k > 32767 ) k = 32767 ;
if ( k < - 32767 ) k = - 32767 ;
g - > receive_gain [ j ] = linear_to_alaw ( k ) ;
} else {
g - > receive_gain [ j ] = j ;
}
if ( txgain ) {
k = ( int ) ( ( ( float ) alaw_to_linear ( j ) ) * linear_txgain ) ;
if ( k > 32767 ) k = 32767 ;
if ( k < - 32767 ) k = - 32767 ;
g - > transmit_gain [ j ] = linear_to_alaw ( k ) ;
} else {
g - > transmit_gain [ j ] = j ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CODEC_ULAW :
2009-06-04 16:18:22 +00:00
for ( j = 0 ; j < ( sizeof ( g - > receive_gain ) / sizeof ( g - > receive_gain [ 0 ] ) ) ; j + + ) {
if ( rxgain ) {
k = ( int ) ( ( ( float ) ulaw_to_linear ( j ) ) * linear_rxgain ) ;
if ( k > 32767 ) k = 32767 ;
if ( k < - 32767 ) k = - 32767 ;
g - > receive_gain [ j ] = linear_to_ulaw ( k ) ;
} else {
g - > receive_gain [ j ] = j ;
}
if ( txgain ) {
k = ( int ) ( ( ( float ) ulaw_to_linear ( j ) ) * linear_txgain ) ;
if ( k > 32767 ) k = 32767 ;
if ( k < - 32767 ) k = - 32767 ;
g - > transmit_gain [ j ] = linear_to_ulaw ( k ) ;
} else {
g - > transmit_gain [ j ] = j ;
}
}
break ;
}
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Initialises a range of ftdmtel channels
2010-01-15 20:08:43 +00:00
* \ param span FreeTDM span
2009-06-08 20:01:29 +00:00
* \ param start Initial wanpipe channel number
* \ param end Final wanpipe channel number
2010-01-15 20:08:43 +00:00
* \ param type FreeTDM channel type
* \ param name FreeTDM span name
* \ param number FreeTDM span number
2009-06-08 20:01:29 +00:00
* \ param cas_bits CAS bits
* \ return number of spans configured
*/
2010-01-15 19:22:49 +00:00
static unsigned zt_open_range ( ftdm_span_t * span , unsigned start , unsigned end , ftdm_chan_type_t type , char * name , char * number , unsigned char cas_bits )
2007-05-30 01:01:32 +00:00
{
unsigned configured = 0 , x ;
2007-06-05 04:37:50 +00:00
zt_params_t ztp ;
memset ( & ztp , 0 , sizeof ( ztp ) ) ;
2007-05-30 01:01:32 +00:00
2010-01-15 19:22:49 +00:00
if ( type = = FTDM_CHAN_TYPE_CAS ) {
ftdm_log ( FTDM_LOG_DEBUG , " Configuring CAS channels with abcd == 0x%X \n " , cas_bits ) ;
2008-10-10 16:02:09 +00:00
}
2007-05-30 01:01:32 +00:00
for ( x = start ; x < end ; x + + ) {
2010-01-15 19:22:49 +00:00
ftdm_channel_t * ftdmchan ;
ftdm_socket_t sockfd = ZT_INVALID_SOCKET ;
2007-05-31 02:41:50 +00:00
int len ;
2007-05-30 01:01:32 +00:00
2009-03-04 21:31:08 +00:00
sockfd = open ( chanpath , O_RDWR ) ;
2010-01-15 19:22:49 +00:00
if ( sockfd ! = ZT_INVALID_SOCKET & & ftdm_span_add_channel ( span , sockfd , type , & ftdmchan ) = = FTDM_SUCCESS ) {
2007-06-20 20:30:10 +00:00
2009-03-04 21:31:08 +00:00
if ( ioctl ( sockfd , codes . SPECIFY , & x ) ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failure configuring device %s chan %d fd %d (%s) \n " , chanpath , x , sockfd , strerror ( errno ) ) ;
2007-06-20 20:30:10 +00:00
close ( sockfd ) ;
continue ;
}
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > type = = FTDM_CHAN_TYPE_DQ921 ) {
2007-06-20 20:30:10 +00:00
struct zt_bufferinfo binfo ;
memset ( & binfo , 0 , sizeof ( binfo ) ) ;
binfo . txbufpolicy = 0 ;
binfo . rxbufpolicy = 0 ;
binfo . numbufs = 32 ;
binfo . bufsize = 1024 ;
2009-03-04 21:31:08 +00:00
if ( ioctl ( sockfd , codes . SET_BUFINFO , & binfo ) ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failure configuring device %s as FreeTDM device %d:%d fd:%d \n " , chanpath , ftdmchan - > span_id , ftdmchan - > chan_id , sockfd ) ;
2007-06-20 20:30:10 +00:00
close ( sockfd ) ;
continue ;
}
}
2007-06-20 17:53:09 +00:00
2010-01-15 19:22:49 +00:00
if ( type = = FTDM_CHAN_TYPE_FXS | | type = = FTDM_CHAN_TYPE_FXO ) {
2007-06-18 21:32:56 +00:00
struct zt_chanconfig cc ;
memset ( & cc , 0 , sizeof ( cc ) ) ;
cc . chan = cc . master = x ;
2008-02-18 16:15:24 +00:00
2007-06-18 21:32:56 +00:00
switch ( type ) {
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXS :
2007-06-18 21:32:56 +00:00
{
switch ( span - > start_type ) {
2010-01-15 19:22:49 +00:00
case FTDM_ANALOG_START_KEWL :
2007-06-18 21:32:56 +00:00
cc . sigtype = ZT_SIG_FXOKS ;
break ;
2010-01-15 19:22:49 +00:00
case FTDM_ANALOG_START_LOOP :
2007-06-18 21:32:56 +00:00
cc . sigtype = ZT_SIG_FXOLS ;
break ;
2010-01-15 19:22:49 +00:00
case FTDM_ANALOG_START_GROUND :
2007-06-18 21:32:56 +00:00
cc . sigtype = ZT_SIG_FXOGS ;
break ;
default :
break ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXO :
2007-06-18 21:32:56 +00:00
{
switch ( span - > start_type ) {
2010-01-15 19:22:49 +00:00
case FTDM_ANALOG_START_KEWL :
2007-06-18 21:32:56 +00:00
cc . sigtype = ZT_SIG_FXSKS ;
break ;
2010-01-15 19:22:49 +00:00
case FTDM_ANALOG_START_LOOP :
2007-06-18 21:32:56 +00:00
cc . sigtype = ZT_SIG_FXSLS ;
break ;
2010-01-15 19:22:49 +00:00
case FTDM_ANALOG_START_GROUND :
2007-06-18 21:32:56 +00:00
cc . sigtype = ZT_SIG_FXSGS ;
break ;
default :
break ;
}
}
break ;
default :
break ;
}
2008-02-18 16:15:24 +00:00
2009-03-04 21:31:08 +00:00
if ( ioctl ( CONTROL_FD , codes . CHANCONFIG , & cc ) ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_WARNING , " this ioctl fails on older ftdmtel but is harmless if you used ztcfg \n [device %s chan %d fd %d (%s)] \n " , chanpath , x , CONTROL_FD , strerror ( errno ) ) ;
2007-06-18 21:32:56 +00:00
}
2007-05-30 01:01:32 +00:00
}
2007-05-31 02:41:50 +00:00
2010-01-15 19:22:49 +00:00
if ( type = = FTDM_CHAN_TYPE_CAS ) {
2008-10-10 16:02:09 +00:00
struct zt_chanconfig cc ;
memset ( & cc , 0 , sizeof ( cc ) ) ;
cc . chan = cc . master = x ;
cc . sigtype = ZT_SIG_CAS ;
cc . idlebits = cas_bits ;
2009-03-04 21:31:08 +00:00
if ( ioctl ( CONTROL_FD , codes . CHANCONFIG , & cc ) ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failure configuring device %s as FreeTDM device %d:%d fd:%d err:%s " , chanpath , ftdmchan - > span_id , ftdmchan - > chan_id , sockfd , strerror ( errno ) ) ;
2008-10-10 16:02:09 +00:00
close ( sockfd ) ;
continue ;
}
}
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > type ! = FTDM_CHAN_TYPE_DQ921 & & ftdmchan - > type ! = FTDM_CHAN_TYPE_DQ931 ) {
2007-06-20 17:53:09 +00:00
len = zt_globals . codec_ms * 8 ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . SET_BLOCKSIZE , & len ) ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failure configuring device %s as FreeTDM device %d:%d fd:%d err:%s \n " ,
2010-01-15 19:22:49 +00:00
chanpath , ftdmchan - > span_id , ftdmchan - > chan_id , sockfd , strerror ( errno ) ) ;
2007-06-20 17:53:09 +00:00
close ( sockfd ) ;
continue ;
}
2010-01-15 19:22:49 +00:00
ftdmchan - > packet_len = len ;
ftdmchan - > effective_interval = ftdmchan - > native_interval = ftdmchan - > packet_len / 8 ;
2007-05-30 01:01:32 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > effective_codec = = FTDM_CODEC_SLIN ) {
ftdmchan - > packet_len * = 2 ;
2007-06-20 17:53:09 +00:00
}
2007-05-31 02:41:50 +00:00
}
2007-05-30 01:01:32 +00:00
2009-03-04 21:31:08 +00:00
if ( ioctl ( sockfd , codes . GET_PARAMS , & ztp ) < 0 ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failure configuring device %s as FreeTDM device %d:%d fd:%d \n " , chanpath , ftdmchan - > span_id , ftdmchan - > chan_id , sockfd ) ;
2007-05-31 02:41:50 +00:00
close ( sockfd ) ;
2007-05-30 01:01:32 +00:00
continue ;
}
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > type = = FTDM_CHAN_TYPE_DQ921 ) {
2009-12-14 17:47:41 +00:00
if (
( ztp . sig_type ! = ZT_SIG_HDLCRAW ) & &
( ztp . sig_type ! = ZT_SIG_HDLCFCS ) & &
( ztp . sig_type ! = ZT_SIG_HARDHDLC )
) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Failure configuring device %s as FreeTDM device %d:%d fd:%d, hardware signaling is not HDLC, fix your Zap/DAHDI configuration! \n " , chanpath , ftdmchan - > span_id , ftdmchan - > chan_id , sockfd ) ;
2007-06-20 20:30:10 +00:00
close ( sockfd ) ;
continue ;
}
}
2007-06-18 21:32:56 +00:00
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_INFO , " configuring device %s channel %d as FreeTDM device %d:%d fd:%d \n " , chanpath , x , ftdmchan - > span_id , ftdmchan - > chan_id , sockfd ) ;
2007-06-20 20:30:10 +00:00
2010-01-15 19:22:49 +00:00
ftdmchan - > rate = 8000 ;
ftdmchan - > physical_span_id = ztp . span_no ;
ftdmchan - > physical_chan_id = ztp . chan_no ;
2007-06-04 14:53:12 +00:00
2010-01-15 19:22:49 +00:00
if ( type = = FTDM_CHAN_TYPE_FXS | | type = = FTDM_CHAN_TYPE_FXO | | type = = FTDM_CHAN_TYPE_EM | | type = = FTDM_CHAN_TYPE_B ) {
2007-05-30 01:01:32 +00:00
if ( ztp . g711_type = = ZT_G711_ALAW ) {
2010-01-15 19:22:49 +00:00
ftdmchan - > native_codec = ftdmchan - > effective_codec = FTDM_CODEC_ALAW ;
2007-07-02 14:15:43 +00:00
} else if ( ztp . g711_type = = ZT_G711_MULAW ) {
2010-01-15 19:22:49 +00:00
ftdmchan - > native_codec = ftdmchan - > effective_codec = FTDM_CODEC_ULAW ;
2007-07-02 14:15:43 +00:00
} else {
int type ;
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > span - > trunk_type = = FTDM_TRUNK_E1 ) {
type = FTDM_CODEC_ALAW ;
2007-07-02 14:15:43 +00:00
} else {
2010-01-15 19:22:49 +00:00
type = FTDM_CODEC_ULAW ;
2007-07-02 14:15:43 +00:00
}
2010-01-15 19:22:49 +00:00
ftdmchan - > native_codec = ftdmchan - > effective_codec = type ;
2007-07-02 14:15:43 +00:00
2007-05-30 01:01:32 +00:00
}
}
2007-06-20 17:53:09 +00:00
2007-05-31 02:41:50 +00:00
ztp . wink_time = zt_globals . wink_ms ;
ztp . flash_time = zt_globals . flash_ms ;
2007-05-30 01:01:32 +00:00
2009-03-04 21:31:08 +00:00
if ( ioctl ( sockfd , codes . SET_PARAMS , & ztp ) < 0 ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failure configuring device %s as FreeTDM device %d:%d fd:%d \n " , chanpath , ftdmchan - > span_id , ftdmchan - > chan_id , sockfd ) ;
2007-05-31 02:41:50 +00:00
close ( sockfd ) ;
continue ;
}
2007-06-20 20:30:10 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ftdm_strlen_zero ( name ) ) {
ftdm_copy_string ( ftdmchan - > chan_name , name , sizeof ( ftdmchan - > chan_name ) ) ;
2007-05-30 01:01:32 +00:00
}
2010-01-15 19:22:49 +00:00
if ( ! ftdm_strlen_zero ( number ) ) {
ftdm_copy_string ( ftdmchan - > chan_number , number , sizeof ( ftdmchan - > chan_number ) ) ;
2007-05-30 01:01:32 +00:00
}
configured + + ;
} else {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failure configuring device %s \n " , chanpath ) ;
2007-05-30 01:01:32 +00:00
}
}
2007-06-23 18:51:10 +00:00
2007-06-18 21:32:56 +00:00
2007-05-30 01:01:32 +00:00
return configured ;
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Initialises an freetdm ftdmtel span from a configuration string
2010-01-15 20:08:43 +00:00
* \ param span FreeTDM span
2009-06-08 20:01:29 +00:00
* \ param str Configuration string
2010-01-15 20:08:43 +00:00
* \ param type FreeTDM span type
* \ param name FreeTDM span name
* \ param number FreeTDM span number
2009-06-08 20:01:29 +00:00
* \ return Success or failure
*/
2010-01-15 20:35:11 +00:00
static FIO_CONFIGURE_SPAN_FUNCTION ( zt_configure_span )
2007-05-16 21:59:11 +00:00
{
2007-05-30 01:01:32 +00:00
int items , i ;
2009-08-19 21:47:56 +00:00
char * mydata , * item_list [ 10 ] ;
2007-05-30 01:01:32 +00:00
char * ch , * mx ;
2008-10-10 16:02:09 +00:00
unsigned char cas_bits = 0 ;
2007-05-30 01:01:32 +00:00
int channo ;
int top = 0 ;
unsigned configured = 0 ;
assert ( str ! = NULL ) ;
2010-01-15 19:22:49 +00:00
mydata = ftdm_strdup ( str ) ;
2007-05-30 01:01:32 +00:00
assert ( mydata ! = NULL ) ;
2010-01-15 19:22:49 +00:00
items = ftdm_separate_string ( mydata , ' , ' , item_list , ( sizeof ( item_list ) / sizeof ( item_list [ 0 ] ) ) ) ;
2007-05-30 01:01:32 +00:00
for ( i = 0 ; i < items ; i + + ) {
ch = item_list [ i ] ;
if ( ! ( ch ) ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Invalid input \n " ) ;
2007-05-30 01:01:32 +00:00
continue ;
}
channo = atoi ( ch ) ;
if ( channo < 0 ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Invalid channel number %d \n " , channo ) ;
2007-05-30 01:01:32 +00:00
continue ;
}
if ( ( mx = strchr ( ch , ' - ' ) ) ) {
mx + + ;
top = atoi ( mx ) + 1 ;
} else {
top = channo + 1 ;
}
if ( top < 0 ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Invalid range number %d \n " , top ) ;
2007-05-30 01:01:32 +00:00
continue ;
}
2010-01-15 19:22:49 +00:00
if ( FTDM_CHAN_TYPE_CAS = = type & & ftdm_config_get_cas_bits ( ch , & cas_bits ) ) {
ftdm_log ( FTDM_LOG_ERROR , " Failed to get CAS bits in CAS channel \n " ) ;
2008-10-10 16:02:09 +00:00
continue ;
}
configured + = zt_open_range ( span , channo , top , type , name , number , cas_bits ) ;
2007-05-30 01:01:32 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_safe_free ( mydata ) ;
2007-05-30 01:01:32 +00:00
return configured ;
2007-05-16 21:59:11 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Process configuration variable for a ftdmtel profile
2009-06-08 20:01:29 +00:00
* \ param category Wanpipe profile name
* \ param var Variable name
* \ param val Variable value
* \ param lineno Line number from configuration file
* \ return Success
*/
2010-01-15 20:35:11 +00:00
static FIO_CONFIGURE_FUNCTION ( zt_configure )
2007-05-16 21:59:11 +00:00
{
2007-05-31 02:41:50 +00:00
int num ;
2009-06-04 16:18:22 +00:00
float fnum ;
2007-05-31 02:41:50 +00:00
2007-05-30 01:01:32 +00:00
if ( ! strcasecmp ( category , " defaults " ) ) {
if ( ! strcasecmp ( var , " codec_ms " ) ) {
2007-05-31 02:41:50 +00:00
num = atoi ( val ) ;
if ( num < 10 | | num > 60 ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_WARNING , " invalid codec ms at line %d \n " , lineno ) ;
2007-05-30 01:01:32 +00:00
} else {
2007-05-31 02:41:50 +00:00
zt_globals . codec_ms = num ;
}
} else if ( ! strcasecmp ( var , " wink_ms " ) ) {
num = atoi ( val ) ;
2007-06-01 15:58:27 +00:00
if ( num < 50 | | num > 3000 ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_WARNING , " invalid wink ms at line %d \n " , lineno ) ;
2007-05-31 02:41:50 +00:00
} else {
zt_globals . wink_ms = num ;
}
} else if ( ! strcasecmp ( var , " flash_ms " ) ) {
num = atoi ( val ) ;
2007-06-01 15:58:27 +00:00
if ( num < 50 | | num > 3000 ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_WARNING , " invalid flash ms at line %d \n " , lineno ) ;
2007-05-31 02:41:50 +00:00
} else {
zt_globals . flash_ms = num ;
2007-05-30 01:01:32 +00:00
}
2007-06-01 15:58:27 +00:00
} else if ( ! strcasecmp ( var , " echo_cancel_level " ) ) {
num = atoi ( val ) ;
if ( num < 0 | | num > 256 ) {
2010-04-06 14:41:30 -04:00
ftdm_log ( FTDM_LOG_WARNING , " invalid echo can val at line %d \n " , lineno ) ;
} else {
zt_globals . eclevel = num ;
}
} else if ( ! strcasecmp ( var , " echo_train_level " ) ) {
if ( zt_globals . eclevel < 1 ) {
ftdm_log ( FTDM_LOG_WARNING , " can't set echo train level without setting echo cancel level first at line %d \n " , lineno ) ;
} else {
num = atoi ( val ) ;
if ( num < 0 | | num > 256 ) {
ftdm_log ( FTDM_LOG_WARNING , " invalid echo train val at line %d \n " , lineno ) ;
} else {
zt_globals . etlevel = num ;
}
}
2009-06-04 16:18:22 +00:00
} else if ( ! strcasecmp ( var , " rxgain " ) ) {
fnum = ( float ) atof ( val ) ;
if ( fnum < - 100.0 | | fnum > 100.0 ) {
2010-04-06 14:41:30 -04:00
ftdm_log ( FTDM_LOG_WARNING , " invalid rxgain val at line %d \n " , lineno ) ;
} else {
zt_globals . rxgain = fnum ;
ftdm_log ( FTDM_LOG_INFO , " Setting rxgain val to %f \n " , fnum ) ;
}
2009-06-04 16:18:22 +00:00
} else if ( ! strcasecmp ( var , " txgain " ) ) {
fnum = ( float ) atof ( val ) ;
if ( fnum < - 100.0 | | fnum > 100.0 ) {
2010-04-06 14:41:30 -04:00
ftdm_log ( FTDM_LOG_WARNING , " invalid txgain val at line %d \n " , lineno ) ;
} else {
zt_globals . txgain = fnum ;
ftdm_log ( FTDM_LOG_INFO , " Setting txgain val to %f \n " , fnum ) ;
}
} else {
ftdm_log ( FTDM_LOG_WARNING , " Ignoring unknown setting '%s' \n " , var ) ;
2007-05-30 01:01:32 +00:00
}
}
2007-05-31 02:41:50 +00:00
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-16 21:59:11 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Opens a ftdmtel channel
* \ param ftdmchan Channel to open
2009-06-08 20:01:29 +00:00
* \ return Success or failure
*/
2010-01-15 20:35:11 +00:00
static FIO_OPEN_FUNCTION ( zt_open )
2007-05-16 21:59:11 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_channel_set_feature ( ftdmchan , FTDM_CHANNEL_FEATURE_INTERVAL ) ;
2008-02-18 16:15:24 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > type = = FTDM_CHAN_TYPE_DQ921 | | ftdmchan - > type = = FTDM_CHAN_TYPE_DQ931 ) {
ftdmchan - > native_codec = ftdmchan - > effective_codec = FTDM_CODEC_NONE ;
2007-06-20 17:53:09 +00:00
} else {
2010-01-15 19:22:49 +00:00
int blocksize = zt_globals . codec_ms * ( ftdmchan - > rate / 1000 ) ;
2007-06-20 17:53:09 +00:00
int err ;
2010-01-15 19:22:49 +00:00
if ( ( err = ioctl ( ftdmchan - > sockfd , codes . SET_BLOCKSIZE , & blocksize ) ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " %s " , strerror ( errno ) ) ;
return FTDM_FAIL ;
2007-06-20 17:53:09 +00:00
} else {
2010-01-15 19:22:49 +00:00
ftdmchan - > effective_interval = ftdmchan - > native_interval ;
ftdmchan - > packet_len = blocksize ;
ftdmchan - > native_codec = ftdmchan - > effective_codec ;
2007-06-20 17:53:09 +00:00
}
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > type = = FTDM_CHAN_TYPE_B ) {
2007-06-21 02:13:41 +00:00
int one = 1 ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . AUDIOMODE , & one ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " %s " , strerror ( errno ) ) ;
ftdm_log ( FTDM_LOG_ERROR , " %s \n " , ftdmchan - > last_error ) ;
return FTDM_FAIL ;
2007-06-21 02:13:41 +00:00
}
2010-04-06 14:41:30 -04:00
}
if ( zt_globals . rxgain | | zt_globals . txgain ) {
struct zt_gains gains ;
memset ( & gains , 0 , sizeof ( gains ) ) ;
gains . chan_no = ftdmchan - > physical_chan_id ;
zt_build_gains ( & gains , zt_globals . rxgain , zt_globals . txgain , ftdmchan - > native_codec ) ;
if ( zt_globals . rxgain )
ftdm_log ( FTDM_LOG_INFO , " Setting rxgain to %f on channel %d \n " , zt_globals . rxgain , gains . chan_no ) ;
if ( zt_globals . txgain )
ftdm_log ( FTDM_LOG_INFO , " Setting txgain to %f on channel %d \n " , zt_globals . txgain , gains . chan_no ) ;
if ( ioctl ( ftdmchan - > sockfd , codes . SETGAINS , & gains ) < 0 ) {
ftdm_log ( FTDM_LOG_ERROR , " failure configuring device %s as FreeTDM device %d:%d fd:%d \n " , chanpath , ftdmchan - > span_id , ftdmchan - > chan_id , ftdmchan - > sockfd ) ;
}
}
if ( zt_globals . eclevel > = 0 ) {
2007-06-21 02:13:41 +00:00
int len = zt_globals . eclevel ;
2010-04-06 14:41:30 -04:00
if ( len ) {
ftdm_log ( FTDM_LOG_INFO , " Setting echo cancel to %d taps for %d:%d \n " , len , ftdmchan - > span_id , ftdmchan - > chan_id ) ;
} else {
ftdm_log ( FTDM_LOG_INFO , " Disable echo cancel for %d:%d \n " , ftdmchan - > span_id , ftdmchan - > chan_id ) ;
}
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . ECHOCANCEL , & len ) ) {
ftdm_log ( FTDM_LOG_WARNING , " Echo cancel not available for %d:%d \n " , ftdmchan - > span_id , ftdmchan - > chan_id ) ;
2010-06-29 00:17:48 -04:00
} else if ( zt_globals . etlevel > 0 ) {
2008-05-14 15:53:02 +00:00
len = zt_globals . etlevel ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . ECHOTRAIN , & len ) ) {
ftdm_log ( FTDM_LOG_WARNING , " Echo training not available for %d:%d \n " , ftdmchan - > span_id , ftdmchan - > chan_id ) ;
2008-05-14 15:53:02 +00:00
}
2007-06-21 02:13:41 +00:00
}
}
2009-06-04 23:08:11 +00:00
2007-06-20 17:53:09 +00:00
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-16 21:59:11 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Closes ftdmtel channel
* \ param ftdmchan Channel to close
2009-06-08 20:01:29 +00:00
* \ return Success
*/
2010-01-15 20:35:11 +00:00
static FIO_CLOSE_FUNCTION ( zt_close )
2007-05-16 21:59:11 +00:00
{
2010-11-14 23:38:16 +01:00
if ( ftdmchan - > type = = FTDM_CHAN_TYPE_B ) {
int value = 0 ; /* disable audio mode */
if ( ioctl ( ftdmchan - > sockfd , codes . AUDIOMODE , & value ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " %s " , strerror ( errno ) ) ;
ftdm_log ( FTDM_LOG_ERROR , " %s \n " , ftdmchan - > last_error ) ;
return FTDM_FAIL ;
}
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-16 21:59:11 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 20:08:43 +00:00
* \ brief Executes an FreeTDM command on a ftdmtel channel
2010-01-15 19:22:49 +00:00
* \ param ftdmchan Channel to execute command on
2010-01-15 20:08:43 +00:00
* \ param command FreeTDM command to execute
2009-06-08 20:01:29 +00:00
* \ param obj Object ( unused )
* \ return Success or failure
*/
2010-01-15 20:35:11 +00:00
static FIO_COMMAND_FUNCTION ( zt_command )
2007-05-16 21:59:11 +00:00
{
2007-06-05 04:37:50 +00:00
zt_params_t ztp ;
2007-05-30 01:01:32 +00:00
int err = 0 ;
2007-06-05 04:37:50 +00:00
memset ( & ztp , 0 , sizeof ( ztp ) ) ;
2007-05-30 01:01:32 +00:00
switch ( command ) {
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_ENABLE_ECHOCANCEL :
2008-07-30 15:05:07 +00:00
{
2010-01-15 19:22:49 +00:00
int level = FTDM_COMMAND_OBJ_INT ;
err = ioctl ( ftdmchan - > sockfd , codes . ECHOCANCEL , & level ) ;
FTDM_COMMAND_OBJ_INT = level ;
2008-07-30 15:05:07 +00:00
}
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_DISABLE_ECHOCANCEL :
2008-07-30 15:05:07 +00:00
{
int level = 0 ;
2010-01-15 19:22:49 +00:00
err = ioctl ( ftdmchan - > sockfd , codes . ECHOCANCEL , & level ) ;
FTDM_COMMAND_OBJ_INT = level ;
2008-07-30 15:05:07 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_ENABLE_ECHOTRAIN :
2008-07-30 15:05:07 +00:00
{
2010-01-15 19:22:49 +00:00
int level = FTDM_COMMAND_OBJ_INT ;
err = ioctl ( ftdmchan - > sockfd , codes . ECHOTRAIN , & level ) ;
FTDM_COMMAND_OBJ_INT = level ;
2008-07-30 15:05:07 +00:00
}
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_DISABLE_ECHOTRAIN :
2008-07-30 15:05:07 +00:00
{
int level = 0 ;
2010-01-15 19:22:49 +00:00
err = ioctl ( ftdmchan - > sockfd , codes . ECHOTRAIN , & level ) ;
FTDM_COMMAND_OBJ_INT = level ;
2008-07-30 15:05:07 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_OFFHOOK :
2007-05-31 20:15:16 +00:00
{
int command = ZT_OFFHOOK ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . HOOK , & command ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " OFFHOOK Failed " ) ;
return FTDM_FAIL ;
2007-05-31 20:15:16 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_set_flag_locked ( ftdmchan , FTDM_CHANNEL_OFFHOOK ) ;
2007-05-31 20:15:16 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_ONHOOK :
2007-05-31 20:15:16 +00:00
{
int command = ZT_ONHOOK ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . HOOK , & command ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " ONHOOK Failed " ) ;
return FTDM_FAIL ;
2007-05-31 20:15:16 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_clear_flag_locked ( ftdmchan , FTDM_CHANNEL_OFFHOOK ) ;
2007-05-31 20:15:16 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_FLASH :
2008-11-20 23:46:15 +00:00
{
int command = ZT_FLASH ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . HOOK , & command ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " FLASH Failed " ) ;
return FTDM_FAIL ;
2008-11-20 23:46:15 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_WINK :
2008-12-03 16:02:17 +00:00
{
int command = ZT_WINK ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . HOOK , & command ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " WINK Failed " ) ;
return FTDM_FAIL ;
2008-12-03 16:02:17 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_GENERATE_RING_ON :
2007-05-31 20:15:16 +00:00
{
int command = ZT_RING ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . HOOK , & command ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " Ring Failed " ) ;
return FTDM_FAIL ;
2007-05-31 20:15:16 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_set_flag_locked ( ftdmchan , FTDM_CHANNEL_RINGING ) ;
2007-05-31 20:15:16 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_GENERATE_RING_OFF :
2007-05-31 20:15:16 +00:00
{
int command = ZT_RINGOFF ;
2010-01-15 19:22:49 +00:00
if ( ioctl ( ftdmchan - > sockfd , codes . HOOK , & command ) ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " Ring-off failed " ) ;
return FTDM_FAIL ;
2007-05-31 20:15:16 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_clear_flag_locked ( ftdmchan , FTDM_CHANNEL_RINGING ) ;
2007-05-31 20:15:16 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_GET_INTERVAL :
2007-05-30 01:01:32 +00:00
{
2007-06-27 19:18:13 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ( err = ioctl ( ftdmchan - > sockfd , codes . GET_BLOCKSIZE , & ftdmchan - > packet_len ) ) ) {
ftdmchan - > native_interval = ftdmchan - > packet_len / 8 ;
if ( ftdmchan - > effective_codec = = FTDM_CODEC_SLIN ) {
ftdmchan - > packet_len * = 2 ;
2007-05-30 01:01:32 +00:00
}
2010-01-15 19:22:49 +00:00
FTDM_COMMAND_OBJ_INT = ftdmchan - > native_interval ;
2007-06-27 19:18:13 +00:00
}
2007-05-30 01:01:32 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_SET_INTERVAL :
2007-05-30 01:01:32 +00:00
{
2010-01-15 19:22:49 +00:00
int interval = FTDM_COMMAND_OBJ_INT ;
2007-05-30 01:01:32 +00:00
int len = interval * 8 ;
2010-01-15 19:22:49 +00:00
if ( ! ( err = ioctl ( ftdmchan - > sockfd , codes . SET_BLOCKSIZE , & len ) ) ) {
ftdmchan - > packet_len = len ;
ftdmchan - > effective_interval = ftdmchan - > native_interval = ftdmchan - > packet_len / 8 ;
2007-05-30 01:01:32 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > effective_codec = = FTDM_CODEC_SLIN ) {
ftdmchan - > packet_len * = 2 ;
2009-08-19 21:47:56 +00:00
}
2007-05-30 01:01:32 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_SET_CAS_BITS :
2008-10-10 16:02:09 +00:00
{
2010-01-15 19:22:49 +00:00
int bits = FTDM_COMMAND_OBJ_INT ;
err = ioctl ( ftdmchan - > sockfd , codes . SETTXBITS , & bits ) ;
2008-10-10 16:02:09 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_GET_CAS_BITS :
2008-10-10 16:02:09 +00:00
{
2010-01-15 19:22:49 +00:00
err = ioctl ( ftdmchan - > sockfd , codes . GETRXBITS , & ftdmchan - > rx_cas_bits ) ;
2009-08-19 21:47:56 +00:00
if ( ! err ) {
2010-01-15 19:22:49 +00:00
FTDM_COMMAND_OBJ_INT = ftdmchan - > rx_cas_bits ;
2009-08-19 21:47:56 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_FLUSH_TX_BUFFERS :
2009-08-19 21:47:56 +00:00
{
int flushmode = ZT_FLUSH_WRITE ;
2010-01-15 19:22:49 +00:00
err = ioctl ( ftdmchan - > sockfd , codes . FLUSH , & flushmode ) ;
2009-08-19 21:47:56 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_FLUSH_RX_BUFFERS :
2009-08-19 21:47:56 +00:00
{
int flushmode = ZT_FLUSH_READ ;
2010-01-15 19:22:49 +00:00
err = ioctl ( ftdmchan - > sockfd , codes . FLUSH , & flushmode ) ;
2009-08-19 21:47:56 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_COMMAND_FLUSH_BUFFERS :
2009-08-19 21:47:56 +00:00
{
int flushmode = ZT_FLUSH_BOTH ;
2010-01-15 19:22:49 +00:00
err = ioctl ( ftdmchan - > sockfd , codes . FLUSH , & flushmode ) ;
2008-10-10 16:02:09 +00:00
}
break ;
2007-05-30 01:01:32 +00:00
default :
2010-01-15 19:22:49 +00:00
err = FTDM_NOTIMPL ;
2007-05-30 01:01:32 +00:00
break ;
} ;
2010-01-15 19:22:49 +00:00
if ( err & & err ! = FTDM_NOTIMPL ) {
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " %s " , strerror ( errno ) ) ;
return FTDM_FAIL ;
2007-05-30 01:01:32 +00:00
}
2010-01-15 19:22:49 +00:00
return err = = 0 ? FTDM_SUCCESS : err ;
2007-05-16 21:59:11 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Gets alarms from a ftdmtel Channel
* \ param ftdmchan Channel to get alarms from
2009-06-08 20:01:29 +00:00
* \ return Success or failure
*/
2010-01-15 20:35:11 +00:00
static FIO_GET_ALARMS_FUNCTION ( zt_get_alarms )
2007-06-23 18:51:10 +00:00
{
struct zt_spaninfo info ;
memset ( & info , 0 , sizeof ( info ) ) ;
2010-01-15 19:22:49 +00:00
info . span_no = ftdmchan - > physical_span_id ;
2007-06-23 18:51:10 +00:00
2009-03-04 21:31:08 +00:00
if ( ioctl ( CONTROL_FD , codes . SPANSTAT , & info ) ) {
2010-01-15 19:22:49 +00:00
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " ioctl failed (%s) " , strerror ( errno ) ) ;
snprintf ( ftdmchan - > span - > last_error , sizeof ( ftdmchan - > span - > last_error ) , " ioctl failed (%s) " , strerror ( errno ) ) ;
return FTDM_FAIL ;
2007-06-23 18:51:10 +00:00
}
2010-01-15 19:22:49 +00:00
ftdmchan - > alarm_flags = info . alarms ;
2007-06-23 18:51:10 +00:00
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-06-23 18:51:10 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Waits for an event on a ftdmtel channel
* \ param ftdmchan Channel to open
2009-06-08 20:01:29 +00:00
* \ param flags Type of event to wait for
* \ param to Time to wait ( in ms )
* \ return Success , failure or timeout
*/
2010-01-15 20:35:11 +00:00
static FIO_WAIT_FUNCTION ( zt_wait )
2007-05-16 21:59:11 +00:00
{
2007-05-30 01:01:32 +00:00
int32_t inflags = 0 ;
int result ;
2010-11-06 17:14:31 -04:00
struct pollfd pfds [ 1 ] ;
2007-05-30 01:01:32 +00:00
2010-01-15 19:22:49 +00:00
if ( * flags & FTDM_READ ) {
2007-05-30 01:01:32 +00:00
inflags | = POLLIN ;
}
2010-01-15 19:22:49 +00:00
if ( * flags & FTDM_WRITE ) {
2007-05-30 01:01:32 +00:00
inflags | = POLLOUT ;
}
2010-01-15 19:22:49 +00:00
if ( * flags & FTDM_EVENTS ) {
2007-05-30 01:01:32 +00:00
inflags | = POLLPRI ;
}
2010-11-16 23:41:11 -05:00
pollagain :
2010-11-06 17:14:31 -04:00
memset ( & pfds [ 0 ] , 0 , sizeof ( pfds [ 0 ] ) ) ;
pfds [ 0 ] . fd = ftdmchan - > sockfd ;
pfds [ 0 ] . events = inflags ;
result = poll ( pfds , 1 , to ) ;
2007-05-30 01:01:32 +00:00
* flags = 0 ;
2010-11-17 17:15:30 +01:00
if ( result < 0 & & errno = = EINTR ) {
2010-11-16 23:41:11 -05:00
ftdm_log_chan_msg ( ftdmchan , FTDM_LOG_DEBUG , " DAHDI wait got interrupted, trying again \n " ) ;
goto pollagain ;
}
2007-05-30 01:01:32 +00:00
if ( pfds [ 0 ] . revents & POLLERR ) {
2010-11-06 17:14:31 -04:00
ftdm_log_chan_msg ( ftdmchan , FTDM_LOG_ERROR , " DAHDI device got POLLERR \n " ) ;
2007-05-30 01:01:32 +00:00
result = - 1 ;
}
if ( result > 0 ) {
2007-06-23 18:51:10 +00:00
inflags = pfds [ 0 ] . revents ;
2007-05-30 01:01:32 +00:00
}
2010-01-15 19:22:49 +00:00
* flags = FTDM_NO_FLAGS ;
2007-05-30 01:01:32 +00:00
if ( result < 0 ) {
2010-01-15 19:22:49 +00:00
snprintf ( ftdmchan - > last_error , sizeof ( ftdmchan - > last_error ) , " Poll failed " ) ;
2010-11-06 17:14:31 -04:00
ftdm_log_chan ( ftdmchan , FTDM_LOG_ERROR , " Failed to poll DAHDI device: %s \n " , strerror ( errno ) ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-30 01:01:32 +00:00
}
if ( result = = 0 ) {
2010-01-15 19:22:49 +00:00
return FTDM_TIMEOUT ;
2007-05-30 01:01:32 +00:00
}
if ( inflags & POLLIN ) {
2010-01-15 19:22:49 +00:00
* flags | = FTDM_READ ;
2007-05-30 01:01:32 +00:00
}
if ( inflags & POLLOUT ) {
2010-01-15 19:22:49 +00:00
* flags | = FTDM_WRITE ;
2007-05-30 01:01:32 +00:00
}
if ( inflags & POLLPRI ) {
2010-01-15 19:22:49 +00:00
* flags | = FTDM_EVENTS ;
2007-05-30 01:01:32 +00:00
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-30 01:01:32 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Checks for events on a ftdmtel span
2009-06-08 20:01:29 +00:00
* \ param span Span to check for events
* \ param ms Time to wait for event
* \ return Success if event is waiting or failure if not
*/
2010-01-15 20:35:11 +00:00
FIO_SPAN_POLL_EVENT_FUNCTION ( zt_poll_event )
2007-05-30 01:01:32 +00:00
{
2010-01-15 19:22:49 +00:00
struct pollfd pfds [ FTDM_MAX_CHANNELS_SPAN ] ;
2007-06-05 04:37:50 +00:00
uint32_t i , j = 0 , k = 0 ;
int r ;
2007-05-30 01:01:32 +00:00
for ( i = 1 ; i < = span - > chan_count ; i + + ) {
memset ( & pfds [ j ] , 0 , sizeof ( pfds [ j ] ) ) ;
2008-09-10 15:25:02 +00:00
pfds [ j ] . fd = span - > channels [ i ] - > sockfd ;
2007-05-30 01:01:32 +00:00
pfds [ j ] . events = POLLPRI ;
j + + ;
}
r = poll ( pfds , j , ms ) ;
if ( r = = 0 ) {
2010-01-15 19:22:49 +00:00
return FTDM_TIMEOUT ;
2007-05-30 01:01:32 +00:00
} else if ( r < 0 | | ( pfds [ i - 1 ] . revents & POLLERR ) ) {
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " %s " , strerror ( errno ) ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-30 01:01:32 +00:00
}
for ( i = 1 ; i < = span - > chan_count ; i + + ) {
if ( pfds [ i - 1 ] . revents & POLLPRI ) {
2010-01-15 19:22:49 +00:00
ftdm_set_flag ( span - > channels [ i ] , FTDM_CHANNEL_EVENT ) ;
span - > channels [ i ] - > last_event_time = ftdm_current_time_in_ms ( ) ;
2007-05-30 01:01:32 +00:00
k + + ;
}
}
2008-05-09 14:50:21 +00:00
if ( ! k ) {
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " no matching descriptor " ) ;
}
2010-01-15 19:22:49 +00:00
return k ? FTDM_SUCCESS : FTDM_FAIL ;
2007-05-30 01:01:32 +00:00
}
2010-12-09 12:48:33 -02:00
/**
2010-12-23 16:05:48 -02:00
* \ brief Process an event from a ftdmchan and set the proper OOB event_id . The channel must be locked .
* \ param fchan Channel to retrieve event from
* \ param event_id Pointer to OOB event id
* \ param zt_event_id Zaptel event id
* \ return FTDM_SUCCESS or FTDM_FAIL
2010-12-09 12:48:33 -02:00
*/
2010-12-23 16:05:48 -02:00
static __inline__ ftdm_status_t zt_channel_process_event ( ftdm_channel_t * fchan , ftdm_oob_event_t * event_id , zt_event_t zt_event_id )
2010-12-09 12:48:33 -02:00
{
2010-12-21 22:13:16 -02:00
switch ( zt_event_id ) {
case ZT_EVENT_RINGEROFF :
{
2010-12-09 12:48:33 -02:00
return FTDM_FAIL ;
}
2010-12-21 22:13:16 -02:00
break ;
case ZT_EVENT_RINGERON :
{
return FTDM_FAIL ;
}
break ;
case ZT_EVENT_RINGBEGIN :
{
2010-12-23 16:05:48 -02:00
* event_id = FTDM_OOB_RING_START ;
2010-12-21 22:13:16 -02:00
}
break ;
case ZT_EVENT_ONHOOK :
{
2010-12-23 16:05:48 -02:00
* event_id = FTDM_OOB_ONHOOK ;
2010-12-21 22:13:16 -02:00
}
break ;
case ZT_EVENT_WINKFLASH :
{
2010-12-23 16:05:48 -02:00
if ( fchan - > state = = FTDM_CHANNEL_STATE_DOWN | | fchan - > state = = FTDM_CHANNEL_STATE_DIALING ) {
* event_id = FTDM_OOB_WINK ;
2010-12-21 22:13:16 -02:00
} else {
2010-12-23 16:05:48 -02:00
* event_id = FTDM_OOB_FLASH ;
2010-12-09 12:48:33 -02:00
}
2010-12-21 22:13:16 -02:00
}
break ;
case ZT_EVENT_RINGOFFHOOK :
{
2010-12-23 16:05:48 -02:00
if ( fchan - > type = = FTDM_CHAN_TYPE_FXS | | ( fchan - > type = = FTDM_CHAN_TYPE_EM & & fchan - > state ! = FTDM_CHANNEL_STATE_UP ) ) {
ftdm_set_flag_locked ( fchan , FTDM_CHANNEL_OFFHOOK ) ;
* event_id = FTDM_OOB_OFFHOOK ;
} else if ( fchan - > type = = FTDM_CHAN_TYPE_FXO ) {
* event_id = FTDM_OOB_RING_START ;
2010-12-21 22:13:16 -02:00
} else {
2010-12-23 16:05:48 -02:00
* event_id = FTDM_OOB_NOOP ;
2010-12-09 12:48:33 -02:00
}
2010-12-21 22:13:16 -02:00
}
break ;
case ZT_EVENT_ALARM :
{
2010-12-23 16:05:48 -02:00
* event_id = FTDM_OOB_ALARM_TRAP ;
2010-12-21 22:13:16 -02:00
}
break ;
case ZT_EVENT_NOALARM :
{
2010-12-23 16:05:48 -02:00
* event_id = FTDM_OOB_ALARM_CLEAR ;
2010-12-21 22:13:16 -02:00
}
break ;
case ZT_EVENT_BITSCHANGED :
{
2010-12-23 16:05:48 -02:00
* event_id = FTDM_OOB_CAS_BITS_CHANGE ;
2010-12-21 22:13:16 -02:00
int bits = 0 ;
2010-12-23 16:05:48 -02:00
int err = ioctl ( fchan - > sockfd , codes . GETRXBITS , & bits ) ;
2010-12-21 22:13:16 -02:00
if ( err ) {
return FTDM_FAIL ;
2010-12-09 12:48:33 -02:00
}
2010-12-23 16:05:48 -02:00
fchan - > rx_cas_bits = bits ;
2010-12-09 12:48:33 -02:00
}
2010-12-21 22:13:16 -02:00
break ;
2011-01-06 14:33:28 -05:00
case ZT_EVENT_NONE :
{
ftdm_log_chan_msg ( fchan , FTDM_LOG_DEBUG , " No event \n " ) ;
* event_id = FTDM_OOB_NOOP ;
}
break ;
2010-12-21 22:13:16 -02:00
default :
{
2010-12-23 16:05:48 -02:00
ftdm_log_chan ( fchan , FTDM_LOG_WARNING , " Unhandled event %d \n " , zt_event_id ) ;
* event_id = FTDM_OOB_INVALID ;
2010-12-21 22:13:16 -02:00
}
break ;
2010-12-09 12:48:33 -02:00
}
2010-12-23 16:05:48 -02:00
return FTDM_SUCCESS ;
}
/**
* \ brief Retrieves an event from a ftdm channel
* \ param ftdmchan Channel to retrieve event from
* \ param event FreeTDM event to return
* \ return Success or failure
*/
FIO_CHANNEL_NEXT_EVENT_FUNCTION ( zt_channel_next_event )
{
uint32_t event_id = FTDM_OOB_INVALID ;
zt_event_t zt_event_id = 0 ;
ftdm_span_t * span = ftdmchan - > span ;
if ( ftdm_test_flag ( ftdmchan , FTDM_CHANNEL_EVENT ) ) {
ftdm_clear_flag ( ftdmchan , FTDM_CHANNEL_EVENT ) ;
}
if ( ioctl ( ftdmchan - > sockfd , codes . GETEVENT , & zt_event_id ) = = - 1 ) {
ftdm_log_chan ( ftdmchan , FTDM_LOG_ERROR , " Failed retrieving event from channel: %s \n " ,
strerror ( errno ) ) ;
return FTDM_FAIL ;
}
2010-12-23 16:10:53 -02:00
/* the core already locked the channel for us, so it's safe to call zt_channel_process_event() here */
2010-12-23 16:05:48 -02:00
if ( ( zt_channel_process_event ( ftdmchan , & event_id , zt_event_id ) ) ! = FTDM_SUCCESS ) {
ftdm_log_chan_msg ( ftdmchan , FTDM_LOG_ERROR , " Failed to process event from channel \n " ) ;
return FTDM_FAIL ;
}
2010-12-09 12:48:33 -02:00
2010-12-21 22:13:16 -02:00
ftdmchan - > last_event_time = 0 ;
span - > event_header . e_type = FTDM_EVENT_OOB ;
span - > event_header . enum_id = event_id ;
span - > event_header . channel = ftdmchan ;
* event = & span - > event_header ;
return FTDM_SUCCESS ;
2010-12-09 12:48:33 -02:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Retrieves an event from a ftdmtel span
2009-06-08 20:01:29 +00:00
* \ param span Span to retrieve event from
2010-01-15 20:08:43 +00:00
* \ param event FreeTDM event to return
2009-06-08 20:01:29 +00:00
* \ return Success or failure
*/
2010-01-15 20:35:11 +00:00
FIO_SPAN_NEXT_EVENT_FUNCTION ( zt_next_event )
2007-05-30 01:01:32 +00:00
{
2010-09-27 21:56:03 -04:00
uint32_t i , event_id = FTDM_OOB_INVALID ;
2010-04-30 23:10:18 +02:00
zt_event_t zt_event_id = 0 ;
2007-05-30 01:01:32 +00:00
for ( i = 1 ; i < = span - > chan_count ; i + + ) {
2010-12-23 16:05:48 -02:00
ftdm_channel_t * fchan = span - > channels [ i ] ;
if ( ftdm_test_flag ( fchan , FTDM_CHANNEL_EVENT ) ) {
ftdm_clear_flag ( fchan , FTDM_CHANNEL_EVENT ) ;
2011-01-06 14:54:19 -05:00
if ( ioctl ( fchan - > sockfd , codes . GETEVENT , & zt_event_id ) = = - 1 ) {
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " %s " , strerror ( errno ) ) ;
return FTDM_FAIL ;
}
2007-05-30 01:01:32 +00:00
2011-01-06 14:54:19 -05:00
ftdm_channel_lock ( fchan ) ;
if ( ( zt_channel_process_event ( fchan , & event_id , zt_event_id ) ) ! = FTDM_SUCCESS ) {
ftdm_log_chan_msg ( fchan , FTDM_LOG_ERROR , " Failed to process event from channel \n " ) ;
ftdm_channel_unlock ( fchan ) ;
return FTDM_FAIL ;
}
2010-12-23 16:10:53 -02:00
ftdm_channel_unlock ( fchan ) ;
2011-01-06 14:54:19 -05:00
fchan - > last_event_time = 0 ;
span - > event_header . e_type = FTDM_EVENT_OOB ;
span - > event_header . enum_id = event_id ;
span - > event_header . channel = fchan ;
* event = & span - > event_header ;
return FTDM_SUCCESS ;
2007-05-30 01:01:32 +00:00
}
}
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-16 21:59:11 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Reads data from a ftdmtel channel
* \ param ftdmchan Channel to read from
2009-06-08 20:01:29 +00:00
* \ param data Data buffer
* \ param datalen Size of data buffer
* \ return Success , failure or timeout
*/
2010-01-15 20:35:11 +00:00
static FIO_READ_FUNCTION ( zt_read )
2007-05-16 21:59:11 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_ssize_t r = 0 ;
2008-01-25 16:42:06 +00:00
int errs = 0 ;
2007-05-30 01:01:32 +00:00
2009-07-27 23:18:47 +00:00
while ( errs + + < 30 ) {
2010-01-15 19:22:49 +00:00
if ( ( r = read ( ftdmchan - > sockfd , data , * datalen ) ) > 0 ) {
2008-01-25 16:42:06 +00:00
break ;
}
2010-12-07 20:06:48 +01:00
else if ( r = = 0 ) {
ftdm_sleep ( 10 ) ;
if ( errs ) errs - - ;
2009-04-22 21:22:42 +00:00
}
2010-12-07 20:06:48 +01:00
else {
if ( errno = = EAGAIN | | errno = = EINTR )
continue ;
if ( errno = = ELAST )
break ;
2007-06-20 20:30:10 +00:00
2010-12-07 20:06:48 +01:00
ftdm_log ( FTDM_LOG_ERROR , " read failed: %s \n " , strerror ( errno ) ) ;
}
}
2008-01-25 16:42:06 +00:00
if ( r > 0 ) {
2007-05-30 01:01:32 +00:00
* datalen = r ;
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > type = = FTDM_CHAN_TYPE_DQ921 ) {
2007-06-20 20:30:10 +00:00
* datalen - = 2 ;
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-30 01:01:32 +00:00
}
2010-12-07 20:06:48 +01:00
else if ( errno = = ELAST ) {
return FTDM_SUCCESS ;
}
2010-01-15 19:22:49 +00:00
return r = = 0 ? FTDM_TIMEOUT : FTDM_FAIL ;
2007-05-16 21:59:11 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Writes data to a ftdmtel channel
* \ param ftdmchan Channel to write to
2009-06-08 20:01:29 +00:00
* \ param data Data buffer
* \ param datalen Size of data buffer
* \ return Success or failure
*/
2010-01-15 20:35:11 +00:00
static FIO_WRITE_FUNCTION ( zt_write )
2007-05-16 21:59:11 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_ssize_t w = 0 ;
ftdm_size_t bytes = * datalen ;
2007-05-30 01:01:32 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdmchan - > type = = FTDM_CHAN_TYPE_DQ921 ) {
2007-06-20 20:30:10 +00:00
memset ( data + bytes , 0 , 2 ) ;
bytes + = 2 ;
}
2007-05-30 01:01:32 +00:00
2010-12-19 00:13:08 -05:00
tryagain :
2010-01-15 19:22:49 +00:00
w = write ( ftdmchan - > sockfd , data , bytes ) ;
2007-06-20 20:30:10 +00:00
2007-05-30 01:01:32 +00:00
if ( w > = 0 ) {
* datalen = w ;
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-30 01:01:32 +00:00
}
2010-12-19 00:13:08 -05:00
if ( errno = = ELAST ) {
zt_event_t zt_event_id = 0 ;
if ( ioctl ( ftdmchan - > sockfd , codes . GETEVENT , & zt_event_id ) = = - 1 ) {
ftdm_log_chan ( ftdmchan , FTDM_LOG_ERROR , " Failed retrieving event after ELAST on write: %s \n " , strerror ( errno ) ) ;
return FTDM_FAIL ;
}
/* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */
ftdm_log_chan ( ftdmchan , FTDM_LOG_ERROR , " Dropping event %d to be able to write data \n " , zt_event_id ) ;
goto tryagain ;
}
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-16 21:59:11 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Destroys a ftdmtel Channel
* \ param ftdmchan Channel to destroy
2009-06-08 20:01:29 +00:00
* \ return Success
*/
2010-01-15 20:35:11 +00:00
static FIO_CHANNEL_DESTROY_FUNCTION ( zt_channel_destroy )
2007-05-31 02:41:50 +00:00
{
2010-01-15 19:22:49 +00:00
close ( ftdmchan - > sockfd ) ;
ftdmchan - > sockfd = ZT_INVALID_SOCKET ;
2007-05-31 02:41:50 +00:00
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-31 02:41:50 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 20:08:43 +00:00
* \ brief Global FreeTDM IO interface for ftdmtel
2009-06-08 20:01:29 +00:00
*/
2010-01-15 19:22:49 +00:00
static ftdm_io_interface_t zt_interface ;
2007-05-16 21:59:11 +00:00
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Loads ftdmtel IO module
2010-01-15 20:35:11 +00:00
* \ param fio FreeTDM IO interface
2009-06-08 20:01:29 +00:00
* \ return Success or failure
*/
2010-01-15 20:35:11 +00:00
static FIO_IO_LOAD_FUNCTION ( zt_init )
2007-05-16 20:36:40 +00:00
{
2010-01-15 20:35:11 +00:00
assert ( fio ! = NULL ) ;
2009-03-04 21:31:08 +00:00
struct stat statbuf ;
2007-05-16 21:59:11 +00:00
memset ( & zt_interface , 0 , sizeof ( zt_interface ) ) ;
2007-05-30 01:01:32 +00:00
memset ( & zt_globals , 0 , sizeof ( zt_globals ) ) ;
2009-03-04 21:31:08 +00:00
if ( ! stat ( zt_ctlpath , & statbuf ) ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_NOTICE , " Using Zaptel control device \n " ) ;
2009-03-04 21:31:08 +00:00
ctlpath = zt_ctlpath ;
chanpath = zt_chanpath ;
memcpy ( & codes , & zt_ioctl_codes , sizeof ( codes ) ) ;
} else if ( ! stat ( dahdi_ctlpath , & statbuf ) ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_NOTICE , " Using DAHDI control device \n " ) ;
2009-03-04 21:31:08 +00:00
ctlpath = dahdi_ctlpath ;
chanpath = dahdi_chanpath ;
memcpy ( & codes , & dahdi_ioctl_codes , sizeof ( codes ) ) ;
} else {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_ERROR , " No DAHDI or Zap control device found in /dev/ \n " ) ;
return FTDM_FAIL ;
2009-03-04 21:31:08 +00:00
}
2007-06-23 18:51:10 +00:00
if ( ( CONTROL_FD = open ( ctlpath , O_RDWR ) ) < 0 ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Cannot open control device %s: %s \n " , ctlpath , strerror ( errno ) ) ;
return FTDM_FAIL ;
2007-06-23 18:51:10 +00:00
}
2007-05-30 01:01:32 +00:00
zt_globals . codec_ms = 20 ;
zt_globals . wink_ms = 150 ;
zt_globals . flash_ms = 750 ;
2010-04-06 14:41:30 -04:00
zt_globals . eclevel = 0 ;
2007-06-21 02:13:41 +00:00
zt_globals . etlevel = 0 ;
2007-06-01 15:58:27 +00:00
2007-05-16 21:59:11 +00:00
zt_interface . name = " zt " ;
2007-05-30 01:01:32 +00:00
zt_interface . configure = zt_configure ;
zt_interface . configure_span = zt_configure_span ;
2007-05-16 21:59:11 +00:00
zt_interface . open = zt_open ;
zt_interface . close = zt_close ;
2007-05-31 20:15:16 +00:00
zt_interface . command = zt_command ;
2007-05-16 21:59:11 +00:00
zt_interface . wait = zt_wait ;
zt_interface . read = zt_read ;
zt_interface . write = zt_write ;
2007-05-30 01:01:32 +00:00
zt_interface . poll_event = zt_poll_event ;
zt_interface . next_event = zt_next_event ;
2007-06-23 18:51:10 +00:00
zt_interface . channel_destroy = zt_channel_destroy ;
zt_interface . get_alarms = zt_get_alarms ;
2010-01-15 20:35:11 +00:00
* fio = & zt_interface ;
2007-05-16 20:36:40 +00:00
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-16 20:36:40 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Unloads ftdmtel IO module
2009-06-08 20:01:29 +00:00
* \ return Success
*/
2010-01-15 20:35:11 +00:00
static FIO_IO_UNLOAD_FUNCTION ( zt_destroy )
2007-05-16 20:36:40 +00:00
{
2007-06-23 18:51:10 +00:00
close ( CONTROL_FD ) ;
2007-05-31 02:41:50 +00:00
memset ( & zt_interface , 0 , sizeof ( zt_interface ) ) ;
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-16 20:36:40 +00:00
}
2007-06-04 14:53:12 +00:00
2009-06-08 20:01:29 +00:00
/**
2010-01-15 20:08:43 +00:00
* \ brief FreeTDM ftdmtel IO module definition
2009-06-08 20:01:29 +00:00
*/
2010-01-15 19:22:49 +00:00
ftdm_module_t ftdm_module = {
2008-08-29 15:58:59 +00:00
" zt " ,
zt_init ,
zt_destroy ,
} ;
2007-06-04 14:53:12 +00:00
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2009-09-14 22:06:20 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2007-06-04 14:53:12 +00:00
*/