Wed Aug 15 01:24:58 2007

Asterisk developer's documentation


chan_zap.c File Reference

Zaptel Pseudo TDM interface. More...

#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <zaptel/zaptel.h>
#include <zaptel/tonezone.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/file.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/adsi.h"
#include "asterisk/cli.h"
#include "asterisk/cdr.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj.h"

Include dependency graph for chan_zap.c:

Go to the source code of this file.

Data Structures

struct  distRingData
struct  ringContextData
struct  zt_chan_conf
 Channel configuration from zapata.conf . This struct is used for parsing the [channels] section of zapata.conf. Generally there is a field here for every possible configuration item. More...
struct  zt_distRings
struct  zt_pvt
struct  zt_subchannel

Defines

#define ASCII_BYTES_PER_CHAR   80
#define AST_LAW(p)   (((p)->law == ZT_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
#define CALLWAITING_REPEAT_SAMPLES   ( (10000 * 8) / READ_SIZE)
#define CALLWAITING_SILENT_SAMPLES   ( (300 * 8) / READ_SIZE)
#define CANBUSYDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
#define CANPROGRESSDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
#define CHAN_PSEUDO   -2
#define CHANNEL_PSEUDO   -12
#define CIDCW_EXPIRE_SAMPLES   ( (500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
#define DCHAN_NOTINALARM   (1 << 1)
#define DCHAN_PROVISIONED   (1 << 0)
#define DCHAN_UP   (1 << 2)
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID.
#define DEFAULT_RINGT   ( (8000 * 8) / READ_SIZE)
#define END_SILENCE_LEN   400
#define FORMAT   "%-40.40s %-10.10s %-10d %-10d %-10d\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define FORMAT2   "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define GET_CHANNEL(p)   ((p)->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_CHANNELS   672
#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ( (2000) )
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro.
#define NUM_CADENCE_MAX   25
#define NUM_DCHANS   4
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define READ_SIZE   160
#define sig2str   zap_sig2str
#define SIG_E911   (0x1000000 | ZT_SIG_EM)
#define SIG_EM   ZT_SIG_EM
#define SIG_EM_E1   ZT_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | ZT_SIG_EM)
#define SIG_FEATB   (0x0800000 | ZT_SIG_EM)
#define SIG_FEATD   (0x0200000 | ZT_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | ZT_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | ZT_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | ZT_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | ZT_SIG_EM)
#define SIG_FXOGS   ZT_SIG_FXOGS
#define SIG_FXOKS   ZT_SIG_FXOKS
#define SIG_FXOLS   ZT_SIG_FXOLS
#define SIG_FXSGS   ZT_SIG_FXSGS
#define SIG_FXSKS   ZT_SIG_FXSKS
#define SIG_FXSLS   ZT_SIG_FXSLS
#define SIG_GR303FXOKS   (0x0100000 | ZT_SIG_FXOKS)
#define SIG_GR303FXSKS   (0x0100000 | ZT_SIG_FXSKS)
#define SIG_PRI   ZT_SIG_CLEAR
#define SIG_SF   ZT_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | ZT_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | ZT_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | ZT_SIG_SF)
#define SIG_SFWINK   (0x0100000 | ZT_SIG_SF)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define tdesc   "Zapata Telephony"
#define TRAILER_MS   5
#define TRANSFER   0
#define ZT_EVENT_DTMFDOWN   0
#define ZT_EVENT_DTMFUP   0

Functions

static int __unload_module (void)
static struct ast_frame__zt_exception (struct ast_channel *ast)
static int action_transfer (struct mansession *s, const struct message *m)
static int action_transferhangup (struct mansession *s, const struct message *m)
static int action_zapdialoffhook (struct mansession *s, const struct message *m)
static int action_zapdndoff (struct mansession *s, const struct message *m)
static int action_zapdndon (struct mansession *s, const struct message *m)
static int action_zaprestart (struct mansession *s, const struct message *m)
static int action_zapshowchannels (struct mansession *s, const struct message *m)
static char * alarm2str (int alarm)
static int alloc_sub (struct zt_pvt *p, int x)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,.load=load_module,.unload=unload_module,.reload=reload,)
 AST_MUTEX_DEFINE_STATIC (monlock)
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
 AST_MUTEX_DEFINE_STATIC (iflock)
 Protect the interface list (of zt_pvt's).
static int attempt_transfer (struct zt_pvt *p)
static int available (struct zt_pvt *p, int channelmatch, int groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct zt_chan_conf conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct zt_pvt *p)
static struct zt_pvtchandup (struct zt_pvt *src)
static int check_for_conference (struct zt_pvt *p)
static int conf_add (struct zt_pvt *p, struct zt_subchannel *c, int index, int slavechannel)
static int conf_del (struct zt_pvt *p, struct zt_subchannel *c, int index)
static int destroy_channel (struct zt_pvt *prev, struct zt_pvt *cur, int now)
static void destroy_zt_pvt (struct zt_pvt **pvt)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct zt_pvt *p)
static void * do_monitor (void *data)
static void enable_dtmf_detect (struct zt_pvt *p)
static char * event2str (int event)
static void fill_rxgain (struct zt_gains *g, float gain, int law)
static void fill_txgain (struct zt_gains *g, float gain, int law)
static struct zt_pvtfind_channel (int channel)
static int get_alarms (struct zt_pvt *p)
static int handle_init_event (struct zt_pvt *i, int event)
static int handle_zap_show_cadences (int fd, int argc, char *argv[])
static int has_voicemail (struct zt_pvt *p)
static int isourconf (struct zt_pvt *p, struct zt_subchannel *c)
static int isslavenative (struct zt_pvt *p, struct zt_pvt **out)
static int load_module (void)
static struct zt_pvtmkintf (int channel, struct zt_chan_conf conf, struct zt_pri *pri, int reloading)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static int my_zt_write (struct zt_pvt *p, unsigned char *buf, int len, int index, int linear)
static int process_zap (struct zt_chan_conf *confp, struct ast_variable *v, int reload, int skipchannels)
static int reload (void)
static int reset_conf (struct zt_pvt *p)
static int restart_monitor (void)
static int restore_conference (struct zt_pvt *p)
static int restore_gains (struct zt_pvt *p)
static int save_conference (struct zt_pvt *p)
static int send_callerid (struct zt_pvt *p)
static int send_cwcidspill (struct zt_pvt *p)
static int set_actual_gain (int fd, int chan, float rxgain, float txgain, int law)
static int set_actual_rxgain (int fd, int chan, float gain, int law)
static int set_actual_txgain (int fd, int chan, float gain, int law)
static int setup_zap (int reload)
static void * ss_thread (void *data)
static void swap_subs (struct zt_pvt *p, int a, int b)
static int unalloc_sub (struct zt_pvt *p, int x)
static int unload_module (void)
static int update_conf (struct zt_pvt *p)
static void wakeup_sub (struct zt_pvt *p, int a, void *pri)
static int zap_destroy_channel (int fd, int argc, char **argv)
static int zap_destroy_channel_bynum (int channel)
static int zap_fake_event (struct zt_pvt *p, int mode)
static void zap_queue_frame (struct zt_pvt *p, struct ast_frame *f, void *pri)
static int zap_restart (void)
static int zap_restart_cmd (int fd, int argc, char **argv)
static int zap_show_channel (int fd, int argc, char **argv)
static int zap_show_channels (int fd, int argc, char **argv)
static int zap_show_status (int fd, int argc, char *argv[])
static char * zap_sig2str (int sig)
static int zt_answer (struct ast_channel *ast)
static enum
ast_bridge_result 
zt_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int zt_call (struct ast_channel *ast, char *rdest, int timeout)
static int zt_callwait (struct ast_channel *ast)
static struct
zt_chan_conf 
zt_chan_conf_default (void)
static void zt_close (int fd)
static int zt_confmute (struct zt_pvt *p, int muted)
static int zt_digit_begin (struct ast_channel *ast, char digit)
static int zt_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void zt_disable_ec (struct zt_pvt *p)
static void zt_enable_ec (struct zt_pvt *p)
static struct ast_framezt_exception (struct ast_channel *ast)
static int zt_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int zt_func_read (struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
static int zt_get_event (int fd)
 Avoid the silly zt_getevent which ignores a bunch of events.
static int zt_get_index (struct ast_channel *ast, struct zt_pvt *p, int nullok)
static void zt_handle_dtmfup (struct ast_channel *ast, int index, struct ast_frame **dest)
static struct ast_framezt_handle_event (struct ast_channel *ast)
static int zt_hangup (struct ast_channel *ast)
static int zt_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void zt_link (struct zt_pvt *slave, struct zt_pvt *master)
static struct
ast_channel
zt_new (struct zt_pvt *, int, int, int, int, int)
static int zt_open (char *fn)
static struct ast_framezt_read (struct ast_channel *ast)
static struct
ast_channel
zt_request (const char *type, int format, void *data, int *cause)
static int zt_ring_phone (struct zt_pvt *p)
static int zt_sendtext (struct ast_channel *c, const char *text)
static int zt_set_hook (int fd, int hs)
static int zt_setlinear (int zfd, int linear)
static int zt_setoption (struct ast_channel *chan, int option, void *data, int datalen)
static void zt_train_ec (struct zt_pvt *p)
static void zt_unlink (struct zt_pvt *slave, struct zt_pvt *master, int needlock)
static int zt_wait_event (int fd)
 Avoid the silly zt_waitevent which ignores a bunch of events.
static int zt_wink (struct zt_pvt *p, int index)
static int zt_write (struct ast_channel *ast, struct ast_frame *frame)

Variables

struct {
   int   alarm
   char *   name
alarms []
static struct
zt_ring_cadence 
cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "zapata.conf"
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static char destroy_channel_usage []
static int distinctiveringaftercid = 0
static struct
zt_distRings 
drings
static char * events []
static int firstdigittimeout = 16000
 Wait up to 16 seconds for first digit (FXO logic).
static int gendigittimeout = 8000
 How long to wait for following digits (FXO logic).
static struct ast_jb_conf global_jbconf
static int ifcount = 0
static struct zt_pvtifend
static struct zt_pvtiflist
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static int num_cadence = 4
static int numbufs = 4
static char progzone [10] = ""
static int ringt_base = DEFAULT_RINGT
struct zt_pvtround_robin [32]
static char show_channel_usage []
static char show_channels_usage []
static char * subnames []
static const char tdesc [] = "Zapata Telephony Driver"
static int user_has_defined_cadences = 0
static struct
ast_cli_entry 
zap_cli []
static char zap_restart_usage []
static char zap_show_cadences_help []
static char zap_show_status_usage []
static struct
ast_channel_tech 
zap_tech


Detailed Description

Zaptel Pseudo TDM interface.

Author:
Mark Spencer <markster@digium.com>
Connects to the zaptel telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.

You need to install libraries before you attempt to compile and install the zaptel channel.

See also
Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_zap.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by zt_sendtext().

#define AST_LAW (  )     (((p)->law == ZT_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)

Definition at line 154 of file chan_zap.c.

Referenced by do_monitor(), send_cwcidspill(), ss_thread(), zt_call(), zt_callwait(), and zt_sendtext().

#define CALLWAITING_REPEAT_SAMPLES   ( (10000 * 8) / READ_SIZE)

300 ms

Definition at line 283 of file chan_zap.c.

Referenced by zt_callwait().

#define CALLWAITING_SILENT_SAMPLES   ( (300 * 8) / READ_SIZE)

300 ms

Definition at line 282 of file chan_zap.c.

#define CANBUSYDETECT (  )     (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)

Definition at line 760 of file chan_zap.c.

Referenced by zt_new().

#define CANPROGRESSDETECT (  )     (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)

Definition at line 761 of file chan_zap.c.

Referenced by zt_handle_event(), and zt_new().

#define CHAN_PSEUDO   -2

Definition at line 196 of file chan_zap.c.

Referenced by build_channels(), enable_dtmf_detect(), mkintf(), process_zap(), zt_new(), and zt_request().

#define CHANNEL_PSEUDO   -12

Definition at line 152 of file chan_zap.c.

#define CIDCW_EXPIRE_SAMPLES   ( (500 * 8) / READ_SIZE)

500 ms

Definition at line 284 of file chan_zap.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 406 of file chan_zap.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 407 of file chan_zap.c.

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 202 of file chan_zap.c.

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 199 of file chan_zap.c.

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 198 of file chan_zap.c.

#define DCHAN_UP   (1 << 2)

Definition at line 200 of file chan_zap.c.

#define DEFAULT_CIDRINGS   1

Typically, how many rings before we should send Caller*ID.

Note:
Define ZHONE_HACK to cause us to go off hook and then back on hook when the user hangs up to reset the state machine so ring works properly. This is used to be able to support kewlstart by putting the zhone in groundstart mode since their forward disconnect supervision is entirely broken even though their documentation says it isn't and their support is entirely unwilling to provide any assistance with their channel banks even though their web site says they support their products for life.

Define if you want to check the hook state for an FXO (FXS signalled) interface before dialing on it. Certain FXO interfaces always think they're out of service with this method however.

Definition at line 150 of file chan_zap.c.

Referenced by zt_chan_conf_default().

#define DEFAULT_RINGT   ( (8000 * 8) / READ_SIZE)

Definition at line 286 of file chan_zap.c.

#define END_SILENCE_LEN   400

Referenced by zt_sendtext().

#define FORMAT   "%-40.40s %-10.10s %-10d %-10d %-10d\n"

#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"

#define FORMAT2   "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"

#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"

#define GET_CHANNEL (  )     ((p)->channel)

Definition at line 710 of file chan_zap.c.

Referenced by update_conf().

#define HANGUP   1

Definition at line 10126 of file chan_zap.c.

Referenced by action_transferhangup(), and zap_fake_event().

#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)

Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_information(), build_notify(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_status(), build_status_enquiry(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_timeout(), build_user_information(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_information(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), parse_setup_acknowledge(), parse_status(), and zt_sendtext().

#define HEADER_MS   50

Referenced by zt_sendtext().

#define ISTRUNK (  ) 

Value:

((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
         (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))

Definition at line 757 of file chan_zap.c.

Referenced by ss_thread(), and zt_indicate().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 279 of file chan_zap.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 280 of file chan_zap.c.

#define MAX_CHANLIST_LEN   80

The length of the parameters list of 'zapchan'.

Todo:
Move definition of MAX_CHANLIST_LEN to a proper place.

Definition at line 10480 of file chan_zap.c.

Referenced by process_zap().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 194 of file chan_zap.c.

Referenced by mkintf().

#define MAX_SLAVES   4

Definition at line 409 of file chan_zap.c.

Referenced by isslavenative(), update_conf(), zap_show_channel(), zt_link(), and zt_unlink().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

Definition at line 285 of file chan_zap.c.

Referenced by zt_handle_event().

#define NEED_MFDETECT (  )     (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))

Signaling types that need to use MF detection should be placed in this macro.

Definition at line 157 of file chan_zap.c.

Referenced by ss_thread(), and zt_new().

#define NUM_CADENCE_MAX   25

Definition at line 735 of file chan_zap.c.

Referenced by process_zap().

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 193 of file chan_zap.c.

#define NUM_SPANS   32

Definition at line 192 of file chan_zap.c.

#define POLARITY_IDLE   0

Definition at line 364 of file chan_zap.c.

Referenced by unalloc_sub(), zt_handle_event(), and zt_hangup().

#define POLARITY_REV   1

Definition at line 365 of file chan_zap.c.

Referenced by handle_init_event(), and zt_handle_event().

#define READ_SIZE   160

Chunk size to read -- we use 20ms chunks to make things happy.

Definition at line 277 of file chan_zap.c.

Referenced by my_zt_write(), process_zap(), send_cwcidspill(), zt_callwait(), zt_open(), zt_read(), zt_sendtext(), and zt_setoption().

#define sig2str   zap_sig2str

Definition at line 1219 of file chan_zap.c.

Referenced by action_zapshowchannels(), build_channels(), handle_init_event(), mkintf(), ss_thread(), zap_show_channel(), and zt_handle_event().

#define SIG_E911   (0x1000000 | ZT_SIG_EM)

Definition at line 172 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_EM   ZT_SIG_EM

Definition at line 167 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_EM_E1   ZT_SIG_EM_E1

Definition at line 188 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_EMWINK   (0x0100000 | ZT_SIG_EM)

Definition at line 168 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_FEATB   (0x0800000 | ZT_SIG_EM)

Definition at line 171 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_FEATD   (0x0200000 | ZT_SIG_EM)

Definition at line 169 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_FEATDMF   (0x0400000 | ZT_SIG_EM)

Definition at line 170 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_FEATDMF_TA   (0x2000000 | ZT_SIG_EM)

Definition at line 173 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_FGC_CAMA   (0x4000000 | ZT_SIG_EM)

Definition at line 174 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_FGC_CAMAMF   (0x8000000 | ZT_SIG_EM)

Definition at line 175 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_FXOGS   ZT_SIG_FXOGS

Definition at line 180 of file chan_zap.c.

Referenced by available(), handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), zt_handle_event(), zt_hangup(), and zt_new().

#define SIG_FXOKS   ZT_SIG_FXOKS

Definition at line 181 of file chan_zap.c.

Referenced by available(), handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), zt_handle_event(), zt_hangup(), and zt_new().

#define SIG_FXOLS   ZT_SIG_FXOLS

Definition at line 179 of file chan_zap.c.

Referenced by available(), handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), zt_handle_event(), zt_hangup(), and zt_new().

#define SIG_FXSGS   ZT_SIG_FXSGS

Definition at line 177 of file chan_zap.c.

Referenced by available(), handle_init_event(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), zt_handle_event(), zt_hangup(), and zt_indicate().

#define SIG_FXSKS   ZT_SIG_FXSKS

Definition at line 178 of file chan_zap.c.

Referenced by available(), handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), zt_handle_event(), zt_hangup(), zt_indicate(), zt_new(), and zt_request().

#define SIG_FXSLS   ZT_SIG_FXSLS

Definition at line 176 of file chan_zap.c.

Referenced by available(), handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), zt_handle_event(), zt_hangup(), and zt_indicate().

#define SIG_GR303FXOKS   (0x0100000 | ZT_SIG_FXOKS)

Definition at line 189 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), and zap_sig2str().

#define SIG_GR303FXSKS   (0x0100000 | ZT_SIG_FXSKS)

Definition at line 190 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), and zap_sig2str().

#define SIG_PRI   ZT_SIG_CLEAR

Definition at line 182 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), zt_confmute(), zt_digit_begin(), zt_digit_end(), zt_enable_ec(), zt_handle_event(), zt_hangup(), zt_indicate(), zt_new(), zt_read(), and zt_write().

#define SIG_SF   ZT_SIG_SF

Definition at line 183 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_SF_FEATB   (0x0800000 | ZT_SIG_SF)

Definition at line 187 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_SF_FEATD   (0x0200000 | ZT_SIG_SF)

Definition at line 185 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_SF_FEATDMF   (0x0400000 | ZT_SIG_SF)

Definition at line 186 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SIG_SFWINK   (0x0100000 | ZT_SIG_SF)

Definition at line 184 of file chan_zap.c.

Referenced by handle_init_event(), mkintf(), process_zap(), ss_thread(), zap_sig2str(), zt_answer(), zt_call(), and zt_handle_event().

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 106 of file chan_zap.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 360 of file chan_zap.c.

#define SUB_REAL   0

Active call

Definition at line 359 of file chan_zap.c.

#define SUB_THREEWAY   2

Three-way call

Definition at line 361 of file chan_zap.c.

#define tdesc   "Zapata Telephony"

Definition at line 11446 of file chan_zap.c.

#define TRAILER_MS   5

Referenced by zt_sendtext().

#define TRANSFER   0

Definition at line 10125 of file chan_zap.c.

Referenced by action_transfer(), and zap_fake_event().

#define ZT_EVENT_DTMFDOWN   0

Definition at line 124 of file chan_zap.c.

Referenced by zt_handle_event().

#define ZT_EVENT_DTMFUP   0

Definition at line 125 of file chan_zap.c.

Referenced by zt_handle_event().


Function Documentation

static int __unload_module ( void   )  [static]

Definition at line 10307 of file chan_zap.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), ast_verbose(), zt_pvt::cidspill, destroy_zt_pvt(), free, iflist, master, zt_pvt::next, zt_pvt::owner, SUB_REAL, zt_pvt::subs, VERBOSE_PREFIX_3, zt_subchannel::zfd, and zt_close().

10308 {
10309    int x = 0;
10310    struct zt_pvt *p, *pl;
10311 #ifdef HAVE_PRI
10312    int i;
10313    for (i = 0; i < NUM_SPANS; i++) {
10314       if (pris[i].master != AST_PTHREADT_NULL) 
10315          pthread_cancel(pris[i].master);
10316    }
10317    ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
10318    ast_unregister_application(zap_send_keypad_facility_app);
10319 #endif
10320    ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
10321    ast_manager_unregister( "ZapDialOffhook" );
10322    ast_manager_unregister( "ZapHangup" );
10323    ast_manager_unregister( "ZapTransfer" );
10324    ast_manager_unregister( "ZapDNDoff" );
10325    ast_manager_unregister( "ZapDNDon" );
10326    ast_manager_unregister("ZapShowChannels");
10327    ast_manager_unregister("ZapRestart");
10328    ast_channel_unregister(&zap_tech);
10329    ast_mutex_lock(&iflock);
10330    /* Hangup all interfaces if they have an owner */
10331    p = iflist;
10332    while (p) {
10333       if (p->owner)
10334          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10335       p = p->next;
10336    }
10337    ast_mutex_unlock(&iflock);
10338    ast_mutex_lock(&monlock);
10339    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10340       pthread_cancel(monitor_thread);
10341       pthread_kill(monitor_thread, SIGURG);
10342       pthread_join(monitor_thread, NULL);
10343    }
10344    monitor_thread = AST_PTHREADT_STOP;
10345    ast_mutex_unlock(&monlock);
10346 
10347    ast_mutex_lock(&iflock);
10348    /* Destroy all the interfaces and free their memory */
10349    p = iflist;
10350    while (p) {
10351       /* Free any callerid */
10352       if (p->cidspill)
10353          free(p->cidspill);
10354       /* Close the zapata thingy */
10355       if (p->subs[SUB_REAL].zfd > -1)
10356          zt_close(p->subs[SUB_REAL].zfd);
10357       pl = p;
10358       p = p->next;
10359       x++;
10360       /* Free associated memory */
10361       if (pl)
10362          destroy_zt_pvt(&pl);
10363       ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10364    }
10365    iflist = NULL;
10366    ifcount = 0;
10367    ast_mutex_unlock(&iflock);
10368 #ifdef HAVE_PRI      
10369    for (i = 0; i < NUM_SPANS; i++) {
10370       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10371          pthread_join(pris[i].master, NULL);
10372       zt_close(pris[i].fds[i]);
10373    }
10374 #endif
10375    return 0;
10376 }

static struct ast_frame* __zt_exception ( struct ast_channel ast  )  [static, read]

Definition at line 4486 of file chan_zap.c.

References ast_channel::_state, ast_bridged_channel(), AST_CONTROL_UNHOLD, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_verbose(), zt_pvt::callwaitingrepeat, zt_pvt::channel, zt_pvt::cidcwexpire, ast_frame::data, ast_frame::datalen, ast_frame::delivery, zt_pvt::dialing, event2str(), zt_subchannel::f, zt_pvt::fake_event, ast_channel::fds, zt_pvt::flashtime, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, zt_subchannel::needanswer, zt_subchannel::needunhold, ast_frame::offset, zt_pvt::oprmode, option_debug, option_verbose, zt_subchannel::owner, zt_pvt::owner, zt_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, zt_pvt::subs, ast_channel::tech_pvt, update_conf(), VERBOSE_PREFIX_3, zt_subchannel::zfd, zt_disable_ec(), zt_get_event(), zt_get_index(), zt_handle_event(), zt_ring_phone(), and zt_set_hook().

Referenced by zt_exception(), and zt_read().

04487 {
04488    struct zt_pvt *p = ast->tech_pvt;
04489    int res;
04490    int usedindex=-1;
04491    int index;
04492    struct ast_frame *f;
04493 
04494 
04495    index = zt_get_index(ast, p, 1);
04496    
04497    p->subs[index].f.frametype = AST_FRAME_NULL;
04498    p->subs[index].f.datalen = 0;
04499    p->subs[index].f.samples = 0;
04500    p->subs[index].f.mallocd = 0;
04501    p->subs[index].f.offset = 0;
04502    p->subs[index].f.subclass = 0;
04503    p->subs[index].f.delivery = ast_tv(0,0);
04504    p->subs[index].f.src = "zt_exception";
04505    p->subs[index].f.data = NULL;
04506    
04507    
04508    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04509       /* If nobody owns us, absorb the event appropriately, otherwise
04510          we loop indefinitely.  This occurs when, during call waiting, the
04511          other end hangs up our channel so that it no longer exists, but we
04512          have neither FLASH'd nor ONHOOK'd to signify our desire to
04513          change to the other channel. */
04514       if (p->fake_event) {
04515          res = p->fake_event;
04516          p->fake_event = 0;
04517       } else
04518          res = zt_get_event(p->subs[SUB_REAL].zfd);
04519       /* Switch to real if there is one and this isn't something really silly... */
04520       if ((res != ZT_EVENT_RINGEROFF) && (res != ZT_EVENT_RINGERON) &&
04521          (res != ZT_EVENT_HOOKCOMPLETE)) {
04522          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04523          p->owner = p->subs[SUB_REAL].owner;
04524          if (p->owner && ast_bridged_channel(p->owner))
04525             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04526          p->subs[SUB_REAL].needunhold = 1;
04527       }
04528       switch (res) {
04529       case ZT_EVENT_ONHOOK:
04530          zt_disable_ec(p);
04531          if (p->owner) {
04532             if (option_verbose > 2) 
04533                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
04534             zt_ring_phone(p);
04535             p->callwaitingrepeat = 0;
04536             p->cidcwexpire = 0;
04537          } else
04538             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04539          update_conf(p);
04540          break;
04541       case ZT_EVENT_RINGOFFHOOK:
04542          zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
04543          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
04544             p->subs[SUB_REAL].needanswer = 1;
04545             p->dialing = 0;
04546          }
04547          break;
04548       case ZT_EVENT_HOOKCOMPLETE:
04549       case ZT_EVENT_RINGERON:
04550       case ZT_EVENT_RINGEROFF:
04551          /* Do nothing */
04552          break;
04553       case ZT_EVENT_WINKFLASH:
04554          gettimeofday(&p->flashtime, NULL);
04555          if (p->owner) {
04556             if (option_verbose > 2) 
04557                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
04558             if (p->owner->_state != AST_STATE_UP) {
04559                /* Answer if necessary */
04560                usedindex = zt_get_index(p->owner, p, 0);
04561                if (usedindex > -1) {
04562                   p->subs[usedindex].needanswer = 1;
04563                }
04564                ast_setstate(p->owner, AST_STATE_UP);
04565             }
04566             p->callwaitingrepeat = 0;
04567             p->cidcwexpire = 0;
04568             if (ast_bridged_channel(p->owner))
04569                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04570             p->subs[SUB_REAL].needunhold = 1;
04571          } else
04572             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04573          update_conf(p);
04574          break;
04575       default:
04576          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
04577       }
04578       f = &p->subs[index].f;
04579       return f;
04580    }
04581    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
04582       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
04583    /* If it's not us, return NULL immediately */
04584    if (ast != p->owner) {
04585       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
04586       f = &p->subs[index].f;
04587       return f;
04588    }
04589    f = zt_handle_event(ast);
04590    return f;
04591 }

static int action_transfer ( struct mansession s,
const struct message m 
) [static]

Definition at line 10194 of file chan_zap.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), find_channel(), TRANSFER, and zap_fake_event().

Referenced by load_module().

10195 {
10196    struct zt_pvt *p = NULL;
10197    const char *channel = astman_get_header(m, "ZapChannel");
10198 
10199    if (ast_strlen_zero(channel)) {
10200       astman_send_error(s, m, "No channel specified");
10201       return 0;
10202    }
10203    p = find_channel(atoi(channel));
10204    if (!p) {
10205       astman_send_error(s, m, "No such channel");
10206       return 0;
10207    }
10208    zap_fake_event(p,TRANSFER);
10209    astman_send_ack(s, m, "ZapTransfer");
10210    return 0;
10211 }

static int action_transferhangup ( struct mansession s,
const struct message m 
) [static]

Definition at line 10213 of file chan_zap.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), find_channel(), HANGUP, and zap_fake_event().

Referenced by load_module().

10214 {
10215    struct zt_pvt *p = NULL;
10216    const char *channel = astman_get_header(m, "ZapChannel");
10217 
10218    if (ast_strlen_zero(channel)) {
10219       astman_send_error(s, m, "No channel specified");
10220       return 0;
10221    }
10222    p = find_channel(atoi(channel));
10223    if (!p) {
10224       astman_send_error(s, m, "No such channel");
10225       return 0;
10226    }
10227    zap_fake_event(p,HANGUP);
10228    astman_send_ack(s, m, "ZapHangup");
10229    return 0;
10230 }

static int action_zapdialoffhook ( struct mansession s,
const struct message m 
) [static]

Definition at line 10232 of file chan_zap.c.

References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), find_channel(), zt_pvt::owner, and zap_queue_frame().

Referenced by load_module().

10233 {
10234    struct zt_pvt *p = NULL;
10235    const char *channel = astman_get_header(m, "ZapChannel");
10236    const char *number = astman_get_header(m, "Number");
10237    int i;
10238 
10239    if (ast_strlen_zero(channel)) {
10240       astman_send_error(s, m, "No channel specified");
10241       return 0;
10242    }
10243    if (ast_strlen_zero(number)) {
10244       astman_send_error(s, m, "No number specified");
10245       return 0;
10246    }
10247    p = find_channel(atoi(channel));
10248    if (!p) {
10249       astman_send_error(s, m, "No such channel");
10250       return 0;
10251    }
10252    if (!p->owner) {
10253       astman_send_error(s, m, "Channel does not have it's owner");
10254       return 0;
10255    }
10256    for (i = 0; i < strlen(number); i++) {
10257       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10258       zap_queue_frame(p, &f, NULL); 
10259    }
10260    astman_send_ack(s, m, "ZapDialOffhook");
10261    return 0;
10262 }

static int action_zapdndoff ( struct mansession s,
const struct message m 
) [static]

Definition at line 10175 of file chan_zap.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), zt_pvt::dnd, and find_channel().

Referenced by load_module().

10176 {
10177    struct zt_pvt *p = NULL;
10178    const char *channel = astman_get_header(m, "ZapChannel");
10179 
10180    if (ast_strlen_zero(channel)) {
10181       astman_send_error(s, m, "No channel specified");
10182       return 0;
10183    }
10184    p = find_channel(atoi(channel));
10185    if (!p) {
10186       astman_send_error(s, m, "No such channel");
10187       return 0;
10188    }
10189    p->dnd = 0;
10190    astman_send_ack(s, m, "DND Disabled");
10191    return 0;
10192 }

static int action_zapdndon ( struct mansession s,
const struct message m 
) [static]

Definition at line 10156 of file chan_zap.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), zt_pvt::dnd, and find_channel().

Referenced by load_module().

10157 {
10158    struct zt_pvt *p = NULL;
10159    const char *channel = astman_get_header(m, "ZapChannel");
10160 
10161    if (ast_strlen_zero(channel)) {
10162       astman_send_error(s, m, "No channel specified");
10163       return 0;
10164    }
10165    p = find_channel(atoi(channel));
10166    if (!p) {
10167       astman_send_error(s, m, "No such channel");
10168       return 0;
10169    }
10170    p->dnd = 1;
10171    astman_send_ack(s, m, "DND Enabled");
10172    return 0;
10173 }

static int action_zaprestart ( struct mansession s,
const struct message m 
) [static]

Definition at line 9783 of file chan_zap.c.

References astman_send_ack(), astman_send_error(), and zap_restart().

Referenced by load_module().

09784 {
09785    if (zap_restart() != 0) {
09786       astman_send_error(s, m, "Failed rereading zaptel configuration");
09787       return 1;
09788    }
09789    astman_send_ack(s, m, "ZapRestart: Success");
09790    return 0;
09791 }

static int action_zapshowchannels ( struct mansession s,
const struct message m 
) [static]

Definition at line 10264 of file chan_zap.c.

References alarm, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), zt_pvt::channel, zt_pvt::context, zt_pvt::dnd, get_alarms(), iflist, zt_pvt::next, zt_pvt::sig, and sig2str.

Referenced by load_module().

10265 {
10266    struct zt_pvt *tmp = NULL;
10267    const char *id = astman_get_header(m, "ActionID");
10268    char idText[256] = "";
10269 
10270    astman_send_ack(s, m, "Zapata channel status will follow");
10271    if (!ast_strlen_zero(id))
10272       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10273 
10274    ast_mutex_lock(&iflock);
10275    
10276    tmp = iflist;
10277    while (tmp) {
10278       if (tmp->channel > 0) {
10279          int alarm = get_alarms(tmp);
10280          astman_append(s,
10281             "Event: ZapShowChannels\r\n"
10282             "Channel: %d\r\n"
10283             "Signalling: %s\r\n"
10284             "Context: %s\r\n"
10285             "DND: %s\r\n"
10286             "Alarm: %s\r\n"
10287             "%s"
10288             "\r\n",
10289             tmp->channel, sig2str(tmp->sig), tmp->context, 
10290             tmp->dnd ? "Enabled" : "Disabled",
10291             alarm2str(alarm), idText);
10292       } 
10293 
10294       tmp = tmp->next;
10295    }
10296 
10297    ast_mutex_unlock(&iflock);
10298    
10299    astman_append(s, 
10300       "Event: ZapShowChannelsComplete\r\n"
10301       "%s"
10302       "\r\n", 
10303       idText);
10304    return 0;
10305 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1130 of file chan_zap.c.

References alarms.

Referenced by action_zapshowchannels(), handle_init_event(), and zt_handle_event().

01131 {
01132    int x;
01133    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01134       if (alarms[x].alarm & alarm)
01135          return alarms[x].name;
01136    }
01137    return alarm ? "Unknown Alarm" : "No Alarm";
01138 }

static int alloc_sub ( struct zt_pvt p,
int  x 
) [static]

Definition at line 928 of file chan_zap.c.

References ast_log(), zt_subchannel::chan, zt_pvt::channel, LOG_DEBUG, LOG_WARNING, option_debug, zt_pvt::subs, zt_subchannel::zfd, zt_close(), and zt_open().

Referenced by ss_thread(), zt_handle_event(), and zt_request().

00929 {
00930    ZT_BUFFERINFO bi;
00931    int res;
00932    if (p->subs[x].zfd < 0) {
00933       p->subs[x].zfd = zt_open("/dev/zap/pseudo");
00934       if (p->subs[x].zfd > -1) {
00935          res = ioctl(p->subs[x].zfd, ZT_GET_BUFINFO, &bi);
00936          if (!res) {
00937             bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
00938             bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
00939             bi.numbufs = numbufs;
00940             res = ioctl(p->subs[x].zfd, ZT_SET_BUFINFO, &bi);
00941             if (res < 0) {
00942                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", x);
00943             }
00944          } else 
00945             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", x);
00946          if (ioctl(p->subs[x].zfd, ZT_CHANNO, &p->subs[x].chan) == 1) {
00947             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d\n", p->subs[x].zfd);
00948             zt_close(p->subs[x].zfd);
00949             p->subs[x].zfd = -1;
00950             return -1;
00951          }
00952          if (option_debug)
00953             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
00954          return 0;
00955       } else
00956          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
00957       return -1;
00958    }
00959    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
00960    return -1;
00961 }

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
tdesc  ,
load = load_module,
unload = unload_module,
reload = reload 
)

AST_MUTEX_DEFINE_STATIC ( monlock   ) 

Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.

AST_MUTEX_DEFINE_STATIC ( iflock   ) 

Protect the interface list (of zt_pvt's).

static int attempt_transfer ( struct zt_pvt p  )  [static]

Definition at line 3483 of file chan_zap.c.

References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_cdr_append(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_indicate(), ast_log(), ast_mutex_unlock(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, ast_channel::cdr, ast_channel::lock, LOG_DEBUG, LOG_WARNING, zt_subchannel::owner, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, swap_subs(), unalloc_sub(), and zt_subchannel::zfd.

03484 {
03485    /* In order to transfer, we need at least one of the channels to
03486       actually be in a call bridge.  We can't conference two applications
03487       together (but then, why would we want to?) */
03488    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03489       /* The three-way person we're about to transfer to could still be in MOH, so
03490          stop if now if appropriate */
03491       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03492          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03493       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03494          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03495       }
03496       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03497          tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, ZT_TONE_RINGTONE);
03498       }
03499       if (p->subs[SUB_REAL].owner->cdr) {
03500          /* Move CDR from second channel to current one */
03501          p->subs[SUB_THREEWAY].owner->cdr =
03502             ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr);
03503          p->subs[SUB_REAL].owner->cdr = NULL;
03504       }
03505       if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) {
03506          /* Move CDR from second channel's bridge to current one */
03507          p->subs[SUB_THREEWAY].owner->cdr =
03508             ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr);
03509          ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL;
03510       }
03511        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03512          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03513                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03514          return -1;
03515       }
03516       /* Orphan the channel after releasing the lock */
03517       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03518       unalloc_sub(p, SUB_THREEWAY);
03519    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03520       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03521       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03522          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03523       }
03524       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03525          tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
03526       }
03527       if (p->subs[SUB_THREEWAY].owner->cdr) {
03528          /* Move CDR from second channel to current one */
03529          p->subs[SUB_REAL].owner->cdr = 
03530             ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr);
03531          p->subs[SUB_THREEWAY].owner->cdr = NULL;
03532       }
03533       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) {
03534          /* Move CDR from second channel's bridge to current one */
03535          p->subs[SUB_REAL].owner->cdr = 
03536             ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr);
03537          ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL;
03538       }
03539       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03540          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03541                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03542          return -1;
03543       }
03544       /* Three-way is now the REAL */
03545       swap_subs(p, SUB_THREEWAY, SUB_REAL);
03546       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03547       unalloc_sub(p, SUB_THREEWAY);
03548       /* Tell the caller not to hangup */
03549       return 1;
03550    } else {
03551       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03552                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03553       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03554       return -1;
03555    }
03556    return 0;
03557 }

static int available ( struct zt_pvt p,
int  channelmatch,
int  groupmatch,
int *  busy,
int *  channelmatched,
int *  groupmatched 
) [inline, static]

Definition at line 7551 of file chan_zap.c.

References ast_channel::_state, ast_log(), AST_STATE_RINGING, AST_STATE_UP, zt_pvt::callwaiting, zt_pvt::channel, zt_pvt::dnd, zt_pvt::group, zt_pvt::guardtime, zt_subchannel::inthreeway, LOG_DEBUG, LOG_WARNING, zt_pvt::oprmode, zt_pvt::outgoing, zt_subchannel::owner, zt_pvt::owner, zt_pvt::radio, zt_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by zt_request().

07552 {
07553    int res;
07554    ZT_PARAMS par;
07555 
07556    /* First, check group matching */
07557    if (groupmatch) {
07558       if ((p->group & groupmatch) != groupmatch)
07559          return 0;
07560       *groupmatched = 1;
07561    }
07562    /* Check to see if we have a channel match */
07563    if (channelmatch != -1) {
07564       if (p->channel != channelmatch)
07565          return 0;
07566       *channelmatched = 1;
07567    }
07568    /* We're at least busy at this point */
07569    if (busy) {
07570       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07571          *busy = 1;
07572    }
07573    /* If do not disturb, definitely not */
07574    if (p->dnd)
07575       return 0;
07576    /* If guard time, definitely not */
07577    if (p->guardtime && (time(NULL) < p->guardtime)) 
07578       return 0;
07579       
07580    /* If no owner definitely available */
07581    if (!p->owner) {
07582 #ifdef HAVE_PRI
07583       /* Trust PRI */
07584       if (p->pri) {
07585          if (p->resetting || p->call)
07586             return 0;
07587          else
07588             return 1;
07589       }
07590 #endif
07591       if (!(p->radio || (p->oprmode < 0)))
07592       {
07593          if (!p->sig || (p->sig == SIG_FXSLS))
07594             return 1;
07595          /* Check hook state */
07596          if (p->subs[SUB_REAL].zfd > -1)
07597             res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
07598          else {
07599             /* Assume not off hook on CVRS */
07600             res = 0;
07601             par.rxisoffhook = 0;
07602          }
07603          if (res) {
07604             ast_log(LOG_WARNING, "Unable to check hook state on channel %d\n", p->channel);
07605          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07606             /* When "onhook" that means no battery on the line, and thus
07607               it is out of service..., if it's on a TDM card... If it's a channel
07608               bank, there is no telling... */
07609             if (par.rxbits > -1)
07610                return 1;
07611             if (par.rxisoffhook)
07612                return 1;
07613             else
07614 #ifdef ZAP_CHECK_HOOKSTATE
07615                return 0;
07616 #else
07617                return 1;
07618 #endif
07619          } else if (par.rxisoffhook) {
07620             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07621             /* Not available when the other end is off hook */
07622             return 0;
07623          }
07624       }
07625       return 1;
07626    }
07627 
07628    /* If it's not an FXO, forget about call wait */
07629    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
07630       return 0;
07631 
07632    if (!p->callwaiting) {
07633       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
07634       return 0;
07635    }
07636 
07637    if (p->subs[SUB_CALLWAIT].zfd > -1) {
07638       /* If there is already a call waiting call, then we can't take a second one */
07639       return 0;
07640    }
07641    
07642    if ((p->owner->_state != AST_STATE_UP) &&
07643        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07644       /* If the current call is not up, then don't allow the call */
07645       return 0;
07646    }
07647    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07648       /* Can't take a call wait when the three way calling hasn't been merged yet. */
07649       return 0;
07650    }
07651    /* We're cool */
07652    return 1;
07653 }

static int build_channels ( struct zt_chan_conf  conf,
int  iscrv,
const char *  value,
int  reload,
int  lineno,
int *  found_pseudo 
) [static]

Definition at line 10388 of file chan_zap.c.

References ast_log(), ast_strdupa, ast_verbose(), zt_chan_conf::chan, CHAN_PSEUDO, LOG_ERROR, LOG_WARNING, mkintf(), option_verbose, zt_pvt::sig, sig2str, strsep(), and VERBOSE_PREFIX_3.

Referenced by process_zap().

10389 {
10390    char *c, *chan;
10391    int x, start, finish;
10392    struct zt_pvt *tmp;
10393 #ifdef HAVE_PRI
10394    struct zt_pri *pri;
10395    int trunkgroup, y;
10396 #endif
10397    
10398    if ((reload == 0) && (conf.chan.sig < 0)) {
10399       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10400       return -1;
10401    }
10402 
10403    c = ast_strdupa(value);
10404 
10405 #ifdef HAVE_PRI
10406    pri = NULL;
10407    if (iscrv) {
10408       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10409          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10410          return -1;
10411       }
10412       if (trunkgroup < 1) {
10413          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10414          return -1;
10415       }
10416       c += y;
10417       for (y = 0; y < NUM_SPANS; y++) {
10418          if (pris[y].trunkgroup == trunkgroup) {
10419             pri = pris + y;
10420             break;
10421          }
10422       }
10423       if (!pri) {
10424          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10425          return -1;
10426       }
10427    }
10428 #endif         
10429 
10430    while ((chan = strsep(&c, ","))) {
10431       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10432          /* Range */
10433       } else if (sscanf(chan, "%d", &start)) {
10434          /* Just one */
10435          finish = start;
10436       } else if (!strcasecmp(chan, "pseudo")) {
10437          finish = start = CHAN_PSEUDO;
10438          if (found_pseudo)
10439             *found_pseudo = 1;
10440       } else {
10441          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10442          return -1;
10443       }
10444       if (finish < start) {
10445          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10446          x = finish;
10447          finish = start;
10448          start = x;
10449       }
10450 
10451       for (x = start; x <= finish; x++) {
10452 #ifdef HAVE_PRI
10453          tmp = mkintf(x, conf, pri, reload);
10454 #else       
10455          tmp = mkintf(x, conf, NULL, reload);
10456 #endif         
10457 
10458          if (tmp) {
10459             if (option_verbose > 2) {
10460 #ifdef HAVE_PRI
10461                if (pri)
10462                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10463                else
10464 #endif
10465                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10466             }
10467          } else {
10468             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10469                (reload == 1) ? "reconfigure" : "register", value);
10470             return -1;
10471          }
10472       }
10473    }
10474 
10475    return 0;
10476 }

static int bump_gains ( struct zt_pvt p  )  [static]

Definition at line 1581 of file chan_zap.c.

References ast_log(), zt_pvt::law, LOG_WARNING, zt_pvt::rxgain, set_actual_gain(), SUB_REAL, zt_pvt::subs, zt_pvt::txgain, and zt_subchannel::zfd.

Referenced by ss_thread().

01582 {
01583    int res;
01584 
01585    /* Bump receive gain by 5.0db */
01586    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01587    if (res) {
01588       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01589       return -1;
01590    }
01591 
01592    return 0;
01593 }

static struct zt_pvt* chandup ( struct zt_pvt src  )  [static, read]

Definition at line 7655 of file chan_zap.c.

References ast_log(), ast_malloc, ast_mutex_init(), zt_pvt::destroy, destroy_zt_pvt(), iflist, zt_pvt::lock, LOG_ERROR, LOG_WARNING, zt_pvt::next, SUB_REAL, zt_pvt::subs, zt_subchannel::zfd, and zt_open().

Referenced by zt_request().

07656 {
07657    struct zt_pvt *p;
07658    ZT_BUFFERINFO bi;
07659    int res;
07660    
07661    if ((p = ast_malloc(sizeof(*p)))) {
07662       memcpy(p, src, sizeof(struct zt_pvt));
07663       ast_mutex_init(&p->lock);
07664       p->subs[SUB_REAL].zfd = zt_open("/dev/zap/pseudo");
07665       /* Allocate a zapata structure */
07666       if (p->subs[SUB_REAL].zfd < 0) {
07667          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
07668          destroy_zt_pvt(&p);
07669          return NULL;
07670       }
07671       res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
07672       if (!res) {
07673          bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
07674          bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
07675          bi.numbufs = numbufs;
07676          res = ioctl(p->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
07677          if (res < 0) {
07678             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel\n");
07679          }
07680       } else
07681          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel\n");
07682    }
07683    p->destroy = 1;
07684    p->next = iflist;
07685    iflist = p;
07686    return p;
07687 }

static int check_for_conference ( struct zt_pvt p  )  [static]

Definition at line 3559 of file chan_zap.c.

References ast_log(), ast_verbose(), zt_pvt::channel, zt_pvt::confno, zt_subchannel::curconf, LOG_WARNING, zt_pvt::master, option_verbose, SUB_REAL, zt_pvt::subs, VERBOSE_PREFIX_3, and zt_subchannel::zfd.

Referenced by zt_handle_event().

03560 {
03561    ZT_CONFINFO ci;
03562    /* Fine if we already have a master, etc */
03563    if (p->master || (p->confno > -1))
03564       return 0;
03565    memset(&ci, 0, sizeof(ci));
03566    if (ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
03567       ast_log(LOG_WARNING, "Failed to get conference info on channel %d\n", p->channel);
03568       return 0;
03569    }
03570    /* If we have no master and don't have a confno, then 
03571       if we're in a conference, it's probably a MeetMe room or
03572       some such, so don't let us 3-way out! */
03573    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03574       if (option_verbose > 2) 
03575          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03576       return 1;
03577    }
03578    return 0;
03579 }

static int conf_add ( struct zt_pvt p,
struct zt_subchannel c,
int  index,
int  slavechannel 
) [static]

Definition at line 1221 of file chan_zap.c.

References ast_log(), zt_pvt::confno, zt_subchannel::curconf, LOG_DEBUG, LOG_WARNING, and zt_subchannel::zfd.

Referenced by update_conf().

01222 {
01223    /* If the conference already exists, and we're already in it
01224       don't bother doing anything */
01225    ZT_CONFINFO zi;
01226    
01227    memset(&zi, 0, sizeof(zi));
01228    zi.chan = 0;
01229 
01230    if (slavechannel > 0) {
01231       /* If we have only one slave, do a digital mon */
01232       zi.confmode = ZT_CONF_DIGITALMON;
01233       zi.confno = slavechannel;
01234    } else {
01235       if (!index) {
01236          /* Real-side and pseudo-side both participate in conference */
01237          zi.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER |
01238             ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
01239       } else
01240          zi.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
01241       zi.confno = p->confno;
01242    }
01243    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01244       return 0;
01245    if (c->zfd < 0)
01246       return 0;
01247    if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
01248       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d\n", c->zfd, zi.confmode, zi.confno);
01249       return -1;
01250    }
01251    if (slavechannel < 1) {
01252       p->confno = zi.confno;
01253    }
01254    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01255    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01256    return 0;
01257 }

static int conf_del ( struct zt_pvt p,
struct zt_subchannel c,
int  index 
) [static]

Definition at line 1270 of file chan_zap.c.

References ast_log(), zt_subchannel::curconf, isourconf(), LOG_DEBUG, LOG_WARNING, and zt_subchannel::zfd.

Referenced by update_conf(), and zt_unlink().

01271 {
01272    ZT_CONFINFO zi;
01273    if (/* Can't delete if there's no zfd */
01274       (c->zfd < 0) ||
01275       /* Don't delete from the conference if it's not our conference */
01276       !isourconf(p, c)
01277       /* Don't delete if we don't think it's conferenced at all (implied) */
01278       ) return 0;
01279    memset(&zi, 0, sizeof(zi));
01280    zi.chan = 0;
01281    zi.confno = 0;
01282    zi.confmode = 0;
01283    if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
01284       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01285       return -1;
01286    }
01287    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01288    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01289    return 0;
01290 }

static int destroy_channel ( struct zt_pvt prev,
struct zt_pvt cur,
int  now 
) [static]

Definition at line 2220 of file chan_zap.c.

References destroy_zt_pvt(), iflist, zt_pvt::next, zt_subchannel::owner, zt_pvt::owner, zt_pvt::prev, SUB_REAL, zt_pvt::subs, zt_subchannel::zfd, and zt_close().

Referenced by zap_destroy_channel_bynum(), zap_restart(), and zt_hangup().

02221 {
02222    int owned = 0;
02223    int i = 0;
02224 
02225    if (!now) {
02226       if (cur->owner) {
02227          owned = 1;
02228       }
02229 
02230       for (i = 0; i < 3; i++) {
02231          if (cur->subs[i].owner) {
02232             owned = 1;
02233          }
02234       }
02235       if (!owned) {
02236          if (prev) {
02237             prev->next = cur->next;
02238             if (prev->next)
02239                prev->next->prev = prev;
02240             else
02241                ifend = prev;
02242          } else {
02243             iflist = cur->next;
02244             if (iflist)
02245                iflist->prev = NULL;
02246             else
02247                ifend = NULL;
02248          }
02249          if (cur->subs[SUB_REAL].zfd > -1) {
02250             zt_close(cur->subs[SUB_REAL].zfd);
02251          }
02252          destroy_zt_pvt(&cur);
02253       }
02254    } else {
02255       if (prev) {
02256          prev->next = cur->next;
02257          if (prev->next)
02258             prev->next->prev = prev;
02259          else
02260             ifend = prev;
02261       } else {
02262          iflist = cur->next;
02263          if (iflist)
02264             iflist->prev = NULL;
02265          else
02266             ifend = NULL;
02267       }
02268       if (cur->subs[SUB_REAL].zfd > -1) {
02269          zt_close(cur->subs[SUB_REAL].zfd);
02270       }
02271       destroy_zt_pvt(&cur);
02272    }
02273    return 0;
02274 }

static void destroy_zt_pvt ( struct zt_pvt **  pvt  )  [static]

Definition at line 2205 of file chan_zap.c.

References ast_mutex_destroy(), ast_smdi_interface_destroy(), ASTOBJ_UNREF, free, zt_pvt::lock, zt_pvt::next, zt_pvt::prev, zt_pvt::smdi_iface, and zt_pvt::use_smdi.

Referenced by __unload_module(), chandup(), destroy_channel(), and mkintf().

02206 {
02207    struct zt_pvt *p = *pvt;
02208    /* Remove channel from the list */
02209    if (p->prev)
02210       p->prev->next = p->next;
02211    if (p->next)
02212       p->next->prev = p->prev;
02213    if (p->use_smdi)
02214       ASTOBJ_UNREF(p->smdi_iface, ast_smdi_interface_destroy);
02215    ast_mutex_destroy(&p->lock);
02216    free(p);
02217    *pvt = NULL;
02218 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 983 of file chan_zap.c.

Referenced by zt_digit_begin().

00984 {
00985    if (isdigit(digit))
00986       return ZT_TONE_DTMF_BASE + (digit - '0');
00987    else if (digit >= 'A' && digit <= 'D')
00988       return ZT_TONE_DTMF_A + (digit - 'A');
00989    else if (digit >= 'a' && digit <= 'd')
00990       return ZT_TONE_DTMF_A + (digit - 'a');
00991    else if (digit == '*')
00992       return ZT_TONE_DTMF_s;
00993    else if (digit == '#')
00994       return ZT_TONE_DTMF_p;
00995    else
00996       return -1;
00997 }

static void disable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3102 of file chan_zap.c.

References ast_dsp_set_features(), zt_pvt::dsp, DSP_FEATURE_DTMF_DETECT, zt_pvt::dsp_features, zt_pvt::hardwaredtmf, zt_pvt::ignoredtmf, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by zt_bridge().

03103 {
03104 #ifdef ZT_TONEDETECT
03105    int val;
03106 #endif
03107 
03108    p->ignoredtmf = 1;
03109 
03110 #ifdef ZT_TONEDETECT
03111    val = 0;
03112    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03113 #endif      
03114    if (!p->hardwaredtmf && p->dsp) {
03115       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03116       ast_dsp_set_features(p->dsp, p->dsp_features);
03117    }
03118 }

static void* do_monitor ( void *  data  )  [static]

Definition at line 6760 of file chan_zap.c.

References ast_app_has_voicemail(), ast_calloc, ast_fdisset(), AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), zt_pvt::channel, zt_pvt::cidlen, zt_pvt::cidpos, zt_pvt::cidspill, event2str(), pollfd::events, pollfd::fd, free, handle_init_event(), iflist, last, LOG_DEBUG, LOG_WARNING, zt_pvt::mailbox, MAX_CALLERID_SIZE, zt_pvt::msgstate, zt_pvt::next, zt_pvt::onhooktime, option_debug, zt_subchannel::owner, zt_pvt::owner, poll(), POLLIN, POLLPRI, zt_pvt::radio, pollfd::revents, zt_pvt::sig, SUB_REAL, zt_pvt::subs, vmwi_generate(), zt_subchannel::zfd, and zt_get_event().

06761 {
06762    int count, res, res2, spoint, pollres=0;
06763    struct zt_pvt *i;
06764    struct zt_pvt *last = NULL;
06765    time_t thispass = 0, lastpass = 0;
06766    int found;
06767    char buf[1024];
06768    struct pollfd *pfds=NULL;
06769    int lastalloc = -1;
06770    /* This thread monitors all the frame relay interfaces which are not yet in use
06771       (and thus do not have a separate thread) indefinitely */
06772    /* From here on out, we die whenever asked */
06773 #if 0
06774    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
06775       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
06776       return NULL;
06777    }
06778    ast_log(LOG_DEBUG, "Monitor starting...\n");
06779 #endif
06780    for (;;) {
06781       /* Lock the interface list */
06782       ast_mutex_lock(&iflock);
06783       if (!pfds || (lastalloc != ifcount)) {
06784          if (pfds)
06785             free(pfds);
06786          if (ifcount) {
06787             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
06788                ast_mutex_unlock(&iflock);
06789                return NULL;
06790             }
06791          }
06792          lastalloc = ifcount;
06793       }
06794       /* Build the stuff we're going to poll on, that is the socket of every
06795          zt_pvt that does not have an associated owner channel */
06796       count = 0;
06797       i = iflist;
06798       while (i) {
06799          if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
06800             if (!i->owner && !i->subs[SUB_REAL].owner) {
06801                /* This needs to be watched, as it lacks an owner */
06802                pfds[count].fd = i->subs[SUB_REAL].zfd;
06803                pfds[count].events = POLLPRI;
06804                pfds[count].revents = 0;
06805                /* Message waiting or r2 channels also get watched for reading */
06806                if (i->cidspill)
06807                   pfds[count].events |= POLLIN;
06808                count++;
06809             }
06810          }
06811          i = i->next;
06812       }
06813       /* Okay, now that we know what to do, release the interface lock */
06814       ast_mutex_unlock(&iflock);
06815       
06816       pthread_testcancel();
06817       /* Wait at least a second for something to happen */
06818       res = poll(pfds, count, 1000);
06819       pthread_testcancel();
06820       /* Okay, poll has finished.  Let's see what happened.  */
06821       if (res < 0) {
06822          if ((errno != EAGAIN) && (errno != EINTR))
06823             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
06824          continue;
06825       }
06826       /* Alright, lock the interface list again, and let's look and see what has
06827          happened */
06828       ast_mutex_lock(&iflock);
06829       found = 0;
06830       spoint = 0;
06831       lastpass = thispass;
06832       thispass = time(NULL);
06833       i = iflist;
06834       while (i) {
06835          if (thispass != lastpass) {
06836             if (!found && ((i == last) || ((i == iflist) && !last))) {
06837                last = i;
06838                if (last) {
06839                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
06840                      (last->sig & __ZT_SIG_FXO)) {
06841                      res = ast_app_has_voicemail(last->mailbox, NULL);
06842                      if (last->msgstate != res) {
06843                         int x;
06844                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
06845                         x = ZT_FLUSH_BOTH;
06846                         res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
06847                         if (res2)
06848                            ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
06849                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
06850                            /* Turn on on hook transfer for 4 seconds */
06851                            x = 4000;
06852                            ioctl(last->subs[SUB_REAL].zfd, ZT_ONHOOKTRANSFER, &x);
06853                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
06854                            last->cidpos = 0;
06855                            last->msgstate = res;
06856                            last->onhooktime = thispass;
06857                         }
06858                         found ++;
06859                      }
06860                   }
06861                   last = last->next;
06862                }
06863             }
06864          }
06865          if ((i->subs[SUB_REAL].zfd > -1) && i->sig) {
06866             if (i->radio && !i->owner)
06867             {
06868                res = zt_get_event(i->subs[SUB_REAL].zfd);
06869                if (res)
06870                {
06871                   if (option_debug)
06872                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
06873                   /* Don't hold iflock while handling init events */
06874                   ast_mutex_unlock(&iflock);
06875                   handle_init_event(i, res);
06876                   ast_mutex_lock(&iflock);   
06877                }
06878                i = i->next;
06879                continue;
06880             }              
06881             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint);
06882             if (pollres & POLLIN) {
06883                if (i->owner || i->subs[SUB_REAL].owner) {
06884 #ifdef HAVE_PRI
06885                   if (!i->pri)
06886 #endif                  
06887                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].zfd);
06888                   i = i->next;
06889                   continue;
06890                }
06891                if (!i->cidspill) {
06892                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
06893                   i = i->next;
06894                   continue;
06895                }
06896                res = read(i->subs[SUB_REAL].zfd, buf, sizeof(buf));
06897                if (res > 0) {
06898                   /* We read some number of bytes.  Write an equal amount of data */
06899                   if (res > i->cidlen - i->cidpos) 
06900                      res = i->cidlen - i->cidpos;
06901                   res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
06902                   if (res2 > 0) {
06903                      i->cidpos += res2;
06904                      if (i->cidpos >= i->cidlen) {
06905                         free(i->cidspill);
06906                         i->cidspill = 0;
06907                         i->cidpos = 0;
06908                         i->cidlen = 0;
06909                      }
06910                   } else {
06911                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
06912                      i->msgstate = -1;
06913                   }
06914                } else {
06915                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
06916                }
06917                if (option_debug)
06918                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
06919                /* Don't hold iflock while handling init events -- race with chlock */
06920                ast_mutex_unlock(&iflock);
06921                handle_init_event(i, res);
06922                ast_mutex_lock(&iflock);   
06923             }
06924             if (pollres & POLLPRI) {
06925                if (i->owner || i->subs[SUB_REAL].owner) {
06926 #ifdef HAVE_PRI
06927                   if (!i->pri)
06928 #endif                  
06929                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].zfd);
06930                   i = i->next;
06931                   continue;
06932                }
06933                res = zt_get_event(i->subs[SUB_REAL].zfd);
06934                if (option_debug)
06935                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
06936                /* Don't hold iflock while handling init events */
06937                ast_mutex_unlock(&iflock);
06938                handle_init_event(i, res);
06939                ast_mutex_lock(&iflock);   
06940             }
06941          }
06942          i=i->next;
06943       }
06944       ast_mutex_unlock(&iflock);
06945    }
06946    /* Never reached */
06947    return NULL;
06948    
06949 }

static void enable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3120 of file chan_zap.c.

References ast_dsp_set_features(), CHAN_PSEUDO, zt_pvt::channel, zt_pvt::dsp, DSP_FEATURE_DTMF_DETECT, zt_pvt::dsp_features, zt_pvt::hardwaredtmf, zt_pvt::ignoredtmf, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by zt_bridge().

03121 {
03122 #ifdef ZT_TONEDETECT
03123    int val;
03124 #endif
03125 
03126    if (p->channel == CHAN_PSEUDO)
03127       return;
03128 
03129    p->ignoredtmf = 0;
03130 
03131 #ifdef ZT_TONEDETECT
03132    val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
03133    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03134 #endif      
03135    if (!p->hardwaredtmf && p->dsp) {
03136       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03137       ast_dsp_set_features(p->dsp, p->dsp_features);
03138    }
03139 }

static char* event2str ( int  event  )  [static]

Definition at line 1140 of file chan_zap.c.

Referenced by __zt_exception(), do_monitor(), ss_thread(), and zt_handle_event().

01141 {
01142    static char buf[256];
01143    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01144       return events[event];
01145    sprintf(buf, "Event %d", event); /* safe */
01146    return buf;
01147 }

static void fill_rxgain ( struct zt_gains *  g,
float  gain,
int  law 
) [static]

Definition at line 1505 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

01506 {
01507    int j;
01508    int k;
01509    float linear_gain = pow(10.0, gain / 20.0);
01510 
01511    switch (law) {
01512    case ZT_LAW_ALAW:
01513       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01514          if (gain) {
01515             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01516             if (k > 32767) k = 32767;
01517             if (k < -32767) k = -32767;
01518             g->rxgain[j] = AST_LIN2A(k);
01519          } else {
01520             g->rxgain[j] = j;
01521          }
01522       }
01523       break;
01524    case ZT_LAW_MULAW:
01525       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01526          if (gain) {
01527             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01528             if (k > 32767) k = 32767;
01529             if (k < -32767) k = -32767;
01530             g->rxgain[j] = AST_LIN2MU(k);
01531          } else {
01532             g->rxgain[j] = j;
01533          }
01534       }
01535       break;
01536    }
01537 }

static void fill_txgain ( struct zt_gains *  g,
float  gain,
int  law 
) [static]

Definition at line 1471 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

01472 {
01473    int j;
01474    int k;
01475    float linear_gain = pow(10.0, gain / 20.0);
01476 
01477    switch (law) {
01478    case ZT_LAW_ALAW:
01479       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01480          if (gain) {
01481             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01482             if (k > 32767) k = 32767;
01483             if (k < -32767) k = -32767;
01484             g->txgain[j] = AST_LIN2A(k);
01485          } else {
01486             g->txgain[j] = j;
01487          }
01488       }
01489       break;
01490    case ZT_LAW_MULAW:
01491       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01492          if (gain) {
01493             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01494             if (k > 32767) k = 32767;
01495             if (k < -32767) k = -32767;
01496             g->txgain[j] = AST_LIN2MU(k);
01497          } else {
01498             g->txgain[j] = j;
01499          }
01500       }
01501       break;
01502    }
01503 }

static struct zt_pvt* find_channel ( int  channel  )  [static, read]

Definition at line 10144 of file chan_zap.c.

References zt_pvt::channel, iflist, and zt_pvt::next.

Referenced by action_transfer(), action_transferhangup(), action_zapdialoffhook(), action_zapdndoff(), and action_zapdndon().

10145 {
10146    struct zt_pvt *p = iflist;
10147    while (p) {
10148       if (p->channel == channel) {
10149          break;
10150       }
10151       p = p->next;
10152    }
10153    return p;
10154 }

static int get_alarms ( struct zt_pvt p  )  [static]

Definition at line 3581 of file chan_zap.c.

References ast_log(), zt_pvt::channel, LOG_WARNING, zt_pvt::span, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by action_zapshowchannels(), handle_init_event(), and zt_handle_event().

03582 {
03583    int res;
03584    ZT_SPANINFO zi;
03585    memset(&zi, 0, sizeof(zi));
03586    zi.spanno = p->span;
03587    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SPANSTAT, &zi);
03588    if (res < 0) {
03589       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03590       return 0;
03591    }
03592    return zi.alarms;
03593 }

static int handle_init_event ( struct zt_pvt i,
int  event 
) [static]

Definition at line 6559 of file chan_zap.c.

References alarm2str(), ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verbose(), zt_pvt::channel, zt_pvt::cid_start, CID_START_POLARITY, zt_pvt::cidspill, EVENT_FLAG_SYSTEM, free, get_alarms(), has_voicemail(), zt_pvt::immediate, zt_pvt::inalarm, LOG_NOTICE, LOG_WARNING, manager_event(), zt_pvt::polarity, POLARITY_REV, zt_pvt::radio, zt_pvt::ringt, zt_pvt::ringt_base, zt_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ss_thread(), SUB_REAL, zt_pvt::subs, VERBOSE_PREFIX_2, zap_destroy_channel_bynum(), zt_subchannel::zfd, zt_disable_ec(), zt_enable_ec(), zt_new(), and zt_set_hook().

Referenced by do_monitor().

06560 {
06561    int res;
06562    pthread_t threadid;
06563    pthread_attr_t attr;
06564    struct ast_channel *chan;
06565    pthread_attr_init(&attr);
06566    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06567    /* Handle an event on a given channel for the monitor thread. */
06568    switch (event) {
06569    case ZT_EVENT_NONE:
06570    case ZT_EVENT_BITSCHANGED:
06571       break;
06572    case ZT_EVENT_WINKFLASH:
06573    case ZT_EVENT_RINGOFFHOOK:
06574       if (i->inalarm) break;
06575       if (i->radio) break;
06576       /* Got a ring/answer.  What kind of channel are we? */
06577       switch (i->sig) {
06578       case SIG_FXOLS:
06579       case SIG_FXOGS:
06580       case SIG_FXOKS:
06581          res = zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
06582          if (res && (errno == EBUSY))
06583             break;
06584          if (i->cidspill) {
06585             /* Cancel VMWI spill */
06586             free(i->cidspill);
06587             i->cidspill = NULL;
06588          }
06589          if (i->immediate) {
06590             zt_enable_ec(i);
06591             /* The channel is immediately up.  Start right away */
06592             res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
06593             chan = zt_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06594             if (!chan) {
06595                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06596                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06597                if (res < 0)
06598                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06599             }
06600          } else {
06601             /* Check for callerid, digits, etc */
06602             chan = zt_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06603             if (chan) {
06604                if (has_voicemail(i))
06605                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_STUTTER);
06606                else
06607                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
06608                if (res < 0) 
06609                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06610                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06611                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06612                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06613                   if (res < 0)
06614                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06615                   ast_hangup(chan);
06616                }
06617             } else
06618                ast_log(LOG_WARNING, "Unable to create channel\n");
06619          }
06620          break;
06621       case SIG_FXSLS:
06622       case SIG_FXSGS:
06623       case SIG_FXSKS:
06624             i->ringt = i->ringt_base;
06625             /* Fall through */
06626       case SIG_EMWINK:
06627       case SIG_FEATD:
06628       case SIG_FEATDMF:
06629       case SIG_FEATDMF_TA:
06630       case SIG_E911:
06631       case SIG_FGC_CAMA:
06632       case SIG_FGC_CAMAMF:
06633       case SIG_FEATB:
06634       case SIG_EM:
06635       case SIG_EM_E1:
06636       case SIG_SFWINK:
06637       case SIG_SF_FEATD:
06638       case SIG_SF_FEATDMF:
06639       case SIG_SF_FEATB:
06640       case SIG_SF:
06641             /* Check for callerid, digits, etc */
06642             chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06643             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06644                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06645                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06646                if (res < 0)
06647                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06648                ast_hangup(chan);
06649             } else if (!chan) {
06650                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06651             }
06652             break;
06653       default:
06654          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06655          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06656          if (res < 0)
06657                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06658          return -1;
06659       }
06660       break;
06661    case ZT_EVENT_NOALARM:
06662       i->inalarm = 0;
06663       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06664       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06665          "Channel: %d\r\n", i->channel);
06666       break;
06667    case ZT_EVENT_ALARM:
06668       i->inalarm = 1;
06669       res = get_alarms(i);
06670       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
06671       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
06672          "Alarm: %s\r\n"
06673          "Channel: %d\r\n",
06674          alarm2str(res), i->channel);
06675       /* fall thru intentionally */
06676    case ZT_EVENT_ONHOOK:
06677       if (i->radio)
06678          break;
06679       /* Back on hook.  Hang up. */
06680       switch (i->sig) {
06681       case SIG_FXOLS:
06682       case SIG_FXOGS:
06683       case SIG_FEATD:
06684       case SIG_FEATDMF:
06685       case SIG_FEATDMF_TA:
06686       case SIG_E911:
06687       case SIG_FGC_CAMA:
06688       case SIG_FGC_CAMAMF:
06689       case SIG_FEATB:
06690       case SIG_EM:
06691       case SIG_EM_E1:
06692       case SIG_EMWINK:
06693       case SIG_SF_FEATD:
06694       case SIG_SF_FEATDMF:
06695       case SIG_SF_FEATB:
06696       case SIG_SF:
06697       case SIG_SFWINK:
06698       case SIG_FXSLS:
06699       case SIG_FXSGS:
06700       case SIG_FXSKS:
06701       case SIG_GR303FXSKS:
06702          zt_disable_ec(i);
06703          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06704          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
06705          break;
06706       case SIG_GR303FXOKS:
06707       case SIG_FXOKS:
06708          zt_disable_ec(i);
06709          /* Diddle the battery for the zhone */
06710 #ifdef ZHONE_HACK
06711          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
06712          usleep(1);
06713 #endif         
06714          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06715          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
06716          break;
06717       case SIG_PRI:
06718          zt_disable_ec(i);
06719          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06720          break;
06721       default:
06722          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06723          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06724          return -1;
06725       }
06726       break;
06727    case ZT_EVENT_POLARITY:
06728       switch (i->sig) {
06729       case SIG_FXSLS:
06730       case SIG_FXSKS:
06731       case SIG_FXSGS:
06732          if (i->cid_start == CID_START_POLARITY) {
06733             i->polarity = POLARITY_REV;
06734             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
06735                    "CID detection on channel %d\n",
06736                    i->channel);
06737             chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
06738             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06739                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06740             }
06741          }
06742          break;
06743       default:
06744          ast_log(LOG_WARNING, "handle_init_event detected "
06745             "polarity reversal on non-FXO (SIG_FXS) "
06746             "interface %d\n", i->channel);
06747       }
06748       break;
06749    case ZT_EVENT_REMOVED: /* destroy channel */
06750       ast_log(LOG_NOTICE, 
06751             "Got ZT_EVENT_REMOVED. Destroying channel %d\n", 
06752             i->channel);
06753       zap_destroy_channel_bynum(i->channel);
06754       break;
06755    }
06756    pthread_attr_destroy(&attr);
06757    return 0;
06758 }

static int handle_zap_show_cadences ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 9988 of file chan_zap.c.

References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().

09989 {
09990    int i, j;
09991    for (i = 0; i < num_cadence; i++) {
09992       char output[1024];
09993       char tmp[16], tmp2[64];
09994       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
09995       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
09996 
09997       for (j = 0; j < 16; j++) {
09998          if (cadences[i].ringcadence[j] == 0)
09999             break;
10000          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10001          if (cidrings[i] * 2 - 1 == j)
10002             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10003          else
10004             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10005          if (j != 0)
10006             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10007          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10008       }
10009       ast_cli(fd,"%s\n",output);
10010    }
10011    return 0;
10012 }

static int has_voicemail ( struct zt_pvt p  )  [static]

Definition at line 1702 of file chan_zap.c.

References ast_app_has_voicemail(), and zt_pvt::mailbox.

01703 {
01704 
01705    return ast_app_has_voicemail(p->mailbox, NULL);
01706 }

static int isourconf ( struct zt_pvt p,
struct zt_subchannel c 
) [static]

Definition at line 1259 of file chan_zap.c.

References zt_pvt::channel, zt_pvt::confno, and zt_subchannel::curconf.

Referenced by conf_del().

01260 {
01261    /* If they're listening to our channel, they're ours */  
01262    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == ZT_CONF_DIGITALMON))
01263       return 1;
01264    /* If they're a talker on our (allocated) conference, they're ours */
01265    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & ZT_CONF_TALKER))
01266       return 1;
01267    return 0;
01268 }

static int isslavenative ( struct zt_pvt p,
struct zt_pvt **  out 
) [static]

Definition at line 1292 of file chan_zap.c.

References zt_subchannel::inthreeway, zt_pvt::law, MAX_SLAVES, zt_pvt::slaves, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by update_conf().

01293 {
01294    int x;
01295    int useslavenative;
01296    struct zt_pvt *slave = NULL;
01297    /* Start out optimistic */
01298    useslavenative = 1;
01299    /* Update conference state in a stateless fashion */
01300    for (x = 0; x < 3; x++) {
01301       /* Any three-way calling makes slave native mode *definitely* out
01302          of the question */
01303       if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway)
01304          useslavenative = 0;
01305    }
01306    /* If we don't have any 3-way calls, check to see if we have
01307       precisely one slave */
01308    if (useslavenative) {
01309       for (x = 0; x < MAX_SLAVES; x++) {
01310          if (p->slaves[x]) {
01311             if (slave) {
01312                /* Whoops already have a slave!  No 
01313                   slave native and stop right away */
01314                slave = NULL;
01315                useslavenative = 0;
01316                break;
01317             } else {
01318                /* We have one slave so far */
01319                slave = p->slaves[x];
01320             }
01321          }
01322       }
01323    }
01324    /* If no slave, slave native definitely out */
01325    if (!slave)
01326       useslavenative = 0;
01327    else if (slave->law != p->law) {
01328       useslavenative = 0;
01329       slave = NULL;
01330    }
01331    if (out)
01332       *out = slave;
01333    return useslavenative;
01334 }

static int load_module ( void   )  [static]

Definition at line 11281 of file chan_zap.c.

References __unload_module(), action_transfer(), action_transferhangup(), action_zapdialoffhook(), action_zapdndoff(), action_zapdndon(), action_zaprestart(), action_zapshowchannels(), ast_channel_register(), ast_cli_register_multiple(), ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application(), ast_string_field_init, ast_string_field_set, inuse, lock, LOG_ERROR, name, and setup_zap().

11282 {
11283    int res;
11284 
11285 #ifdef HAVE_PRI
11286    int y,i;
11287    memset(pris, 0, sizeof(pris));
11288    for (y = 0; y < NUM_SPANS; y++) {
11289       ast_mutex_init(&pris[y].lock);
11290       pris[y].offset = -1;
11291       pris[y].master = AST_PTHREADT_NULL;
11292       for (i = 0; i < NUM_DCHANS; i++)
11293          pris[y].fds[i] = -1;
11294    }
11295    pri_set_error(zt_pri_error);
11296    pri_set_message(zt_pri_message);
11297    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11298          zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11299 #endif
11300    res = setup_zap(0);
11301    /* Make sure we can register our Zap channel type */
11302    if (res)
11303       return AST_MODULE_LOAD_DECLINE;
11304    if (ast_channel_register(&zap_tech)) {
11305       ast_log(LOG_ERROR, "Unable to register channel class 'Zap'\n");
11306       __unload_module();
11307       return -1;
11308    }
11309 #ifdef HAVE_PRI
11310    ast_string_field_init(&inuse, 16);
11311    ast_string_field_set(&inuse, name, "GR-303InUse");
11312    ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
11313 #endif   
11314    ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
11315    
11316    memset(round_robin, 0, sizeof(round_robin));
11317    ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
11318    ast_manager_register( "ZapHangup", 0, action_transferhangup, "Hangup Zap Channel" );
11319    ast_manager_register( "ZapDialOffhook", 0, action_zapdialoffhook, "Dial over Zap channel while offhook" );
11320    ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
11321    ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
11322    ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
11323    ast_manager_register("ZapRestart", 0, action_zaprestart, "Fully Restart zaptel channels (terminates calls)");
11324 
11325    return res;
11326 }

static struct zt_pvt* mkintf ( int  channel,
struct zt_chan_conf  conf,
struct zt_pri *  pri,
int  reloading 
) [static, read]

Definition at line 7096 of file chan_zap.c.

References zt_pvt::accountcode, zt_pvt::adsi, zt_pvt::amaflags, zt_pvt::answeronpolarityswitch, ast_calloc, ast_dsp_digitmode(), ast_log(), ast_mutex_init(), ast_smdi_interface_find(), ast_strlen_zero(), zt_pvt::busy_quietlength, zt_pvt::busy_tonelength, zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::callgroup, zt_pvt::callprogress, zt_pvt::callreturn, zt_pvt::callwaiting, zt_pvt::callwaitingcallerid, zt_pvt::cancallforward, zt_pvt::canpark, zt_chan_conf::chan, CHAN_PSEUDO, zt_pvt::channel, zt_pvt::cid_name, zt_pvt::cid_num, CID_SIG_SMDI, zt_pvt::cid_signalling, zt_pvt::cid_start, zt_pvt::cid_ton, zt_pvt::confno, zt_pvt::context, zt_pvt::defcontext, zt_pvt::destroy, destroy_zt_pvt(), drings, zt_pvt::drings, zt_pvt::dsp, DSP_DIGITMODE_DTMF, zt_pvt::dtmfrelax, zt_pvt::echocanbridged, zt_pvt::echocancel, zt_pvt::echotraining, zt_pvt::firstradio, zt_pvt::group, zt_pvt::hanguponpolarityswitch, zt_pvt::hidecallerid, iflist, zt_pvt::immediate, zt_pvt::inalarm, zt_pvt::language, zt_pvt::law, zt_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, zt_pvt::mailbox, MAX_CHANNELS, zt_pvt::mohinterpret, zt_pvt::mohsuggest, zt_pvt::msgstate, zt_pvt::next, zt_pvt::onhooktime, zt_pvt::outsigmod, zt_pvt::permcallwaiting, zt_pvt::permhidecallerid, zt_pvt::pickupgroup, zt_pvt::polarityonanswerdelay, zt_pvt::prev, zt_pvt::priexclusive, zt_pvt::priindication_oob, zt_pvt::propconfno, zt_pvt::pulse, zt_pvt::radio, zt_pvt::restrictcid, zt_pvt::ringt_base, zt_pvt::rxgain, zt_pvt::sendcalleridafter, set_actual_gain(), zt_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, zt_pvt::smdi_iface, zt_chan_conf::smdi_port, zt_pvt::span, zt_pvt::stripmsd, SUB_REAL, zt_pvt::subs, zt_pvt::threewaycalling, zt_chan_conf::timing, zt_pvt::tonezone, zt_pvt::transfer, zt_pvt::transfertobusy, zt_pvt::txgain, update_conf(), zt_pvt::use_callerid, zt_pvt::use_callingpres, zt_pvt::use_smdi, zt_pvt::usedistinctiveringdetection, zt_pvt::zaptrcallerid, zt_subchannel::zfd, zt_open(), and zt_set_hook().

Referenced by build_channels(), and process_zap().

07097 {
07098    /* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
07099    struct zt_pvt *tmp = NULL, *tmp2,  *prev = NULL;
07100    char fn[80];
07101 #if 1
07102    struct zt_bufferinfo bi;
07103 #endif
07104    struct zt_spaninfo si;
07105    int res;
07106    int span=0;
07107    int here = 0;
07108    int x;
07109    struct zt_pvt **wlist;
07110    struct zt_pvt **wend;
07111    ZT_PARAMS p;
07112 
07113    wlist = &iflist;
07114    wend = &ifend;
07115 
07116 #ifdef HAVE_PRI
07117    if (pri) {
07118       wlist = &pri->crvs;
07119       wend = &pri->crvend;
07120    }
07121 #endif
07122 
07123    tmp2 = *wlist;
07124    prev = NULL;
07125 
07126    while (tmp2) {
07127       if (!tmp2->destroy) {
07128          if (tmp2->channel == channel) {
07129             tmp = tmp2;
07130             here = 1;
07131             break;
07132          }
07133          if (tmp2->channel > channel) {
07134             break;
07135          }
07136       }
07137       prev = tmp2;
07138       tmp2 = tmp2->next;
07139    }
07140 
07141    if (!here && !reloading) {
07142       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07143          destroy_zt_pvt(&tmp);
07144          return NULL;
07145       }
07146       ast_mutex_init(&tmp->lock);
07147       ifcount++;
07148       for (x = 0; x < 3; x++)
07149          tmp->subs[x].zfd = -1;
07150       tmp->channel = channel;
07151    }
07152 
07153    if (tmp) {
07154       if (!here) {
07155          if ((channel != CHAN_PSEUDO) && !pri) {
07156             snprintf(fn, sizeof(fn), "%d", channel);
07157             /* Open non-blocking */
07158             if (!here)
07159                tmp->subs[SUB_REAL].zfd = zt_open(fn);
07160             /* Allocate a zapata structure */
07161             if (tmp->subs[SUB_REAL].zfd < 0) {
07162                ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
07163                destroy_zt_pvt(&tmp);
07164                return NULL;
07165             }
07166             memset(&p, 0, sizeof(p));
07167             res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &p);
07168             if (res < 0) {
07169                ast_log(LOG_ERROR, "Unable to get parameters\n");
07170                destroy_zt_pvt(&tmp);
07171                return NULL;
07172             }
07173             if (p.sigtype != (conf.chan.sig & 0x3ffff)) {
07174                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf.chan.sig), sig2str(p.sigtype));
07175                destroy_zt_pvt(&tmp);
07176                return NULL;
07177             }
07178             tmp->law = p.curlaw;
07179             tmp->span = p.spanno;
07180             span = p.spanno - 1;
07181          } else {
07182             if (channel == CHAN_PSEUDO)
07183                conf.chan.sig = 0;
07184             else if ((conf.chan.sig != SIG_FXOKS) && (conf.chan.sig != SIG_FXSKS)) {
07185                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07186                return NULL;
07187             }
07188          }
07189 #ifdef HAVE_PRI
07190          if ((conf.chan.sig == SIG_PRI) || (conf.chan.sig == SIG_GR303FXOKS) || (conf.chan.sig == SIG_GR303FXSKS)) {
07191             int offset;
07192             int myswitchtype;
07193             int matchesdchan;
07194             int x,y;
07195             offset = 0;
07196             if ((conf.chan.sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &offset)) {
07197                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07198                destroy_zt_pvt(&tmp);
07199                return NULL;
07200             }
07201             if (span >= NUM_SPANS) {
07202                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07203                destroy_zt_pvt(&tmp);
07204                return NULL;
07205             } else {
07206                si.spanno = 0;
07207                if (ioctl(tmp->subs[SUB_REAL].zfd,ZT_SPANSTAT,&si) == -1) {
07208                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07209                   destroy_zt_pvt(&tmp);
07210                   return NULL;
07211                }
07212                /* Store the logical span first based upon the real span */
07213                tmp->logicalspan = pris[span].prilogicalspan;
07214                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07215                if (span < 0) {
07216                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07217                   destroy_zt_pvt(&tmp);
07218                   return NULL;
07219                }
07220                if (conf.chan.sig == SIG_PRI)
07221                   myswitchtype = conf.pri.switchtype;
07222                else
07223                   myswitchtype = PRI_SWITCH_GR303_TMC;
07224                /* Make sure this isn't a d-channel */
07225                matchesdchan=0;
07226                for (x = 0; x < NUM_SPANS; x++) {
07227                   for (y = 0; y < NUM_DCHANS; y++) {
07228                      if (pris[x].dchannels[y] == tmp->channel) {
07229                         matchesdchan = 1;
07230                         break;
07231                      }
07232                   }
07233                }
07234                offset = p.chanpos;
07235                if (!matchesdchan) {
07236                   if (pris[span].nodetype && (pris[span].nodetype != conf.pri.nodetype)) {
07237                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07238                      destroy_zt_pvt(&tmp);
07239                      return NULL;
07240                   }
07241                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07242                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07243                      destroy_zt_pvt(&tmp);
07244                      return NULL;
07245                   }
07246                   if ((pris[span].dialplan) && (pris[span].dialplan != conf.pri.dialplan)) {
07247                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07248                      destroy_zt_pvt(&tmp);
07249                      return NULL;
07250                   }
07251                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf.pri.idledial)) {
07252                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf.pri.idledial);
07253                      destroy_zt_pvt(&tmp);
07254                      return NULL;
07255                   }
07256                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf.pri.idleext)) {
07257                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf.pri.idleext);
07258                      destroy_zt_pvt(&tmp);
07259                      return NULL;
07260                   }
07261                   if (pris[span].minunused && (pris[span].minunused != conf.pri.minunused)) {
07262                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf.pri.minunused);
07263                      destroy_zt_pvt(&tmp);
07264                      return NULL;
07265                   }
07266                   if (pris[span].minidle && (pris[span].minidle != conf.pri.minidle)) {
07267                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf.pri.minidle);
07268                      destroy_zt_pvt(&tmp);
07269                      return NULL;
07270                   }
07271                   if (pris[span].numchans >= MAX_CHANNELS) {
07272                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07273                         pris[span].trunkgroup);
07274                      destroy_zt_pvt(&tmp);
07275                      return NULL;
07276                   }
07277                   pris[span].nodetype = conf.pri.nodetype;
07278                   pris[span].switchtype = myswitchtype;
07279                   pris[span].nsf = conf.pri.nsf;
07280                   pris[span].dialplan = conf.pri.dialplan;
07281                   pris[span].localdialplan = conf.pri.localdialplan;
07282                   pris[span].pvts[pris[span].numchans++] = tmp;
07283                   pris[span].minunused = conf.pri.minunused;
07284                   pris[span].minidle = conf.pri.minidle;
07285                   pris[span].overlapdial = conf.pri.overlapdial;
07286                   pris[span].facilityenable = conf.pri.facilityenable;
07287                   ast_copy_string(pris[span].idledial, conf.pri.idledial, sizeof(pris[span].idledial));
07288                   ast_copy_string(pris[span].idleext, conf.pri.idleext, sizeof(pris[span].idleext));
07289                   ast_copy_string(pris[span].internationalprefix, conf.pri.internationalprefix, sizeof(pris[span].internationalprefix));
07290                   ast_copy_string(pris[span].nationalprefix, conf.pri.nationalprefix, sizeof(pris[span].nationalprefix));
07291                   ast_copy_string(pris[span].localprefix, conf.pri.localprefix, sizeof(pris[span].localprefix));
07292                   ast_copy_string(pris[span].privateprefix, conf.pri.privateprefix, sizeof(pris[span].privateprefix));
07293                   ast_copy_string(pris[span].unknownprefix, conf.pri.unknownprefix, sizeof(pris[span].unknownprefix));
07294                   pris[span].resetinterval = conf.pri.resetinterval;
07295                   
07296                   tmp->pri = &pris[span];
07297                   tmp->prioffset = offset;
07298                   tmp->call = NULL;
07299                } else {
07300                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07301                   destroy_zt_pvt(&tmp);
07302                   return NULL;
07303                }
07304             }
07305          } else {
07306             tmp->prioffset = 0;
07307          }
07308 #endif
07309       } else {
07310          conf.chan.sig = tmp->sig;
07311          conf.chan.radio = tmp->radio;
07312          memset(&p, 0, sizeof(p));
07313          if (tmp->subs[SUB_REAL].zfd > -1)
07314             res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &p);
07315       }
07316       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
07317       if ((conf.chan.sig == SIG_FXSKS) || (conf.chan.sig == SIG_FXSLS) ||
07318           (conf.chan.sig == SIG_EM) || (conf.chan.sig == SIG_EM_E1) ||  (conf.chan.sig == SIG_EMWINK) ||
07319          (conf.chan.sig == SIG_FEATD) || (conf.chan.sig == SIG_FEATDMF) || (conf.chan.sig == SIG_FEATDMF_TA) ||
07320            (conf.chan.sig == SIG_FEATB) || (conf.chan.sig == SIG_E911) ||
07321           (conf.chan.sig == SIG_SF) || (conf.chan.sig == SIG_SFWINK) || (conf.chan.sig == SIG_FGC_CAMA) || (conf.chan.sig == SIG_FGC_CAMAMF) ||
07322          (conf.chan.sig == SIG_SF_FEATD) || (conf.chan.sig == SIG_SF_FEATDMF) ||
07323            (conf.chan.sig == SIG_SF_FEATB)) {
07324          p.starttime = 250;
07325       }
07326       if (conf.chan.radio) {
07327          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
07328          p.channo = channel;
07329          p.rxwinktime = 1;
07330          p.rxflashtime = 1;
07331          p.starttime = 1;
07332          p.debouncetime = 5;
07333       }
07334       if (!conf.chan.radio) {
07335          p.channo = channel;
07336          /* Override timing settings based on config file */
07337          if (conf.timing.prewinktime >= 0)
07338             p.prewinktime = conf.timing.prewinktime;
07339          if (conf.timing.preflashtime >= 0)
07340             p.preflashtime = conf.timing.preflashtime;
07341          if (conf.timing.winktime >= 0)
07342             p.winktime = conf.timing.winktime;
07343          if (conf.timing.flashtime >= 0)
07344             p.flashtime = conf.timing.flashtime;
07345          if (conf.timing.starttime >= 0)
07346             p.starttime = conf.timing.starttime;
07347          if (conf.timing.rxwinktime >= 0)
07348             p.rxwinktime = conf.timing.rxwinktime;
07349          if (conf.timing.rxflashtime >= 0)
07350             p.rxflashtime = conf.timing.rxflashtime;
07351          if (conf.timing.debouncetime >= 0)
07352             p.debouncetime = conf.timing.debouncetime;
07353       }
07354       
07355       /* dont set parms on a pseudo-channel (or CRV) */
07356       if (tmp->subs[SUB_REAL].zfd >= 0)
07357       {
07358          res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_PARAMS, &p);
07359          if (res < 0) {
07360             ast_log(LOG_ERROR, "Unable to set parameters\n");
07361             destroy_zt_pvt(&tmp);
07362             return NULL;
07363          }
07364       }
07365 #if 1
07366       if (!here && (tmp->subs[SUB_REAL].zfd > -1)) {
07367          memset(&bi, 0, sizeof(bi));
07368          res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
07369          if (!res) {
07370             bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
07371             bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
07372             bi.numbufs = numbufs;
07373             res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
07374             if (res < 0) {
07375                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", channel);
07376             }
07377          } else
07378             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", channel);
07379       }
07380 #endif
07381       tmp->immediate = conf.chan.immediate;
07382       tmp->transfertobusy = conf.chan.transfertobusy;
07383       tmp->sig = conf.chan.sig;
07384       tmp->outsigmod = conf.chan.outsigmod;
07385       tmp->radio = conf.chan.radio;
07386       tmp->ringt_base = ringt_base;
07387       tmp->firstradio = 0;
07388       if ((conf.chan.sig == SIG_FXOKS) || (conf.chan.sig == SIG_FXOLS) || (conf.chan.sig == SIG_FXOGS))
07389          tmp->permcallwaiting = conf.chan.callwaiting;
07390       else
07391          tmp->permcallwaiting = 0;
07392       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
07393       tmp->destroy = 0;
07394       tmp->drings = drings;
07395       tmp->usedistinctiveringdetection = conf.chan.usedistinctiveringdetection;
07396       tmp->callwaitingcallerid = conf.chan.callwaitingcallerid;
07397       tmp->threewaycalling = conf.chan.threewaycalling;
07398       tmp->adsi = conf.chan.adsi;
07399       tmp->use_smdi = conf.chan.use_smdi;
07400       tmp->permhidecallerid = conf.chan.hidecallerid;
07401       tmp->callreturn = conf.chan.callreturn;
07402       tmp->echocancel = conf.chan.echocancel;
07403       tmp->echotraining = conf.chan.echotraining;
07404       tmp->pulse = conf.chan.pulse;
07405       tmp->echocanbridged = conf.chan.echocanbridged;
07406       tmp->busydetect = conf.chan.busydetect;
07407       tmp->busycount = conf.chan.busycount;
07408       tmp->busy_tonelength = conf.chan.busy_tonelength;
07409       tmp->busy_quietlength = conf.chan.busy_quietlength;
07410       tmp->callprogress = conf.chan.callprogress;
07411       tmp->cancallforward = conf.chan.cancallforward;
07412       tmp->dtmfrelax = conf.chan.dtmfrelax;
07413       tmp->callwaiting = tmp->permcallwaiting;
07414       tmp->hidecallerid = tmp->permhidecallerid;
07415       tmp->channel = channel;
07416       tmp->stripmsd = conf.chan.stripmsd;
07417       tmp->use_callerid = conf.chan.use_callerid;
07418       tmp->cid_signalling = conf.chan.cid_signalling;
07419       tmp->cid_start = conf.chan.cid_start;
07420       tmp->zaptrcallerid = conf.chan.zaptrcallerid;
07421       tmp->restrictcid = conf.chan.restrictcid;
07422       tmp->use_callingpres = conf.chan.use_callingpres;
07423       tmp->priindication_oob = conf.chan.priindication_oob;
07424       tmp->priexclusive = conf.chan.priexclusive;
07425       if (tmp->usedistinctiveringdetection) {
07426          if (!tmp->use_callerid) {
07427             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07428             tmp->use_callerid = 1;
07429          }
07430       }
07431 
07432       if (tmp->cid_signalling == CID_SIG_SMDI) {
07433          if (!tmp->use_smdi) {
07434             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07435             tmp->use_smdi = 1;
07436          }
07437       }
07438       if (tmp->use_smdi) {
07439          tmp->smdi_iface = ast_smdi_interface_find(conf.smdi_port);
07440          if (!(tmp->smdi_iface)) {
07441             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07442             tmp->use_smdi = 0;
07443          }
07444       }
07445 
07446       ast_copy_string(tmp->accountcode, conf.chan.accountcode, sizeof(tmp->accountcode));
07447       tmp->amaflags = conf.chan.amaflags;
07448       if (!here) {
07449          tmp->confno = -1;
07450          tmp->propconfno = -1;
07451       }
07452       tmp->canpark = conf.chan.canpark;
07453       tmp->transfer = conf.chan.transfer;
07454       ast_copy_string(tmp->defcontext,conf.chan.context,sizeof(tmp->defcontext));
07455       ast_copy_string(tmp->language, conf.chan.language, sizeof(tmp->language));
07456       ast_copy_string(tmp->mohinterpret, conf.chan.mohinterpret, sizeof(tmp->mohinterpret));
07457       ast_copy_string(tmp->mohsuggest, conf.chan.mohsuggest, sizeof(tmp->mohsuggest));
07458       ast_copy_string(tmp->context, conf.chan.context, sizeof(tmp->context));
07459       ast_copy_string(tmp->cid_num, conf.chan.cid_num, sizeof(tmp->cid_num));
07460       tmp->cid_ton = 0;
07461       ast_copy_string(tmp->cid_name, conf.chan.cid_name, sizeof(tmp->cid_name));
07462       ast_copy_string(tmp->mailbox, conf.chan.mailbox, sizeof(tmp->mailbox));
07463       tmp->msgstate = -1;
07464       tmp->group = conf.chan.group;
07465       tmp->callgroup = conf.chan.callgroup;
07466       tmp->pickupgroup= conf.chan.pickupgroup;
07467       tmp->rxgain = conf.chan.rxgain;
07468       tmp->txgain = conf.chan.txgain;
07469       tmp->tonezone = conf.chan.tonezone;
07470       tmp->onhooktime = time(NULL);
07471       if (tmp->subs[SUB_REAL].zfd > -1) {
07472          set_actual_gain(tmp->subs[SUB_REAL].zfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
07473          if (tmp->dsp)
07474             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
07475          update_conf(tmp);
07476          if (!here) {
07477             if (conf.chan.sig != SIG_PRI)
07478                /* Hang it up to be sure it's good */
07479                zt_set_hook(tmp->subs[SUB_REAL].zfd, ZT_ONHOOK);
07480          }
07481          ioctl(tmp->subs[SUB_REAL].zfd,ZT_SETTONEZONE,&tmp->tonezone);
07482 #ifdef HAVE_PRI
07483          /* the dchannel is down so put the channel in alarm */
07484          if (tmp->pri && !pri_is_up(tmp->pri))
07485             tmp->inalarm = 1;
07486          else
07487             tmp->inalarm = 0;
07488 #endif            
07489          memset(&si, 0, sizeof(si));
07490          if (ioctl(tmp->subs[SUB_REAL].zfd,ZT_SPANSTAT,&si) == -1) {
07491             ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07492             destroy_zt_pvt(&tmp);
07493             return NULL;
07494          }
07495          if (si.alarms) tmp->inalarm = 1;
07496       }
07497 
07498       tmp->polarityonanswerdelay = conf.chan.polarityonanswerdelay;
07499       tmp->answeronpolarityswitch = conf.chan.answeronpolarityswitch;
07500       tmp->hanguponpolarityswitch = conf.chan.hanguponpolarityswitch;
07501       tmp->sendcalleridafter = conf.chan.sendcalleridafter;
07502 
07503    }
07504    if (tmp && !here) {
07505       /* nothing on the iflist */
07506       if (!*wlist) {
07507          *wlist = tmp;
07508          tmp->prev = NULL;
07509          tmp->next = NULL;
07510          *wend = tmp;
07511       } else {
07512          /* at least one member on the iflist */
07513          struct zt_pvt *working = *wlist;
07514 
07515          /* check if we maybe have to put it on the begining */
07516          if (working->channel > tmp->channel) {
07517             tmp->next = *wlist;
07518             tmp->prev = NULL;
07519             (*wlist)->prev = tmp;
07520             *wlist = tmp;
07521          } else {
07522          /* go through all the members and put the member in the right place */
07523             while (working) {
07524                /* in the middle */
07525                if (working->next) {
07526                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
07527                      tmp->next = working->next;
07528                      tmp->prev = working;
07529                      working->next->prev = tmp;
07530                      working->next = tmp;
07531                      break;
07532                   }
07533                } else {
07534                /* the last */
07535                   if (working->channel < tmp->channel) {
07536                      working->next = tmp;
07537                      tmp->next = NULL;
07538                      tmp->prev = working;
07539                      *wend = tmp;
07540                      break;
07541                   }
07542                }
07543                working = working->next;
07544             }
07545          }
07546       }
07547    }
07548    return tmp;
07549 }

static int my_getsigstr ( struct ast_channel chan,
char *  str,
const char *  term,
int  ms 
) [static]

Definition at line 5363 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

05364 {
05365    char c;
05366 
05367    *str = 0; /* start with empty output buffer */
05368    for (;;)
05369    {
05370       /* Wait for the first digit (up to specified ms). */
05371       c = ast_waitfordigit(chan, ms);
05372       /* if timeout, hangup or error, return as such */
05373       if (c < 1)
05374          return c;
05375       *str++ = c;
05376       *str = 0;
05377       if (strchr(term, c))
05378          return 1;
05379    }
05380 }

static int my_zt_write ( struct zt_pvt p,
unsigned char *  buf,
int  len,
int  index,
int  linear 
) [static]

Definition at line 4890 of file chan_zap.c.

References ast_log(), zt_pvt::channel, LOG_DEBUG, option_debug, READ_SIZE, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by zt_write().

04891 {
04892    int sent=0;
04893    int size;
04894    int res;
04895    int fd;
04896    fd = p->subs[index].zfd;
04897    while (len) {
04898       size = len;
04899       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
04900          size = (linear ? READ_SIZE * 2 : READ_SIZE);
04901       res = write(fd, buf, size);
04902       if (res != size) {
04903          if (option_debug)
04904             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04905          return sent;
04906       }
04907       len -= size;
04908       buf += size;
04909    }
04910    return sent;
04911 }

static int process_zap ( struct zt_chan_conf confp,
struct ast_variable v,
int  reload,
int  skipchannels 
) [static]

Definition at line 10481 of file chan_zap.c.

References zt_pvt::accountcode, zt_pvt::adsi, zt_pvt::amaflags, zt_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_get_group(), ast_jb_read_conf(), ast_log(), ast_strlen_zero(), ast_true(), ast_verbose(), build_channels(), zt_pvt::busy_quietlength, zt_pvt::busy_tonelength, zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::callgroup, zt_pvt::callprogress, zt_pvt::callreturn, zt_pvt::callwaiting, zt_pvt::callwaitingcallerid, zt_pvt::cancallforward, zt_pvt::canpark, zt_chan_conf::chan, CHAN_PSEUDO, zt_pvt::cid_name, zt_pvt::cid_num, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, zt_pvt::cid_signalling, zt_pvt::cid_start, CID_START_POLARITY, CID_START_RING, zt_pvt::context, ringContextData::contextData, drings, DSP_DIGITMODE_RELAXDTMF, zt_pvt::dtmfrelax, zt_pvt::echocanbridged, zt_pvt::echocancel, zt_pvt::echotraining, global_jbconf, zt_pvt::group, zt_pvt::hanguponpolarityswitch, HAVE_PRI, zt_pvt::hidecallerid, zt_pvt::hidecalleridname, zt_pvt::immediate, zt_pvt::language, ast_variable::lineno, LOG_ERROR, LOG_WARNING, zt_pvt::mailbox, MAX_CHANLIST_LEN, mkintf(), zt_pvt::mohinterpret, zt_pvt::mohsuggest, ast_variable::name, ast_variable::next, NUM_CADENCE_MAX, option_verbose, zt_pvt::outsigmod, zt_pvt::pickupgroup, zt_pvt::polarityonanswerdelay, zt_pvt::priexclusive, zt_pvt::priindication_oob, zt_pvt::pulse, zt_pvt::radio, READ_SIZE, zt_pvt::restrictcid, distRingData::ring, zt_distRings::ringContext, zt_distRings::ringnum, zt_pvt::rxgain, zt_pvt::sendcalleridafter, zt_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, zt_chan_conf::smdi_port, zt_pvt::stripmsd, strsep(), zt_pvt::threewaycalling, zt_chan_conf::timing, zt_pvt::tonezone, zt_pvt::transfer, zt_pvt::transfertobusy, zt_pvt::txgain, zt_pvt::use_callerid, zt_pvt::use_callingpres, zt_pvt::use_smdi, zt_pvt::usedistinctiveringdetection, ast_variable::value, VERBOSE_PREFIX_3, and zt_pvt::zaptrcallerid.

Referenced by setup_zap().

10482 {
10483    struct zt_pvt *tmp;
10484    char *ringc; /* temporary string for parsing the dring number. */
10485    int y;
10486    int found_pseudo = 0;
10487         char zapchan[MAX_CHANLIST_LEN] = {};
10488 
10489    for (; v; v = v->next) {
10490       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
10491          continue;
10492 
10493       /* Create the interface list */
10494       if (!strcasecmp(v->name, "channel")
10495 #ifdef HAVE_PRI
10496           || !strcasecmp(v->name, "crv")
10497 #endif         
10498          ) {
10499          int iscrv;
10500          if (skipchannels)
10501             continue;
10502          iscrv = !strcasecmp(v->name, "crv");
10503          if (build_channels(*confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
10504                return -1;
10505       } else if (!strcasecmp(v->name, "zapchan")) {
10506          ast_copy_string(zapchan, v->value, sizeof(zapchan));
10507       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
10508          if (ast_true(v->value))
10509             confp->chan.usedistinctiveringdetection = 1;
10510       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
10511          if (ast_true(v->value))
10512             distinctiveringaftercid = 1;
10513       } else if (!strcasecmp(v->name, "dring1context")) {
10514          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
10515       } else if (!strcasecmp(v->name, "dring2context")) {
10516          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
10517       } else if (!strcasecmp(v->name, "dring3context")) {
10518          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
10519       } else if (!strcasecmp(v->name, "dring1")) {
10520          ringc = v->value;
10521          sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
10522       } else if (!strcasecmp(v->name, "dring2")) {
10523          ringc = v->value;
10524          sscanf(ringc, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
10525       } else if (!strcasecmp(v->name, "dring3")) {
10526          ringc = v->value;
10527          sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
10528       } else if (!strcasecmp(v->name, "usecallerid")) {
10529          confp->chan.use_callerid = ast_true(v->value);
10530       } else if (!strcasecmp(v->name, "cidsignalling")) {
10531          if (!strcasecmp(v->value, "bell"))
10532             confp->chan.cid_signalling = CID_SIG_BELL;
10533          else if (!strcasecmp(v->value, "v23"))
10534             confp->chan.cid_signalling = CID_SIG_V23;
10535          else if (!strcasecmp(v->value, "dtmf"))
10536             confp->chan.cid_signalling = CID_SIG_DTMF;
10537          else if (!strcasecmp(v->value, "smdi"))
10538             confp->chan.cid_signalling = CID_SIG_SMDI;
10539          else if (!strcasecmp(v->value, "v23_jp"))
10540             confp->chan.cid_signalling = CID_SIG_V23_JP;
10541          else if (ast_true(v->value))
10542             confp->chan.cid_signalling = CID_SIG_BELL;
10543       } else if (!strcasecmp(v->name, "cidstart")) {
10544          if (!strcasecmp(v->value, "ring"))
10545             confp->chan.cid_start = CID_START_RING;
10546          else if (!strcasecmp(v->value, "polarity"))
10547             confp->chan.cid_start = CID_START_POLARITY;
10548          else if (ast_true(v->value))
10549             confp->chan.cid_start = CID_START_RING;
10550       } else if (!strcasecmp(v->name, "threewaycalling")) {
10551          confp->chan.threewaycalling = ast_true(v->value);
10552       } else if (!strcasecmp(v->name, "cancallforward")) {
10553          confp->chan.cancallforward = ast_true(v->value);
10554       } else if (!strcasecmp(v->name, "relaxdtmf")) {
10555          if (ast_true(v->value)) 
10556             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
10557          else
10558             confp->chan.dtmfrelax = 0;
10559       } else if (!strcasecmp(v->name, "mailbox")) {
10560          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
10561       } else if (!strcasecmp(v->name, "adsi")) {
10562          confp->chan.adsi = ast_true(v->value);
10563       } else if (!strcasecmp(v->name, "usesmdi")) {
10564          confp->chan.use_smdi = ast_true(v->value);
10565       } else if (!strcasecmp(v->name, "smdiport")) {
10566          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
10567       } else if (!strcasecmp(v->name, "transfer")) {
10568          confp->chan.transfer = ast_true(v->value);
10569       } else if (!strcasecmp(v->name, "canpark")) {
10570          confp->chan.canpark = ast_true(v->value);
10571       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
10572          confp->chan.echocanbridged = ast_true(v->value);
10573       } else if (!strcasecmp(v->name, "busydetect")) {
10574          confp->chan.busydetect = ast_true(v->value);
10575       } else if (!strcasecmp(v->name, "busycount")) {
10576          confp->chan.busycount = atoi(v->value);
10577       } else if (!strcasecmp(v->name, "busypattern")) {
10578          if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
10579             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
10580          }
10581       } else if (!strcasecmp(v->name, "callprogress")) {
10582          if (ast_true(v->value))
10583             confp->chan.callprogress |= 1;
10584          else
10585             confp->chan.callprogress &= ~1;
10586       } else if (!strcasecmp(v->name, "faxdetect")) {
10587          if (!strcasecmp(v->value, "incoming")) {
10588             confp->chan.callprogress |= 4;
10589             confp->chan.callprogress &= ~2;
10590          } else if (!strcasecmp(v->value, "outgoing")) {
10591             confp->chan.callprogress &= ~4;
10592             confp->chan.callprogress |= 2;
10593          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
10594             confp->chan.callprogress |= 6;
10595          else
10596             confp->chan.callprogress &= ~6;
10597       } else if (!strcasecmp(v->name, "echocancel")) {
10598          if (!ast_strlen_zero(v->value)) {
10599             y = atoi(v->value);
10600          } else
10601             y = 0;
10602          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
10603             confp->chan.echocancel = y;
10604          else {
10605             confp->chan.echocancel = ast_true(v->value);
10606             if (confp->chan.echocancel)
10607                confp->chan.echocancel=128;
10608          }
10609       } else if (!strcasecmp(v->name, "echotraining")) {
10610          if (sscanf(v->value, "%d", &y) == 1) {
10611             if ((y < 10) || (y > 4000)) {
10612                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
10613             } else {
10614                confp->chan.echotraining = y;
10615             }
10616          } else if (ast_true(v->value)) {
10617             confp->chan.echotraining = 400;
10618          } else
10619             confp->chan.echotraining = 0;
10620       } else if (!strcasecmp(v->name, "hidecallerid")) {
10621          confp->chan.hidecallerid = ast_true(v->value);
10622       } else if (!strcasecmp(v->name, "hidecalleridname")) {
10623          confp->chan.hidecalleridname = ast_true(v->value);
10624       } else if (!strcasecmp(v->name, "pulsedial")) {
10625          confp->chan.pulse = ast_true(v->value);
10626       } else if (!strcasecmp(v->name, "callreturn")) {
10627          confp->chan.callreturn = ast_true(v->value);
10628       } else if (!strcasecmp(v->name, "callwaiting")) {
10629          confp->chan.callwaiting = ast_true(v->value);
10630       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
10631          confp->chan.callwaitingcallerid = ast_true(v->value);
10632       } else if (!strcasecmp(v->name, "context")) {
10633          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
10634       } else if (!strcasecmp(v->name, "language")) {
10635          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
10636       } else if (!strcasecmp(v->name, "progzone")) {
10637          ast_copy_string(progzone, v->value, sizeof(progzone));
10638       } else if (!strcasecmp(v->name, "mohinterpret") 
10639          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
10640          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
10641       } else if (!strcasecmp(v->name, "mohsuggest")) {
10642          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
10643       } else if (!strcasecmp(v->name, "stripmsd")) {
10644          confp->chan.stripmsd = atoi(v->value);
10645       } else if (!strcasecmp(v->name, "jitterbuffers")) {
10646          numbufs = atoi(v->value);
10647       } else if (!strcasecmp(v->name, "group")) {
10648          confp->chan.group = ast_get_group(v->value);
10649       } else if (!strcasecmp(v->name, "callgroup")) {
10650          confp->chan.callgroup = ast_get_group(v->value);
10651       } else if (!strcasecmp(v->name, "pickupgroup")) {
10652          confp->chan.pickupgroup = ast_get_group(v->value);
10653       } else if (!strcasecmp(v->name, "immediate")) {
10654          confp->chan.immediate = ast_true(v->value);
10655       } else if (!strcasecmp(v->name, "transfertobusy")) {
10656          confp->chan.transfertobusy = ast_true(v->value);
10657       } else if (!strcasecmp(v->name, "rxgain")) {
10658          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
10659             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
10660          }
10661       } else if (!strcasecmp(v->name, "txgain")) {
10662          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
10663             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
10664          }
10665       } else if (!strcasecmp(v->name, "tonezone")) {
10666          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
10667             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
10668          }
10669       } else if (!strcasecmp(v->name, "callerid")) {
10670          if (!strcasecmp(v->value, "asreceived")) {
10671             confp->chan.cid_num[0] = '\0';
10672             confp->chan.cid_name[0] = '\0';
10673          } else {
10674             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
10675          } 
10676       } else if (!strcasecmp(v->name, "fullname")) {
10677          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
10678       } else if (!strcasecmp(v->name, "cid_number")) {
10679          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
10680       } else if (!strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
10681          confp->chan.zaptrcallerid = ast_true(v->value);
10682       } else if (!strcasecmp(v->name, "restrictcid")) {
10683          confp->chan.restrictcid = ast_true(v->value);
10684       } else if (!strcasecmp(v->name, "usecallingpres")) {
10685          confp->chan.use_callingpres = ast_true(v->value);
10686       } else if (!strcasecmp(v->name, "accountcode")) {
10687          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
10688       } else if (!strcasecmp(v->name, "amaflags")) {
10689          y = ast_cdr_amaflags2int(v->value);
10690          if (y < 0) 
10691             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
10692          else
10693             confp->chan.amaflags = y;
10694       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
10695          confp->chan.polarityonanswerdelay = atoi(v->value);
10696       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
10697          confp->chan.answeronpolarityswitch = ast_true(v->value);
10698       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
10699          confp->chan.hanguponpolarityswitch = ast_true(v->value);
10700       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
10701          confp->chan.sendcalleridafter = atoi(v->value);
10702       } else if (!reload){ 
10703           if (!strcasecmp(v->name, "signalling")) {
10704             confp->chan.outsigmod = -1;
10705             if (!strcasecmp(v->value, "em")) {
10706                confp->chan.sig = SIG_EM;
10707             } else if (!strcasecmp(v->value, "em_e1")) {
10708                confp->chan.sig = SIG_EM_E1;
10709             } else if (!strcasecmp(v->value, "em_w")) {
10710                confp->chan.sig = SIG_EMWINK;
10711                confp->chan.radio = 0;
10712             } else if (!strcasecmp(v->value, "fxs_ls")) {
10713                confp->chan.sig = SIG_FXSLS;
10714                confp->chan.radio = 0;
10715             } else if (!strcasecmp(v->value, "fxs_gs")) {
10716                confp->chan.sig = SIG_FXSGS;
10717                confp->chan.radio = 0;
10718             } else if (!strcasecmp(v->value, "fxs_ks")) {
10719                confp->chan.sig = SIG_FXSKS;
10720                confp->chan.radio = 0;
10721             } else if (!strcasecmp(v->value, "fxo_ls")) {
10722                confp->chan.sig = SIG_FXOLS;
10723                confp->chan.radio = 0;
10724             } else if (!strcasecmp(v->value, "fxo_gs")) {
10725                confp->chan.sig = SIG_FXOGS;
10726                confp->chan.radio = 0;
10727             } else if (!strcasecmp(v->value, "fxo_ks")) {
10728                confp->chan.sig = SIG_FXOKS;
10729                confp->chan.radio = 0;
10730             } else if (!strcasecmp(v->value, "fxs_rx")) {
10731                confp->chan.sig = SIG_FXSKS;
10732                confp->chan.radio = 1;
10733             } else if (!strcasecmp(v->value, "fxo_rx")) {
10734                confp->chan.sig = SIG_FXOLS;
10735                confp->chan.radio = 1;
10736             } else if (!strcasecmp(v->value, "fxs_tx")) {
10737                confp->chan.sig = SIG_FXSLS;
10738                confp->chan.radio = 1;
10739             } else if (!strcasecmp(v->value, "fxo_tx")) {
10740                confp->chan.sig = SIG_FXOGS;
10741                confp->chan.radio = 1;
10742             } else if (!strcasecmp(v->value, "em_rx")) {
10743                confp->chan.sig = SIG_EM;
10744                confp->chan.radio = 1;
10745             } else if (!strcasecmp(v->value, "em_tx")) {
10746                confp->chan.sig = SIG_EM;
10747                confp->chan.radio = 1;
10748             } else if (!strcasecmp(v->value, "em_rxtx")) {
10749                confp->chan.sig = SIG_EM;
10750                confp->chan.radio = 2;
10751             } else if (!strcasecmp(v->value, "em_txrx")) {
10752                confp->chan.sig = SIG_EM;
10753                confp->chan.radio = 2;
10754             } else if (!strcasecmp(v->value, "sf")) {
10755                confp->chan.sig = SIG_SF;
10756                confp->chan.radio = 0;
10757             } else if (!strcasecmp(v->value, "sf_w")) {
10758                confp->chan.sig = SIG_SFWINK;
10759                confp->chan.radio = 0;
10760             } else if (!strcasecmp(v->value, "sf_featd")) {
10761                confp->chan.sig = SIG_FEATD;
10762                confp->chan.radio = 0;
10763             } else if (!strcasecmp(v->value, "sf_featdmf")) {
10764                confp->chan.sig = SIG_FEATDMF;
10765                confp->chan.radio = 0;
10766             } else if (!strcasecmp(v->value, "sf_featb")) {
10767                confp->chan.sig = SIG_SF_FEATB;
10768                confp->chan.radio = 0;
10769             } else if (!strcasecmp(v->value, "sf")) {
10770                confp->chan.sig = SIG_SF;
10771                confp->chan.radio = 0;
10772             } else if (!strcasecmp(v->value, "sf_rx")) {
10773                confp->chan.sig = SIG_SF;
10774                confp->chan.radio = 1;
10775             } else if (!strcasecmp(v->value, "sf_tx")) {
10776                confp->chan.sig = SIG_SF;
10777                confp->chan.radio = 1;
10778             } else if (!strcasecmp(v->value, "sf_rxtx")) {
10779                confp->chan.sig = SIG_SF;
10780                confp->chan.radio = 2;
10781             } else if (!strcasecmp(v->value, "sf_txrx")) {
10782                confp->chan.sig = SIG_SF;
10783                confp->chan.radio = 2;
10784             } else if (!strcasecmp(v->value, "featd")) {
10785                confp->chan.sig = SIG_FEATD;
10786                confp->chan.radio = 0;
10787             } else if (!strcasecmp(v->value, "featdmf")) {
10788                confp->chan.sig = SIG_FEATDMF;
10789                confp->chan.radio = 0;
10790             } else if (!strcasecmp(v->value, "featdmf_ta")) {
10791                confp->chan.sig = SIG_FEATDMF_TA;
10792                confp->chan.radio = 0;
10793             } else if (!strcasecmp(v->value, "e911")) {
10794                confp->chan.sig = SIG_E911;
10795                confp->chan.radio = 0;
10796             } else if (!strcasecmp(v->value, "fgccama")) {
10797                confp->chan.sig = SIG_FGC_CAMA;
10798                confp->chan.radio = 0;
10799             } else if (!strcasecmp(v->value, "fgccamamf")) {
10800                confp->chan.sig = SIG_FGC_CAMAMF;
10801                confp->chan.radio = 0;
10802             } else if (!strcasecmp(v->value, "featb")) {
10803                confp->chan.sig = SIG_FEATB;
10804                confp->chan.radio = 0;
10805 #ifdef HAVE_PRI
10806             } else if (!strcasecmp(v->value, "pri_net")) {
10807                confp->chan.radio = 0;
10808                confp->chan.sig = SIG_PRI;
10809                confp->pri.nodetype = PRI_NETWORK;
10810             } else if (!strcasecmp(v->value, "pri_cpe")) {
10811                confp->chan.sig = SIG_PRI;
10812                confp->chan.radio = 0;
10813                confp->pri.nodetype = PRI_CPE;
10814             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
10815                confp->chan.sig = SIG_GR303FXOKS;
10816                confp->chan.radio = 0;
10817                confp->pri.nodetype = PRI_NETWORK;
10818             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
10819                confp->chan.sig = SIG_GR303FXSKS;
10820                confp->chan.radio = 0;
10821                confp->pri.nodetype = PRI_CPE;
10822 #endif
10823             } else {
10824                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
10825             }
10826           } else if (!strcasecmp(v->name, "outsignalling")) {
10827             if (!strcasecmp(v->value, "em")) {
10828                confp->chan.outsigmod = SIG_EM;
10829             } else if (!strcasecmp(v->value, "em_e1")) {
10830                confp->chan.outsigmod = SIG_EM_E1;
10831             } else if (!strcasecmp(v->value, "em_w")) {
10832                confp->chan.outsigmod = SIG_EMWINK;
10833             } else if (!strcasecmp(v->value, "sf")) {
10834                confp->chan.outsigmod = SIG_SF;
10835             } else if (!strcasecmp(v->value, "sf_w")) {
10836                confp->chan.outsigmod = SIG_SFWINK;
10837             } else if (!strcasecmp(v->value, "sf_featd")) {
10838                confp->chan.outsigmod = SIG_FEATD;
10839             } else if (!strcasecmp(v->value, "sf_featdmf")) {
10840                confp->chan.outsigmod = SIG_FEATDMF;
10841             } else if (!strcasecmp(v->value, "sf_featb")) {
10842                confp->chan.outsigmod = SIG_SF_FEATB;
10843             } else if (!strcasecmp(v->value, "sf")) {
10844                confp->chan.outsigmod = SIG_SF;
10845             } else if (!strcasecmp(v->value, "featd")) {
10846                confp->chan.outsigmod = SIG_FEATD;
10847             } else if (!strcasecmp(v->value, "featdmf")) {
10848                confp->chan.outsigmod = SIG_FEATDMF;
10849             } else if (!strcasecmp(v->value, "featdmf_ta")) {
10850                confp->chan.outsigmod = SIG_FEATDMF_TA;
10851             } else if (!strcasecmp(v->value, "e911")) {
10852                confp->chan.outsigmod = SIG_E911;
10853             } else if (!strcasecmp(v->value, "fgccama")) {
10854                confp->chan.outsigmod = SIG_FGC_CAMA;
10855             } else if (!strcasecmp(v->value, "fgccamamf")) {
10856                confp->chan.outsigmod = SIG_FGC_CAMAMF;
10857             } else if (!strcasecmp(v->value, "featb")) {
10858                confp->chan.outsigmod = SIG_FEATB;
10859             } else {
10860                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
10861             }
10862 #ifdef HAVE_PRI
10863          } else if (!strcasecmp(v->name, "pridialplan")) {
10864             if (!strcasecmp(v->value, "national")) {
10865                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
10866             } else if (!strcasecmp(v->value, "unknown")) {
10867                confp->pri.dialplan = PRI_UNKNOWN + 1;
10868             } else if (!strcasecmp(v->value, "private")) {
10869                confp->pri.dialplan = PRI_PRIVATE + 1;
10870             } else if (!strcasecmp(v->value, "international")) {
10871                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
10872             } else if (!strcasecmp(v->value, "local")) {
10873                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
10874             } else if (!strcasecmp(v->value, "dynamic")) {
10875                confp->pri.dialplan = -1;
10876             } else {
10877                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
10878             }
10879          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
10880             if (!strcasecmp(v->value, "national")) {
10881                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
10882             } else if (!strcasecmp(v->value, "unknown")) {
10883                confp->pri.localdialplan = PRI_UNKNOWN + 1;
10884             } else if (!strcasecmp(v->value, "private")) {
10885                confp->pri.localdialplan = PRI_PRIVATE + 1;
10886             } else if (!strcasecmp(v->value, "international")) {
10887                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
10888             } else if (!strcasecmp(v->value, "local")) {
10889                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
10890             } else if (!strcasecmp(v->value, "dynamic")) {
10891                confp->pri.localdialplan = -1;
10892             } else {
10893                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
10894             }
10895          } else if (!strcasecmp(v->name, "switchtype")) {
10896             if (!strcasecmp(v->value, "national")) 
10897                confp->pri.switchtype = PRI_SWITCH_NI2;
10898             else if (!strcasecmp(v->value, "ni1"))
10899                confp->pri.switchtype = PRI_SWITCH_NI1;
10900             else if (!strcasecmp(v->value, "dms100"))
10901                confp->pri.switchtype = PRI_SWITCH_DMS100;
10902             else if (!strcasecmp(v->value, "4ess"))
10903                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
10904             else if (!strcasecmp(v->value, "5ess"))
10905                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
10906             else if (!strcasecmp(v->value, "euroisdn"))
10907                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
10908             else if (!strcasecmp(v->value, "qsig"))
10909                confp->pri.switchtype = PRI_SWITCH_QSIG;
10910             else {
10911                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
10912                return -1;
10913             }
10914          } else if (!strcasecmp(v->name, "nsf")) {
10915             if (!strcasecmp(v->value, "sdn"))
10916                confp->pri.nsf = PRI_NSF_SDN;
10917             else if (!strcasecmp(v->value, "megacom"))
10918                confp->pri.nsf = PRI_NSF_MEGACOM;
10919             else if (!strcasecmp(v->value, "tollfreemegacom"))
10920                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
10921             else if (!strcasecmp(v->value, "accunet"))
10922                confp->pri.nsf = PRI_NSF_ACCUNET;
10923             else if (!strcasecmp(v->value, "none"))
10924                confp->pri.nsf = PRI_NSF_NONE;
10925             else {
10926                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
10927                confp->pri.nsf = PRI_NSF_NONE;
10928             }
10929          } else if (!strcasecmp(v->name, "priindication")) {
10930             if (!strcasecmp(v->value, "outofband"))
10931                confp->chan.priindication_oob = 1;
10932             else if (!strcasecmp(v->value, "inband"))
10933                confp->chan.priindication_oob = 0;
10934             else
10935                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
10936                   v->value, v->lineno);
10937          } else if (!strcasecmp(v->name, "priexclusive")) {
10938             confp->chan.priexclusive = ast_true(v->value);
10939          } else if (!strcasecmp(v->name, "internationalprefix")) {
10940             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
10941          } else if (!strcasecmp(v->name, "nationalprefix")) {
10942             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
10943          } else if (!strcasecmp(v->name, "localprefix")) {
10944             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
10945          } else if (!strcasecmp(v->name, "privateprefix")) {
10946             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
10947          } else if (!strcasecmp(v->name, "unknownprefix")) {
10948             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
10949          } else if (!strcasecmp(v->name, "resetinterval")) {
10950             if (!strcasecmp(v->value, "never"))
10951                confp->pri.resetinterval = -1;
10952             else if (atoi(v->value) >= 60)
10953                confp->pri.resetinterval = atoi(v->value);
10954             else
10955                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
10956                   v->value, v->lineno);
10957          } else if (!strcasecmp(v->name, "minunused")) {
10958             confp->pri.minunused = atoi(v->value);
10959          } else if (!strcasecmp(v->name, "minidle")) {
10960             confp->pri.minidle = atoi(v->value); 
10961          } else if (!strcasecmp(v->name, "idleext")) {
10962             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
10963          } else if (!strcasecmp(v->name, "idledial")) {
10964             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
10965          } else if (!strcasecmp(v->name, "overlapdial")) {
10966             confp->pri.overlapdial = ast_true(v->value);
10967          } else if (!strcasecmp(v->name, "pritimer")) {
10968 #ifdef PRI_GETSET_TIMERS
10969             char *timerc, *c;
10970             int timer, timeridx;
10971             c = v->value;
10972             timerc = strsep(&c, ",");
10973             if (timerc) {
10974                timer = atoi(c);
10975                if (!timer)
10976                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
10977                else {
10978                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
10979                      pritimers[timeridx] = timer;
10980                   else
10981                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
10982                }
10983             } else
10984                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
10985 
10986          } else if (!strcasecmp(v->name, "facilityenable")) {
10987             confp->pri.facilityenable = ast_true(v->value);
10988 #endif /* PRI_GETSET_TIMERS */
10989 #endif /* HAVE_PRI */
10990          } else if (!strcasecmp(v->name, "cadence")) {
10991             /* setup to scan our argument */
10992             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
10993             int i;
10994             struct zt_ring_cadence new_cadence;
10995             int cid_location = -1;
10996             int firstcadencepos = 0;
10997             char original_args[80];
10998             int cadence_is_ok = 1;
10999 
11000             ast_copy_string(original_args, v->value, sizeof(original_args));
11001             /* 16 cadences allowed (8 pairs) */
11002             element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
11003    
11004             /* Cadence must be even (on/off) */
11005             if (element_count % 2 == 1) {
11006                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11007                cadence_is_ok = 0;
11008             }
11009    
11010             /* Ring cadences cannot be negative */
11011             for (i = 0; i < element_count; i++) {
11012                if (c[i] == 0) {
11013                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11014                   cadence_is_ok = 0;
11015                   break;
11016                } else if (c[i] < 0) {
11017                   if (i % 2 == 1) {
11018                      /* Silence duration, negative possibly okay */
11019                      if (cid_location == -1) {
11020                         cid_location = i;
11021                         c[i] *= -1;
11022                      } else {
11023                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11024                         cadence_is_ok = 0;
11025                         break;
11026                      }
11027                   } else {
11028                      if (firstcadencepos == 0) {
11029                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
11030                                  /* duration will be passed negative to the zaptel driver */
11031                      } else {
11032                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11033                         cadence_is_ok = 0;
11034                         break;
11035                      }
11036                   }
11037                }
11038             }
11039    
11040             /* Substitute our scanned cadence */
11041             for (i = 0; i < 16; i++) {
11042                new_cadence.ringcadence[i] = c[i];
11043             }
11044    
11045             if (cadence_is_ok) {
11046                /* ---we scanned it without getting annoyed; now some sanity checks--- */
11047                if (element_count < 2) {
11048                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11049                } else {
11050                   if (cid_location == -1) {
11051                      /* user didn't say; default to first pause */
11052                      cid_location = 1;
11053                   } else {
11054                      /* convert element_index to cidrings value */
11055                      cid_location = (cid_location + 1) / 2;
11056                   }
11057                   /* ---we like their cadence; try to install it--- */
11058                   if (!user_has_defined_cadences++)
11059                      /* this is the first user-defined cadence; clear the default user cadences */
11060                      num_cadence = 0;
11061                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
11062                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11063                   else {
11064                      cadences[num_cadence] = new_cadence;
11065                      cidrings[num_cadence++] = cid_location;
11066                      if (option_verbose > 2)
11067                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11068                   }
11069                }
11070             }
11071          } else if (!strcasecmp(v->name, "ringtimeout")) {
11072             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11073          } else if (!strcasecmp(v->name, "prewink")) {
11074             confp->timing.prewinktime = atoi(v->value);
11075          } else if (!strcasecmp(v->name, "preflash")) {
11076             confp->timing.preflashtime = atoi(v->value);
11077          } else if (!strcasecmp(v->name, "wink")) {
11078             confp->timing.winktime = atoi(v->value);
11079          } else if (!strcasecmp(v->name, "flash")) {
11080             confp->timing.flashtime = atoi(v->value);
11081          } else if (!strcasecmp(v->name, "start")) {
11082             confp->timing.starttime = atoi(v->value);
11083          } else if (!strcasecmp(v->name, "rxwink")) {
11084             confp->timing.rxwinktime = atoi(v->value);
11085          } else if (!strcasecmp(v->name, "rxflash")) {
11086             confp->timing.rxflashtime = atoi(v->value);
11087          } else if (!strcasecmp(v->name, "debounce")) {
11088             confp->timing.debouncetime = atoi(v->value);
11089          } else if (!strcasecmp(v->name, "toneduration")) {
11090             int toneduration;
11091             int ctlfd;
11092             int res;
11093             struct zt_dialparams dps;
11094 
11095             ctlfd = open("/dev/zap/ctl", O_RDWR);
11096             if (ctlfd == -1) {
11097                ast_log(LOG_ERROR, "Unable to open /dev/zap/ctl to set toneduration\n");
11098                return -1;
11099             }
11100 
11101             toneduration = atoi(v->value);
11102             if (toneduration > -1) {
11103                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11104                res = ioctl(ctlfd, ZT_SET_DIALPARAMS, &dps);
11105                if (res < 0) {
11106                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms\n", toneduration);
11107                   return -1;
11108                }
11109             }
11110             close(ctlfd);
11111          } else if (!strcasecmp(v->name, "defaultcic")) {
11112             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11113          } else if (!strcasecmp(v->name, "defaultozz")) {
11114             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11115          } 
11116       } else if (!skipchannels)
11117          ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11118    }
11119    if (zapchan[0]) { 
11120       /* The user has set 'zapchan' */
11121       /*< \todo pass proper line number instead of 0 */
11122       if (build_channels(*confp, 0, zapchan, reload, 0, &found_pseudo)) {
11123          return -1;
11124       }
11125    }
11126    /*< \todo why check for the pseudo in the per-channel section.
11127     * Any actual use for manual setup of the pseudo channel? */
11128    if (!found_pseudo && reload == 0) {
11129       /* Make sure pseudo isn't a member of any groups if
11130          we're automatically making it. */   
11131       
11132       confp->chan.group = 0;
11133       confp->chan.callgroup = 0;
11134       confp->chan.pickupgroup = 0;
11135 
11136       tmp = mkintf(CHAN_PSEUDO, *confp, NULL, reload);
11137 
11138       if (tmp) {
11139          if (option_verbose > 2)
11140             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11141       } else {
11142          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11143       }
11144    }
11145    return 0;
11146 }

static int reload ( void   )  [static]

Definition at line 11427 of file chan_zap.c.

References ast_log(), LOG_WARNING, and setup_zap().

11428 {
11429    int res = 0;
11430 
11431    res = setup_zap(1);
11432    if (res) {
11433       ast_log(LOG_WARNING, "Reload of chan_zap.so is unsuccessful!\n");
11434       return -1;
11435    }
11436    return 0;
11437 }

static int reset_conf ( struct zt_pvt p  )  [static]

Definition at line 1336 of file chan_zap.c.

References ast_log(), zt_pvt::channel, zt_pvt::confno, zt_subchannel::curconf, LOG_WARNING, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by zt_hangup().

01337 {
01338    ZT_CONFINFO zi;
01339    memset(&zi, 0, sizeof(zi));
01340    p->confno = -1;
01341    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01342    if (p->subs[SUB_REAL].zfd > -1) {
01343       if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &zi))
01344          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d!\n", p->channel);
01345    }
01346    return 0;
01347 }

static int restart_monitor ( void   )  [static]

Definition at line 6951 of file chan_zap.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, and LOG_WARNING.

06952 {
06953    pthread_attr_t attr;
06954    pthread_attr_init(&attr);
06955    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06956    /* If we're supposed to be stopped -- stay stopped */
06957    if (monitor_thread == AST_PTHREADT_STOP)
06958       return 0;
06959    ast_mutex_lock(&monlock);
06960    if (monitor_thread == pthread_self()) {
06961       ast_mutex_unlock(&monlock);
06962       ast_log(LOG_WARNING, "Cannot kill myself\n");
06963       return -1;
06964    }
06965    if (monitor_thread != AST_PTHREADT_NULL) {
06966       /* Wake up the thread */
06967       pthread_kill(monitor_thread, SIGURG);
06968    } else {
06969       /* Start a new monitor */
06970       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
06971          ast_mutex_unlock(&monlock);
06972          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
06973          pthread_attr_destroy(&attr);
06974          return -1;
06975       }
06976    }
06977    ast_mutex_unlock(&monlock);
06978    pthread_attr_destroy(&attr);
06979    return 0;
06980 }

static int restore_conference ( struct zt_pvt p  )  [static]

Definition at line 1668 of file chan_zap.c.

References ast_log(), LOG_DEBUG, LOG_WARNING, option_debug, zt_pvt::saveconf, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by send_callerid(), zt_handle_event(), and zt_read().

01669 {
01670    int res;
01671    if (p->saveconf.confmode) {
01672       res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &p->saveconf);
01673       p->saveconf.confmode = 0;
01674       if (res) {
01675          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01676          return -1;
01677       }
01678    }
01679    if (option_debug)
01680       ast_log(LOG_DEBUG, "Restored conferencing\n");
01681    return 0;
01682 }

static int restore_gains ( struct zt_pvt p  )  [static]

Definition at line 1595 of file chan_zap.c.

References ast_log(), zt_pvt::law, LOG_WARNING, zt_pvt::rxgain, set_actual_gain(), SUB_REAL, zt_pvt::subs, zt_pvt::txgain, and zt_subchannel::zfd.

Referenced by ss_thread(), and zt_hangup().

01596 {
01597    int res;
01598 
01599    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
01600    if (res) {
01601       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01602       return -1;
01603    }
01604 
01605    return 0;
01606 }

static int save_conference ( struct zt_pvt p  )  [static]

Definition at line 1640 of file chan_zap.c.

References ast_log(), LOG_DEBUG, LOG_WARNING, option_debug, zt_pvt::saveconf, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by zt_callwait(), and zt_handle_event().

01641 {
01642    struct zt_confinfo c;
01643    int res;
01644    if (p->saveconf.confmode) {
01645       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01646       return -1;
01647    }
01648    p->saveconf.chan = 0;
01649    res = ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &p->saveconf);
01650    if (res) {
01651       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01652       p->saveconf.confmode = 0;
01653       return -1;
01654    }
01655    c.chan = 0;
01656    c.confno = 0;
01657    c.confmode = ZT_CONF_NORMAL;
01658    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &c);
01659    if (res) {
01660       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01661       return -1;
01662    }
01663    if (option_debug)
01664       ast_log(LOG_DEBUG, "Disabled conferencing\n");
01665    return 0;
01666 }

static int send_callerid ( struct zt_pvt p  )  [static]

Definition at line 1708 of file chan_zap.c.

References ast_log(), zt_pvt::callwaitcas, CIDCW_EXPIRE_SAMPLES, zt_pvt::cidcwexpire, zt_pvt::cidlen, zt_pvt::cidpos, zt_pvt::cidspill, free, zt_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, zt_pvt::subs, zt_subchannel::zfd, and zt_setlinear().

Referenced by send_cwcidspill(), zt_call(), zt_callwait(), and zt_read().

01709 {
01710    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
01711    int res;
01712    /* Take out of linear mode if necessary */
01713    if (p->subs[SUB_REAL].linear) {
01714       p->subs[SUB_REAL].linear = 0;
01715       zt_setlinear(p->subs[SUB_REAL].zfd, 0);
01716    }
01717    while (p->cidpos < p->cidlen) {
01718       res = write(p->subs[SUB_REAL].zfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01719       if (res < 0) {
01720          if (errno == EAGAIN)
01721             return 0;
01722          else {
01723             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01724             return -1;
01725          }
01726       }
01727       if (!res)
01728          return 0;
01729       p->cidpos += res;
01730    }
01731    free(p->cidspill);
01732    p->cidspill = NULL;
01733    if (p->callwaitcas) {
01734       /* Wait for CID/CW to expire */
01735       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01736    } else
01737       restore_conference(p);
01738    return 0;
01739 }

static int send_cwcidspill ( struct zt_pvt p  )  [static]

Definition at line 1686 of file chan_zap.c.

References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verbose(), zt_pvt::callwait_name, zt_pvt::callwait_num, zt_pvt::callwaitcas, zt_pvt::cidcwexpire, zt_pvt::cidlen, zt_pvt::cidpos, zt_pvt::cidspill, MAX_CALLERID_SIZE, option_verbose, READ_SIZE, send_callerid(), and VERBOSE_PREFIX_3.

Referenced by zt_handle_dtmfup().

01687 {
01688    p->callwaitcas = 0;
01689    p->cidcwexpire = 0;
01690    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01691       return -1;
01692    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01693    /* Make sure we account for the end */
01694    p->cidlen += READ_SIZE * 4;
01695    p->cidpos = 0;
01696    send_callerid(p);
01697    if (option_verbose > 2)
01698       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01699    return 0;
01700 }

static int set_actual_gain ( int  fd,
int  chan,
float  rxgain,
float  txgain,
int  law 
) [static]

Definition at line 1576 of file chan_zap.c.

References set_actual_rxgain(), and set_actual_txgain().

Referenced by bump_gains(), mkintf(), restore_gains(), and zt_call().

01577 {
01578    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01579 }

static int set_actual_rxgain ( int  fd,
int  chan,
float  gain,
int  law 
) [static]

Definition at line 1558 of file chan_zap.c.

References ast_log(), fill_rxgain(), and LOG_DEBUG.

Referenced by set_actual_gain(), and zt_setoption().

01559 {
01560    struct zt_gains g;
01561    int res;
01562 
01563    memset(&g, 0, sizeof(g));
01564    g.chan = chan;
01565    res = ioctl(fd, ZT_GETGAINS, &g);
01566    if (res) {
01567       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01568       return res;
01569    }
01570 
01571    fill_rxgain(&g, gain, law);
01572 
01573    return ioctl(fd, ZT_SETGAINS, &g);
01574 }

static int set_actual_txgain ( int  fd,
int  chan,
float  gain,
int  law 
) [static]

Definition at line 1539 of file chan_zap.c.

References ast_log(), fill_txgain(), LOG_DEBUG, and option_debug.

Referenced by set_actual_gain(), and zt_setoption().

01540 {
01541    struct zt_gains g;
01542    int res;
01543 
01544    memset(&g, 0, sizeof(g));
01545    g.chan = chan;
01546    res = ioctl(fd, ZT_GETGAINS, &g);
01547    if (res) {
01548       if (option_debug)
01549          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01550       return res;
01551    }
01552 
01553    fill_txgain(&g, gain, law);
01554 
01555    return ioctl(fd, ZT_SETGAINS, &g);
01556 }

static int setup_zap ( int  reload  )  [static]

Todo:
At this point we should probably duplicate conf, and pass a copy, to prevent one section from affecting another

Definition at line 11148 of file chan_zap.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), global_jbconf, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, option_verbose, process_zap(), restart_monitor(), ast_variable::value, VERBOSE_PREFIX_2, and zt_chan_conf_default().

Referenced by load_module(), reload(), and zap_restart().

11149 {
11150    struct ast_config *cfg;
11151    struct ast_variable *v;
11152    struct zt_chan_conf conf = zt_chan_conf_default();
11153    int res;
11154 
11155 #ifdef HAVE_PRI
11156    char *c;
11157    int spanno;
11158    int i, x;
11159    int logicalspan;
11160    int trunkgroup;
11161    int dchannels[NUM_DCHANS];
11162 #endif
11163 
11164    cfg = ast_config_load(config);
11165 
11166    /* Error if we have no config file */
11167    if (!cfg) {
11168       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
11169       return 0;
11170    }
11171 
11172    /* It's a little silly to lock it, but we mind as well just to be sure */
11173    ast_mutex_lock(&iflock);
11174 #ifdef HAVE_PRI
11175    if (!reload) {
11176       /* Process trunkgroups first */
11177       v = ast_variable_browse(cfg, "trunkgroups");
11178       while (v) {
11179          if (!strcasecmp(v->name, "trunkgroup")) {
11180             trunkgroup = atoi(v->value);
11181             if (trunkgroup > 0) {
11182                if ((c = strchr(v->value, ','))) {
11183                   i = 0;
11184                   memset(dchannels, 0, sizeof(dchannels));
11185                   while (c && (i < NUM_DCHANS)) {
11186                      dchannels[i] = atoi(c + 1);
11187                      if (dchannels[i] < 0) {
11188                         ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of zapata.conf\n", trunkgroup, v->lineno);
11189                      } else
11190                         i++;
11191                      c = strchr(c + 1, ',');
11192                   }
11193                   if (i) {
11194                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11195                         ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of zapata.conf\n", trunkgroup, dchannels[0], v->lineno);
11196                      } else if (option_verbose > 1)
11197                         ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
11198                   } else
11199                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
11200                } else
11201                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
11202             } else
11203                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
11204          } else if (!strcasecmp(v->name, "spanmap")) {
11205             spanno = atoi(v->value);
11206             if (spanno > 0) {
11207                if ((c = strchr(v->value, ','))) {
11208                   trunkgroup = atoi(c + 1);
11209                   if (trunkgroup > 0) {
11210                      if ((c = strchr(c + 1, ','))) 
11211                         logicalspan = atoi(c + 1);
11212                      else
11213                         logicalspan = 0;
11214                      if (logicalspan >= 0) {
11215                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11216                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11217                         } else if (option_verbose > 1) 
11218                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11219                      } else
11220                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
11221                   } else
11222                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
11223                } else
11224                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
11225             } else
11226                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
11227          } else {
11228             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11229          }
11230          v = v->next;
11231       }
11232    }
11233 #endif
11234    
11235    /* Copy the default jb config over global_jbconf */
11236    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11237 
11238    v = ast_variable_browse(cfg, "channels");
11239    res = process_zap(&conf, v, reload, 0);
11240    ast_mutex_unlock(&iflock);
11241    ast_config_destroy(cfg);
11242    if (res)
11243       return res;
11244    cfg = ast_config_load("users.conf");
11245    if (cfg) {
11246       char *cat;
11247       const char *chans;
11248       process_zap(&conf, ast_variable_browse(cfg, "general"), 1, 1);
11249       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11250          if (!strcasecmp(cat, "general"))
11251             continue;
11252          chans = ast_variable_retrieve(cfg, cat, "zapchan");
11253          if (!ast_strlen_zero(chans)) {
11254             /** \todo At this point we should probably 
11255              * duplicate conf, and pass a copy, to prevent 
11256              * one section from affecting another
11257              */
11258             process_zap(&conf, ast_variable_browse(cfg, cat), reload, 0);
11259          }
11260       }
11261       ast_config_destroy(cfg);
11262    }
11263 #ifdef HAVE_PRI
11264    if (!reload) {
11265       for (x = 0; x < NUM_SPANS; x++) {
11266          if (pris[x].pvts[0]) {
11267             if (start_pri(pris + x)) {
11268                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11269                return -1;
11270             } else if (option_verbose > 1)
11271                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11272          }
11273       }
11274    }
11275 #endif
11276    /* And start the monitor for the first time */
11277    restart_monitor();
11278    return 0;
11279 }

static void * ss_thread ( void *  data  )  [static]

Definition at line 5400 of file chan_zap.c.

References ast_channel::_state, alloc_sub(), ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_db_put(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_destroy(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verbose(), ast_waitfor(), ast_waitfordigit(), ast_waitstream(), ASTOBJ_UNREF, bump_gains(), zt_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, zt_pvt::callreturn, zt_pvt::callwaiting, zt_pvt::cancallforward, zt_pvt::canpark, zt_pvt::channel, ast_channel::cid, ast_callerid::cid_name, zt_pvt::cid_name, ast_callerid::cid_num, zt_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, zt_pvt::cid_signalling, zt_pvt::cid_start, CID_START_POLARITY, CID_START_RING, zt_pvt::context, ast_channel::context, ringContextData::contextData, zt_pvt::defcontext, zt_pvt::dnd, zt_pvt::dop, zt_pvt::drings, zt_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, zt_pvt::dtmfrelax, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, zt_pvt::exten, exten, ast_frame::frametype, free, func, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, zt_pvt::hardwaredtmf, zt_pvt::hidecallerid, zt_pvt::immediate, ISTRUNK, zt_pvt::lastcid_num, len, zt_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event(), my_getsigstr(), name, NEED_MFDETECT, option_debug, option_verbose, zt_pvt::owner, zt_subchannel::owner, pbx_builtin_setvar_helper(), restore_gains(), distRingData::ring, zt_distRings::ringContext, zt_distRings::ringnum, ast_channel::rings, zt_pvt::ringt, zt_pvt::ringt_base, zt_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, zt_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, zt_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, zt_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), zt_pvt::use_callerid, zt_pvt::use_smdi, zt_pvt::usedistinctiveringdetection, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, zt_subchannel::zfd, zt_enable_ec(), zt_get_event(), zt_get_index(), zt_set_hook(), zt_setlinear(), zt_wait_event(), and zt_wink().

Referenced by handle_init_event(), and zt_handle_event().

05401 {
05402    struct ast_channel *chan = data;
05403    struct zt_pvt *p = chan->tech_pvt;
05404    char exten[AST_MAX_EXTENSION] = "";
05405    char exten2[AST_MAX_EXTENSION] = "";
05406    unsigned char buf[256];
05407    char dtmfcid[300];
05408    char dtmfbuf[300];
05409    struct callerid_state *cs = NULL;
05410    char *name = NULL, *number = NULL;
05411    int distMatches;
05412    int curRingData[3];
05413    int receivedRingT;
05414    int counter1;
05415    int counter;
05416    int samples = 0;
05417    struct ast_smdi_md_message *smdi_msg = NULL;
05418    int flags;
05419    int i;
05420    int timeout;
05421    int getforward = 0;
05422    char *s1, *s2;
05423    int len = 0;
05424    int res;
05425    int index;
05426 
05427    /* in the bizarre case where the channel has become a zombie before we
05428       even get started here, abort safely
05429    */
05430    if (!p) {
05431       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05432       ast_hangup(chan);
05433       return NULL;
05434    }
05435 
05436    if (option_verbose > 2) 
05437       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05438    index = zt_get_index(chan, p, 1);
05439    if (index < 0) {
05440       ast_log(LOG_WARNING, "Huh?\n");
05441       ast_hangup(chan);
05442       return NULL;
05443    }
05444    if (p->dsp)
05445       ast_dsp_digitreset(p->dsp);
05446    switch (p->sig) {
05447 #ifdef HAVE_PRI
05448    case SIG_PRI:
05449       /* Now loop looking for an extension */
05450       ast_copy_string(exten, p->exten, sizeof(exten));
05451       len = strlen(exten);
05452       res = 0;
05453       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05454          if (len && !ast_ignore_pattern(chan->context, exten))
05455             tone_zone_play_tone(p->subs[index].zfd, -1);
05456          else
05457             tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
05458          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05459             timeout = matchdigittimeout;
05460          else
05461             timeout = gendigittimeout;
05462          res = ast_waitfordigit(chan, timeout);
05463          if (res < 0) {
05464             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05465             ast_hangup(chan);
05466             return NULL;
05467          } else if (res) {
05468             exten[len++] = res;
05469             exten[len] = '\0';
05470          } else
05471             break;
05472       }
05473       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
05474       if (ast_strlen_zero(exten)) {
05475          if (option_verbose > 2)
05476             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05477          exten[0] = 's';
05478          exten[1] = '\0';
05479       }
05480       tone_zone_play_tone(p->subs[index].zfd, -1);
05481       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05482          /* Start the real PBX */
05483          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05484          if (p->dsp) ast_dsp_digitreset(p->dsp);
05485          zt_enable_ec(p);
05486          ast_setstate(chan, AST_STATE_RING);
05487          res = ast_pbx_run(chan);
05488          if (res) {
05489             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05490          }
05491       } else {
05492          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05493          chan->hangupcause = AST_CAUSE_UNALLOCATED;
05494          ast_hangup(chan);
05495          p->exten[0] = '\0';
05496          /* Since we send release complete here, we won't get one */
05497          p->call = NULL;
05498       }
05499       return NULL;
05500       break;
05501 #endif
05502    case SIG_FEATD:
05503    case SIG_FEATDMF:
05504    case SIG_FEATDMF_TA:
05505    case SIG_E911:
05506    case SIG_FGC_CAMAMF:
05507    case SIG_FEATB:
05508    case SIG_EMWINK:
05509    case SIG_SF_FEATD:
05510    case SIG_SF_FEATDMF:
05511    case SIG_SF_FEATB:
05512    case SIG_SFWINK:
05513       if (zt_wink(p, index))  
05514          return NULL;
05515       /* Fall through */
05516    case SIG_EM:
05517    case SIG_EM_E1:
05518    case SIG_SF:
05519    case SIG_FGC_CAMA:
05520       res = tone_zone_play_tone(p->subs[index].zfd, -1);
05521       if (p->dsp)
05522          ast_dsp_digitreset(p->dsp);
05523       /* set digit mode appropriately */
05524       if (p->dsp) {
05525          if (NEED_MFDETECT(p))
05526             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
05527          else 
05528             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05529       }
05530       memset(dtmfbuf, 0, sizeof(dtmfbuf));
05531       /* Wait for the first digit only if immediate=no */
05532       if (!p->immediate)
05533          /* Wait for the first digit (up to 5 seconds). */
05534          res = ast_waitfordigit(chan, 5000);
05535       else
05536          res = 0;
05537       if (res > 0) {
05538          /* save first char */
05539          dtmfbuf[0] = res;
05540          switch (p->sig) {
05541          case SIG_FEATD:
05542          case SIG_SF_FEATD:
05543             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05544             if (res > 0)
05545                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05546             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05547             break;
05548          case SIG_FEATDMF_TA:
05549             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05550             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05551             if (zt_wink(p, index)) return NULL;
05552             dtmfbuf[0] = 0;
05553             /* Wait for the first digit (up to 5 seconds). */
05554             res = ast_waitfordigit(chan, 5000);
05555             if (res <= 0) break;
05556             dtmfbuf[0] = res;
05557             /* fall through intentionally */
05558          case SIG_FEATDMF:
05559          case SIG_E911:
05560          case SIG_FGC_CAMAMF:
05561          case SIG_SF_FEATDMF:
05562             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05563             /* if international caca, do it again to get real ANO */
05564             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
05565             {
05566                if (zt_wink(p, index)) return NULL;
05567                dtmfbuf[0] = 0;
05568                /* Wait for the first digit (up to 5 seconds). */
05569                res = ast_waitfordigit(chan, 5000);
05570                if (res <= 0) break;
05571                dtmfbuf[0] = res;
05572                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05573             }
05574             if (res > 0) {
05575                /* if E911, take off hook */
05576                if (p->sig == SIG_E911)
05577                   zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
05578                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
05579             }
05580             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05581             break;
05582          case SIG_FEATB:
05583          case SIG_SF_FEATB:
05584             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05585             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05586             break;
05587          case SIG_EMWINK:
05588             /* if we received a '*', we are actually receiving Feature Group D
05589                dial syntax, so use that mode; otherwise, fall through to normal
05590                mode
05591             */
05592             if (res == '*') {
05593                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05594                if (res > 0)
05595                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05596                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05597                break;
05598             }
05599          default:
05600             /* If we got the first digit, get the rest */
05601             len = 1;
05602             dtmfbuf[len] = '\0';
05603             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05604                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05605                   timeout = matchdigittimeout;
05606                } else {
05607                   timeout = gendigittimeout;
05608                }
05609                res = ast_waitfordigit(chan, timeout);
05610                if (res < 0) {
05611                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05612                   ast_hangup(chan);
05613                   return NULL;
05614                } else if (res) {
05615                   dtmfbuf[len++] = res;
05616                   dtmfbuf[len] = '\0';
05617                } else {
05618                   break;
05619                }
05620             }
05621             break;
05622          }
05623       }
05624       if (res == -1) {
05625          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
05626          ast_hangup(chan);
05627          return NULL;
05628       } else if (res < 0) {
05629          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
05630          ast_hangup(chan);
05631          return NULL;
05632       }
05633 
05634       if (p->sig == SIG_FGC_CAMA) {
05635          char anibuf[100];
05636 
05637          if (ast_safe_sleep(chan,1000) == -1) {
05638                            ast_hangup(chan);
05639                            return NULL;
05640          }
05641                         zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
05642                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
05643                         res = my_getsigstr(chan, anibuf, "#", 10000);
05644                         if ((res > 0) && (strlen(anibuf) > 2)) {
05645             if (anibuf[strlen(anibuf) - 1] == '#')
05646                anibuf[strlen(anibuf) - 1] = 0;
05647             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
05648          }
05649                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05650       }
05651 
05652       ast_copy_string(exten, dtmfbuf, sizeof(exten));
05653       if (ast_strlen_zero(exten))
05654          ast_copy_string(exten, "s", sizeof(exten));
05655       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
05656          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
05657          if (exten[0] == '*') {
05658             char *stringp=NULL;
05659             ast_copy_string(exten2, exten, sizeof(exten2));
05660             /* Parse out extension and callerid */
05661             stringp=exten2 +1;
05662             s1 = strsep(&stringp, "*");
05663             s2 = strsep(&stringp, "*");
05664             if (s2) {
05665                if (!ast_strlen_zero(p->cid_num))
05666                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05667                else
05668                   ast_set_callerid(chan, s1, NULL, s1);
05669                ast_copy_string(exten, s2, sizeof(exten));
05670             } else
05671                ast_copy_string(exten, s1, sizeof(exten));
05672          } else if (p->sig == SIG_FEATD)
05673             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05674       }
05675       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05676          if (exten[0] == '*') {
05677             char *stringp=NULL;
05678             ast_copy_string(exten2, exten, sizeof(exten2));
05679             /* Parse out extension and callerid */
05680             stringp=exten2 +1;
05681             s1 = strsep(&stringp, "#");
05682             s2 = strsep(&stringp, "#");
05683             if (s2) {
05684                if (!ast_strlen_zero(p->cid_num))
05685                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05686                else
05687                   if (*(s1 + 2))
05688                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
05689                ast_copy_string(exten, s2 + 1, sizeof(exten));
05690             } else
05691                ast_copy_string(exten, s1 + 2, sizeof(exten));
05692          } else
05693             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05694       }
05695       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
05696          if (exten[0] == '*') {
05697             char *stringp=NULL;
05698             ast_copy_string(exten2, exten, sizeof(exten2));
05699             /* Parse out extension and callerid */
05700             stringp=exten2 +1;
05701             s1 = strsep(&stringp, "#");
05702             s2 = strsep(&stringp, "#");
05703             if (s2 && (*(s2 + 1) == '0')) {
05704                if (*(s2 + 2))
05705                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
05706             }
05707             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
05708             else ast_copy_string(exten, "911", sizeof(exten));
05709          } else
05710             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05711       }
05712       if (p->sig == SIG_FEATB) {
05713          if (exten[0] == '*') {
05714             char *stringp=NULL;
05715             ast_copy_string(exten2, exten, sizeof(exten2));
05716             /* Parse out extension and callerid */
05717             stringp=exten2 +1;
05718             s1 = strsep(&stringp, "#");
05719             ast_copy_string(exten, exten2 + 1, sizeof(exten));
05720          } else
05721             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05722       }
05723       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05724          zt_wink(p, index);
05725                         /* some switches require a minimum guard time between
05726                            the last FGD wink and something that answers
05727                            immediately. This ensures it */
05728                         if (ast_safe_sleep(chan,100)) return NULL;
05729       }
05730       zt_enable_ec(p);
05731       if (NEED_MFDETECT(p)) {
05732          if (p->dsp) {
05733             if (!p->hardwaredtmf)
05734                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
05735             else {
05736                ast_dsp_free(p->dsp);
05737                p->dsp = NULL;
05738             }
05739          }
05740       }
05741 
05742       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
05743          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05744          if (p->dsp) ast_dsp_digitreset(p->dsp);
05745          res = ast_pbx_run(chan);
05746          if (res) {
05747             ast_log(LOG_WARNING, "PBX exited non-zero\n");
05748             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05749          }
05750          return NULL;
05751       } else {
05752          if (option_verbose > 2)
05753             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
05754          sleep(2);
05755          res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_INFO);
05756          if (res < 0)
05757             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
05758          else
05759             sleep(1);
05760          res = ast_streamfile(chan, "ss-noservice", chan->language);
05761          if (res >= 0)
05762             ast_waitstream(chan, "");
05763          res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05764          ast_hangup(chan);
05765          return NULL;
05766       }
05767       break;
05768    case SIG_FXOLS:
05769    case SIG_FXOGS:
05770    case SIG_FXOKS:
05771       /* Read the first digit */
05772       timeout = firstdigittimeout;
05773       /* If starting a threeway call, never timeout on the first digit so someone
05774          can use flash-hook as a "hold" feature */
05775       if (p->subs[SUB_THREEWAY].owner) 
05776          timeout = 999999;
05777       while (len < AST_MAX_EXTENSION-1) {
05778          /* Read digit unless it's supposed to be immediate, in which case the
05779             only answer is 's' */
05780          if (p->immediate) 
05781             res = 's';
05782          else
05783             res = ast_waitfordigit(chan, timeout);
05784          timeout = 0;
05785          if (res < 0) {
05786             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05787             res = tone_zone_play_tone(p->subs[index].zfd, -1);
05788             ast_hangup(chan);
05789             return NULL;
05790          } else if (res)  {
05791             exten[len++]=res;
05792             exten[len] = '\0';
05793          }
05794          if (!ast_ignore_pattern(chan->context, exten))
05795             tone_zone_play_tone(p->subs[index].zfd, -1);
05796          else
05797             tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
05798          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
05799             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05800                if (getforward) {
05801                   /* Record this as the forwarding extension */
05802                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
05803                   if (option_verbose > 2)
05804                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
05805                   res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05806                   if (res)
05807                      break;
05808                   usleep(500000);
05809                   res = tone_zone_play_tone(p->subs[index].zfd, -1);
05810                   sleep(1);
05811                   memset(exten, 0, sizeof(exten));
05812                   res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
05813                   len = 0;
05814                   getforward = 0;
05815                } else  {
05816                   res = tone_zone_play_tone(p->subs[index].zfd, -1);
05817                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05818                   if (!ast_strlen_zero(p->cid_num)) {
05819                      if (!p->hidecallerid)
05820                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
05821                      else
05822                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
05823                   }
05824                   if (!ast_strlen_zero(p->cid_name)) {
05825                      if (!p->hidecallerid)
05826                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
05827                   }
05828                   ast_setstate(chan, AST_STATE_RING);
05829                   zt_enable_ec(p);
05830                   res = ast_pbx_run(chan);
05831                   if (res) {
05832                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
05833                      res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05834                   }
05835                   return NULL;
05836                }
05837             } else {
05838                /* It's a match, but they just typed a digit, and there is an ambiguous match,
05839                   so just set the timeout to matchdigittimeout and wait some more */
05840                timeout = matchdigittimeout;
05841             }
05842          } else if (res == 0) {
05843             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
05844             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05845             zt_wait_event(p->subs[index].zfd);
05846             ast_hangup(chan);
05847             return NULL;
05848          } else if (p->callwaiting && !strcmp(exten, "*70")) {
05849             if (option_verbose > 2) 
05850                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
05851             /* Disable call waiting if enabled */
05852             p->callwaiting = 0;
05853             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05854             if (res) {
05855                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
05856                   chan->name, strerror(errno));
05857             }
05858             len = 0;
05859             ioctl(p->subs[index].zfd,ZT_CONFDIAG,&len);
05860             memset(exten, 0, sizeof(exten));
05861             timeout = firstdigittimeout;
05862                
05863          } else if (!strcmp(exten,ast_pickup_ext())) {
05864             /* Scan all channels and see if any there
05865              * ringing channqels with that have call groups
05866              * that equal this channels pickup group  
05867              */
05868             if (index == SUB_REAL) {
05869                /* Switch us from Third call to Call Wait */
05870                if (p->subs[SUB_THREEWAY].owner) {
05871                   /* If you make a threeway call and the *8# a call, it should actually 
05872                      look like a callwait */
05873                   alloc_sub(p, SUB_CALLWAIT);   
05874                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
05875                   unalloc_sub(p, SUB_THREEWAY);
05876                }
05877                zt_enable_ec(p);
05878                if (ast_pickup_call(chan)) {
05879                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
05880                   res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05881                   zt_wait_event(p->subs[index].zfd);
05882                }
05883                ast_hangup(chan);
05884                return NULL;
05885             } else {
05886                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
05887                ast_hangup(chan);
05888                return NULL;
05889             }
05890             
05891          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
05892             if (option_verbose > 2) 
05893                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
05894             /* Disable Caller*ID if enabled */
05895             p->hidecallerid = 1;
05896             if (chan->cid.cid_num)
05897                free(chan->cid.cid_num);
05898             chan->cid.cid_num = NULL;
05899             if (chan->cid.cid_name)
05900                free(chan->cid.cid_name);
05901             chan->cid.cid_name = NULL;
05902             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05903             if (res) {
05904                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
05905                   chan->name, strerror(errno));
05906             }
05907             len = 0;
05908             memset(exten, 0, sizeof(exten));
05909             timeout = firstdigittimeout;
05910          } else if (p->callreturn && !strcmp(exten, "*69")) {
05911             res = 0;
05912             if (!ast_strlen_zero(p->lastcid_num)) {
05913                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
05914             }
05915             if (!res)
05916                res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05917             break;
05918          } else if (!strcmp(exten, "*78")) {
05919             /* Do not disturb */
05920             if (option_verbose > 2)
05921                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
05922             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
05923                      "Channel: Zap/%d\r\n"
05924                      "Status: enabled\r\n", p->channel);
05925             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05926             p->dnd = 1;
05927             getforward = 0;
05928             memset(exten, 0, sizeof(exten));
05929             len = 0;
05930          } else if (!strcmp(exten, "*79")) {
05931             /* Do not disturb */
05932             if (option_verbose > 2)
05933                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
05934             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
05935                      "Channel: Zap/%d\r\n"
05936                      "Status: disabled\r\n", p->channel);
05937             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05938             p->dnd = 0;
05939             getforward = 0;
05940             memset(exten, 0, sizeof(exten));
05941             len = 0;
05942          } else if (p->cancallforward && !strcmp(exten, "*72")) {
05943             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05944             getforward = 1;
05945             memset(exten, 0, sizeof(exten));
05946             len = 0;
05947          } else if (p->cancallforward && !strcmp(exten, "*73")) {
05948             if (option_verbose > 2)
05949                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
05950             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05951             memset(p->call_forward, 0, sizeof(p->call_forward));
05952             getforward = 0;
05953             memset(exten, 0, sizeof(exten));
05954             len = 0;
05955          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
05956                   p->subs[SUB_THREEWAY].owner &&
05957                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05958             /* This is a three way call, the main call being a real channel, 
05959                and we're parking the first call. */
05960             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
05961             if (option_verbose > 2)
05962                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
05963             break;
05964          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
05965             if (option_verbose > 2)
05966                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
05967             res = ast_db_put("blacklist", p->lastcid_num, "1");
05968             if (!res) {
05969                res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05970                memset(exten, 0, sizeof(exten));
05971                len = 0;
05972             }
05973          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
05974             if (option_verbose > 2) 
05975                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
05976             /* Enable Caller*ID if enabled */
05977             p->hidecallerid = 0;
05978             if (chan->cid.cid_num)
05979                free(chan->cid.cid_num);
05980             chan->cid.cid_num = NULL;
05981             if (chan->cid.cid_name)
05982                free(chan->cid.cid_name);
05983             chan->cid.cid_name = NULL;
05984             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
05985             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
05986             if (res) {
05987                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
05988                   chan->name, strerror(errno));
05989             }
05990             len = 0;
05991             memset(exten, 0, sizeof(exten));
05992             timeout = firstdigittimeout;
05993          } else if (!strcmp(exten, "*0")) {
05994             struct ast_channel *nbridge = 
05995                p->subs[SUB_THREEWAY].owner;
05996             struct zt_pvt *pbridge = NULL;
05997               /* set up the private struct of the bridged one, if any */
05998             if (nbridge && ast_bridged_channel(nbridge)) 
05999                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06000             if (nbridge && pbridge && 
06001                 (nbridge->tech == &zap_tech) && 
06002                 (ast_bridged_channel(nbridge)->tech == &zap_tech) &&
06003                 ISTRUNK(pbridge)) {
06004                int func = ZT_FLASH;
06005                /* Clear out the dial buffer */
06006                p->dop.dialstr[0] = '\0';
06007                /* flash hookswitch */
06008                if ((ioctl(pbridge->subs[SUB_REAL].zfd,ZT_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06009                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06010                      nbridge->name, strerror(errno));
06011                }
06012                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06013                unalloc_sub(p, SUB_THREEWAY);
06014                p->owner = p->subs[SUB_REAL].owner;
06015                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06016                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06017                ast_hangup(chan);
06018                return NULL;
06019             } else {
06020                tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
06021                zt_wait_event(p->subs[index].zfd);
06022                tone_zone_play_tone(p->subs[index].zfd, -1);
06023                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06024                unalloc_sub(p, SUB_THREEWAY);
06025                p->owner = p->subs[SUB_REAL].owner;
06026                ast_hangup(chan);
06027                return NULL;
06028             }              
06029          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06030                      ((exten[0] != '*') || (strlen(exten) > 2))) {
06031             if (option_debug)
06032                ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
06033             break;
06034          }
06035          if (!timeout)
06036             timeout = gendigittimeout;
06037          if (len && !ast_ignore_pattern(chan->context, exten))
06038             tone_zone_play_tone(p->subs[index].zfd, -1);
06039       }
06040       break;
06041    case SIG_FXSLS:
06042    case SIG_FXSGS:
06043    case SIG_FXSKS:
06044 #ifdef HAVE_PRI
06045       if (p->pri) {
06046          /* This is a GR-303 trunk actually.  Wait for the first ring... */
06047          struct ast_frame *f;
06048          int res;
06049          time_t start;
06050 
06051          time(&start);
06052          ast_setstate(chan, AST_STATE_RING);
06053          while (time(NULL) < start + 3) {
06054             res = ast_waitfor(chan, 1000);
06055             if (res) {
06056                f = ast_read(chan);
06057                if (!f) {
06058                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06059                   ast_hangup(chan);
06060                   return NULL;
06061                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06062                   res = 1;
06063                } else
06064                   res = 0;
06065                ast_frfree(f);
06066                if (res) {
06067                   ast_log(LOG_DEBUG, "Got ring!\n");
06068                   res = 0;
06069                   break;
06070                }
06071             }
06072          }
06073       }
06074 #endif
06075       /* check for SMDI messages */
06076       if (p->use_smdi && p->smdi_iface) {
06077          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06078 
06079          if (smdi_msg != NULL) {
06080             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06081 
06082             if (smdi_msg->type == 'B')
06083                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06084             else if (smdi_msg->type == 'N')
06085                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06086 
06087             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06088          } else {
06089             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06090          }
06091       }
06092 
06093       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06094             number = smdi_msg->calling_st;
06095 
06096       /* If we want caller id, we're in a prering state due to a polarity reversal
06097        * and we're set to use a polarity reversal to trigger the start of caller id,
06098        * grab the caller id and wait for ringing to start... */
06099       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06100          /* If set to use DTMF CID signalling, listen for DTMF */
06101          if (p->cid_signalling == CID_SIG_DTMF) {
06102             int i = 0;
06103             cs = NULL;
06104             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06105                "channel %s\n", chan->name);
06106             zt_setlinear(p->subs[index].zfd, 0);
06107             res = 2000;
06108             for (;;) {
06109                struct ast_frame *f;
06110                res = ast_waitfor(chan, res);
06111                if (res <= 0) {
06112                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06113                      "Exiting simple switch\n");
06114                   ast_hangup(chan);
06115                   return NULL;
06116                } 
06117                f = ast_read(chan);
06118                if (f->frametype == AST_FRAME_DTMF) {
06119                   dtmfbuf[i++] = f->subclass;
06120                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06121                   res = 2000;
06122                }
06123                ast_frfree(f);
06124                if (chan->_state == AST_STATE_RING ||
06125                    chan->_state == AST_STATE_RINGING) 
06126                   break; /* Got ring */
06127             }
06128             dtmfbuf[i] = '\0';
06129             zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
06130             /* Got cid and ring. */
06131             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06132             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06133             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
06134                dtmfcid, flags);
06135             /* If first byte is NULL, we have no cid */
06136             if (!ast_strlen_zero(dtmfcid)) 
06137                number = dtmfcid;
06138             else
06139                number = NULL;
06140          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
06141          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06142             cs = callerid_new(p->cid_signalling);
06143             if (cs) {
06144                samples = 0;
06145 #if 1
06146                bump_gains(p);
06147 #endif            
06148                /* Take out of linear mode for Caller*ID processing */
06149                zt_setlinear(p->subs[index].zfd, 0);
06150                
06151                /* First we wait and listen for the Caller*ID */
06152                for (;;) {  
06153                   i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
06154                   if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))  {
06155                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06156                      callerid_free(cs);
06157                      ast_hangup(chan);
06158                      return NULL;
06159                   }
06160                   if (i & ZT_IOMUX_SIGEVENT) {
06161                      res = zt_get_event(p->subs[index].zfd);
06162                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06163 
06164                      if (p->cid_signalling == CID_SIG_V23_JP) {
06165 #ifdef ZT_EVENT_RINGBEGIN
06166                         if (res == ZT_EVENT_RINGBEGIN) {
06167                            res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
06168                            usleep(1);
06169                         }
06170 #endif
06171                      } else {
06172                         res = 0;
06173                         break;
06174                      }
06175                   } else if (i & ZT_IOMUX_READ) {
06176                      res = read(p->subs[index].zfd, buf, sizeof(buf));
06177                      if (res < 0) {
06178                         if (errno != ELAST) {
06179                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06180                            callerid_free(cs);
06181                            ast_hangup(chan);
06182                            return NULL;
06183                         }
06184                         break;
06185                      }
06186                      samples += res;
06187 
06188                      if  (p->cid_signalling == CID_SIG_V23_JP) {
06189                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06190                      } else {
06191                         res = callerid_feed(cs, buf, res, AST_LAW(p));
06192                      }
06193 
06194                      if (res < 0) {
06195                         ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06196                         break;
06197                      } else if (res)
06198                         break;
06199                      else if (samples > (8000 * 10))
06200                         break;
06201                   }
06202                }
06203                if (res == 1) {
06204                   callerid_get(cs, &name, &number, &flags);
06205                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06206                }
06207                if (res < 0) {
06208                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06209                }
06210 
06211                if (p->cid_signalling == CID_SIG_V23_JP) {
06212                   res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
06213                   usleep(1);
06214                   res = 4000;
06215                } else {
06216 
06217                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
06218                   res = 2000;
06219                }
06220 
06221                for (;;) {
06222                   struct ast_frame *f;
06223                   res = ast_waitfor(chan, res);
06224                   if (res <= 0) {
06225                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06226                         "Exiting simple switch\n");
06227                      ast_hangup(chan);
06228                      return NULL;
06229                   } 
06230                   f = ast_read(chan);
06231                   ast_frfree(f);
06232                   if (chan->_state == AST_STATE_RING ||
06233                       chan->_state == AST_STATE_RINGING) 
06234                      break; /* Got ring */
06235                }
06236    
06237                /* We must have a ring by now, so, if configured, lets try to listen for
06238                 * distinctive ringing */ 
06239                if (p->usedistinctiveringdetection == 1) {
06240                   len = 0;
06241                   distMatches = 0;
06242                   /* Clear the current ring data array so we dont have old data in it. */
06243                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06244                      curRingData[receivedRingT] = 0;
06245                   receivedRingT = 0;
06246                   counter = 0;
06247                   counter1 = 0;
06248                   /* Check to see if context is what it should be, if not set to be. */
06249                   if (strcmp(p->context,p->defcontext) != 0) {
06250                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06251                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06252                   }
06253       
06254                   for (;;) {  
06255                      i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
06256                      if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))  {
06257                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06258                         callerid_free(cs);
06259                         ast_hangup(chan);
06260                         return NULL;
06261                      }
06262                      if (i & ZT_IOMUX_SIGEVENT) {
06263                         res = zt_get_event(p->subs[index].zfd);
06264                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06265                         res = 0;
06266                         /* Let us detect distinctive ring */
06267       
06268                         curRingData[receivedRingT] = p->ringt;
06269       
06270                         if (p->ringt < p->ringt_base/2)
06271                            break;
06272                         /* Increment the ringT counter so we can match it against
06273                            values in zapata.conf for distinctive ring */
06274                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06275                            break;
06276                      } else if (i & ZT_IOMUX_READ) {
06277                         res = read(p->subs[index].zfd, buf, sizeof(buf));
06278                         if (res < 0) {
06279                            if (errno != ELAST) {
06280                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06281                               callerid_free(cs);
06282                               ast_hangup(chan);
06283                               return NULL;
06284                            }
06285                            break;
06286                         }
06287                         if (p->ringt) 
06288                            p->ringt--;
06289                         if (p->ringt == 1) {
06290                            res = -1;
06291                            break;
06292                         }
06293                      }
06294                   }
06295                   if (option_verbose > 2)
06296                      /* this only shows up if you have n of the dring patterns filled in */
06297                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06298    
06299                   for (counter = 0; counter < 3; counter++) {
06300                      /* Check to see if the rings we received match any of the ones in zapata.conf for this
06301                      channel */
06302                      distMatches = 0;
06303                      for (counter1 = 0; counter1 < 3; counter1++) {
06304                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06305                         (p->drings.ringnum[counter].ring[counter1]-10)) {
06306                            distMatches++;
06307                         }
06308                      }
06309                      if (distMatches == 3) {
06310                         /* The ring matches, set the context to whatever is for distinctive ring.. */
06311                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06312                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06313                         if (option_verbose > 2)
06314                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06315                         break;
06316                      }
06317                   }
06318                }
06319                /* Restore linear mode (if appropriate) for Caller*ID processing */
06320                zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
06321 #if 1
06322                restore_gains(p);
06323 #endif            
06324             } else
06325                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
06326          } else {
06327             ast_log(LOG_WARNING, "Channel %s in prering "
06328                "state, but I have nothing to do. "
06329                "Terminating simple switch, should be "
06330                "restarted by the actual ring.\n", 
06331                chan->name);
06332             ast_hangup(chan);
06333             return NULL;
06334          }
06335       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06336          /* FSK Bell202 callerID */
06337          cs = callerid_new(p->cid_signalling);
06338          if (cs) {
06339 #if 1
06340             bump_gains(p);
06341 #endif            
06342             samples = 0;
06343             len = 0;
06344             distMatches = 0;
06345             /* Clear the current ring data array so we dont have old data in it. */
06346             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06347                curRingData[receivedRingT] = 0;
06348             receivedRingT = 0;
06349             counter = 0;
06350             counter1 = 0;
06351             /* Check to see if context is what it should be, if not set to be. */
06352             if (strcmp(p->context,p->defcontext) != 0) {
06353                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06354                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06355             }
06356 
06357             /* Take out of linear mode for Caller*ID processing */
06358             zt_setlinear(p->subs[index].zfd, 0);
06359             for (;;) {  
06360                i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
06361                if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))  {
06362                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06363                   callerid_free(cs);
06364                   ast_hangup(chan);
06365                   return NULL;
06366                }
06367                if (i & ZT_IOMUX_SIGEVENT) {
06368                   res = zt_get_event(p->subs[index].zfd);
06369                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06370                   res = 0;
06371                   /* Let us detect callerid when the telco uses distinctive ring */
06372 
06373                   curRingData[receivedRingT] = p->ringt;
06374 
06375                   if (p->ringt < p->ringt_base/2)
06376                      break;
06377                   /* Increment the ringT counter so we can match it against
06378                      values in zapata.conf for distinctive ring */
06379                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06380                      break;
06381                } else if (i & ZT_IOMUX_READ) {
06382                   res = read(p->subs[index].zfd, buf, sizeof(buf));
06383                   if (res < 0) {
06384                      if (errno != ELAST) {
06385                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06386                         callerid_free(cs);
06387                         ast_hangup(chan);
06388                         return NULL;
06389                      }
06390                      break;
06391                   }
06392                   if (p->ringt) 
06393                      p->ringt--;
06394                   if (p->ringt == 1) {
06395                      res = -1;
06396                      break;
06397                   }
06398                   samples += res;
06399                   res = callerid_feed(cs, buf, res, AST_LAW(p));
06400                   if (res < 0) {
06401                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06402                      break;
06403                   } else if (res)
06404                      break;
06405                   else if (samples > (8000 * 10))
06406                      break;
06407                }
06408             }
06409             if (res == 1) {
06410                callerid_get(cs, &name, &number, &flags);
06411                if (option_debug)
06412                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06413             }
06414             if (distinctiveringaftercid == 1) {
06415                /* Clear the current ring data array so we dont have old data in it. */
06416                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06417                   curRingData[receivedRingT] = 0;
06418                }
06419                receivedRingT = 0;
06420                if (option_verbose > 2)
06421                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06422                for (;;) {
06423                   i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
06424                   if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))    {
06425                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06426                      callerid_free(cs);
06427                      ast_hangup(chan);
06428                      return NULL;
06429                   }
06430                   if (i & ZT_IOMUX_SIGEVENT) {
06431                      res = zt_get_event(p->subs[index].zfd);
06432                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06433                      res = 0;
06434                      /* Let us detect callerid when the telco uses distinctive ring */
06435 
06436                      curRingData[receivedRingT] = p->ringt;
06437 
06438                      if (p->ringt < p->ringt_base/2)
06439                         break;
06440                      /* Increment the ringT counter so we can match it against
06441                         values in zapata.conf for distinctive ring */
06442                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06443                         break;
06444                   } else if (i & ZT_IOMUX_READ) {
06445                      res = read(p->subs[index].zfd, buf, sizeof(buf));
06446                      if (res < 0) {
06447                         if (errno != ELAST) {
06448                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06449                            callerid_free(cs);
06450                            ast_hangup(chan);
06451                            return NULL;
06452                         }
06453                         break;
06454                      }
06455                   if (p->ringt)
06456                      p->ringt--;
06457                      if (p->ringt == 1) {
06458                         res = -1;
06459                         break;
06460                      }
06461                   }
06462                }
06463             }
06464             if (p->usedistinctiveringdetection == 1) {
06465                if (option_verbose > 2)
06466                   /* this only shows up if you have n of the dring patterns filled in */
06467                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06468 
06469                for (counter = 0; counter < 3; counter++) {
06470                   /* Check to see if the rings we received match any of the ones in zapata.conf for this
06471                   channel */
06472                   if (option_verbose > 2)
06473                      /* this only shows up if you have n of the dring patterns filled in */
06474                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06475                         p->drings.ringnum[counter].ring[0],
06476                         p->drings.ringnum[counter].ring[1],
06477                         p->drings.ringnum[counter].ring[2]);
06478                   distMatches = 0;
06479                   for (counter1 = 0; counter1 < 3; counter1++) {
06480                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06481                      (p->drings.ringnum[counter].ring[counter1]-10)) {
06482                         distMatches++;
06483                      }
06484                   }
06485                   if (distMatches == 3) {
06486                      /* The ring matches, set the context to whatever is for distinctive ring.. */
06487                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06488                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06489                      if (option_verbose > 2)
06490                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06491                      break;
06492                   }
06493                }
06494             }
06495             /* Restore linear mode (if appropriate) for Caller*ID processing */
06496             zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
06497 #if 1
06498             restore_gains(p);
06499 #endif            
06500             if (res < 0) {
06501                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06502             }
06503          } else
06504             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06505       }
06506       else
06507          cs = NULL;
06508 
06509       if (number)
06510          ast_shrink_phone_number(number);
06511       ast_set_callerid(chan, number, name, number);
06512 
06513       if (smdi_msg)
06514          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
06515 
06516       if (cs)
06517          callerid_free(cs);
06518 
06519       ast_setstate(chan, AST_STATE_RING);
06520       chan->rings = 1;
06521       p->ringt = p->ringt_base;
06522       res = ast_pbx_run(chan);
06523       if (res) {
06524          ast_hangup(chan);
06525          ast_log(LOG_WARNING, "PBX exited non-zero\n");
06526       }
06527       return NULL;
06528    default:
06529       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
06530       res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
06531       if (res < 0)
06532             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06533    }
06534    res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
06535    if (res < 0)
06536          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06537    ast_hangup(chan);
06538    return NULL;
06539 }

static void swap_subs ( struct zt_pvt p,
int  a,
int  b 
) [static]

Definition at line 843 of file chan_zap.c.

References ast_log(), zt_subchannel::chan, ast_channel::fds, zt_subchannel::inthreeway, LOG_DEBUG, zt_subchannel::owner, zt_pvt::subs, wakeup_sub(), and zt_subchannel::zfd.

Referenced by attempt_transfer(), ss_thread(), zt_answer(), zt_handle_event(), and zt_hangup().

00844 {
00845    int tchan;
00846    int tinthreeway;
00847    struct ast_channel *towner;
00848 
00849    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
00850 
00851    tchan = p->subs[a].chan;
00852    towner = p->subs[a].owner;
00853    tinthreeway = p->subs[a].inthreeway;
00854 
00855    p->subs[a].chan = p->subs[b].chan;
00856    p->subs[a].owner = p->subs[b].owner;
00857    p->subs[a].inthreeway = p->subs[b].inthreeway;
00858 
00859    p->subs[b].chan = tchan;
00860    p->subs[b].owner = towner;
00861    p->subs[b].inthreeway = tinthreeway;
00862 
00863    if (p->subs[a].owner) 
00864       p->subs[a].owner->fds[0] = p->subs[a].zfd;
00865    if (p->subs[b].owner) 
00866       p->subs[b].owner->fds[0] = p->subs[b].zfd;
00867    wakeup_sub(p, a, NULL);
00868    wakeup_sub(p, b, NULL);
00869 }

static int unalloc_sub ( struct zt_pvt p,
int  x 
) [static]

Definition at line 963 of file chan_zap.c.

References ast_log(), zt_subchannel::chan, zt_pvt::channel, zt_subchannel::curconf, zt_subchannel::inthreeway, zt_subchannel::linear, LOG_DEBUG, LOG_WARNING, zt_subchannel::owner, zt_pvt::polarity, POLARITY_IDLE, zt_pvt::subs, zt_subchannel::zfd, and zt_close().

00964 {
00965    if (!x) {
00966       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
00967       return -1;
00968    }
00969    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
00970    if (p->subs[x].zfd > -1) {
00971       zt_close(p->subs[x].zfd);
00972    }
00973    p->subs[x].zfd = -1;
00974    p->subs[x].linear = 0;
00975    p->subs[x].chan = 0;
00976    p->subs[x].owner = NULL;
00977    p->subs[x].inthreeway = 0;
00978    p->polarity = POLARITY_IDLE;
00979    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
00980    return 0;
00981 }

static int unload_module ( void   )  [static]

Definition at line 10378 of file chan_zap.c.

References __unload_module(), ast_mutex_destroy(), and lock.

10379 {
10380 #ifdef HAVE_PRI      
10381    int y;
10382    for (y = 0; y < NUM_SPANS; y++)
10383       ast_mutex_destroy(&pris[y].lock);
10384 #endif
10385    return __unload_module();
10386 }

static int update_conf ( struct zt_pvt p  )  [static]

Definition at line 1349 of file chan_zap.c.

References ast_log(), zt_pvt::channel, conf_add(), conf_del(), zt_pvt::confno, GET_CHANNEL, zt_pvt::inconference, zt_subchannel::inthreeway, isslavenative(), LOG_DEBUG, zt_pvt::master, MAX_SLAVES, option_debug, zt_pvt::slaves, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by __zt_exception(), mkintf(), zt_bridge(), zt_fixup(), zt_handle_event(), zt_hangup(), and zt_unlink().

01350 {
01351    int needconf = 0;
01352    int x;
01353    int useslavenative;
01354    struct zt_pvt *slave = NULL;
01355 
01356    useslavenative = isslavenative(p, &slave);
01357    /* Start with the obvious, general stuff */
01358    for (x = 0; x < 3; x++) {
01359       /* Look for three way calls */
01360       if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway) {
01361          conf_add(p, &p->subs[x], x, 0);
01362          needconf++;
01363       } else {
01364          conf_del(p, &p->subs[x], x);
01365       }
01366    }
01367    /* If we have a slave, add him to our conference now. or DAX
01368       if this is slave native */
01369    for (x = 0; x < MAX_SLAVES; x++) {
01370       if (p->slaves[x]) {
01371          if (useslavenative)
01372             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01373          else {
01374             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01375             needconf++;
01376          }
01377       }
01378    }
01379    /* If we're supposed to be in there, do so now */
01380    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01381       if (useslavenative)
01382          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01383       else {
01384          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01385          needconf++;
01386       }
01387    }
01388    /* If we have a master, add ourselves to his conference */
01389    if (p->master) {
01390       if (isslavenative(p->master, NULL)) {
01391          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01392       } else {
01393          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01394       }
01395    }
01396    if (!needconf) {
01397       /* Nobody is left (or should be left) in our conference.
01398          Kill it. */
01399       p->confno = -1;
01400    }
01401    if (option_debug)
01402       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01403    return 0;
01404 }

static void wakeup_sub ( struct zt_pvt p,
int  a,
void *  pri 
) [static]

Definition at line 783 of file chan_zap.c.

References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), zt_pvt::lock, ast_channel::lock, zt_subchannel::owner, and zt_pvt::subs.

Referenced by swap_subs().

00785 {
00786 #ifdef HAVE_PRI
00787    if (pri)
00788       ast_mutex_unlock(&pri->lock);
00789 #endif         
00790    for (;;) {
00791       if (p->subs[a].owner) {
00792          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00793             ast_mutex_unlock(&p->lock);
00794             usleep(1);
00795             ast_mutex_lock(&p->lock);
00796          } else {
00797             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
00798             ast_mutex_unlock(&p->subs[a].owner->lock);
00799             break;
00800          }
00801       } else
00802          break;
00803    }
00804 #ifdef HAVE_PRI
00805    if (pri)
00806       ast_mutex_lock(&pri->lock);
00807 #endif         
00808 }

static int zap_destroy_channel ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 9740 of file chan_zap.c.

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

09741 {
09742    int channel;
09743    
09744    if (argc != 4)
09745       return RESULT_SHOWUSAGE;
09746    
09747    channel = atoi(argv[3]);
09748 
09749    return zap_destroy_channel_bynum(channel);
09750 }

static int zap_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 6542 of file chan_zap.c.

References zt_pvt::channel, destroy_channel(), iflist, zt_pvt::next, zt_pvt::prev, RESULT_FAILURE, and RESULT_SUCCESS.

Referenced by handle_init_event(), and zap_destroy_channel().

06543 {
06544    struct zt_pvt *tmp = NULL;
06545    struct zt_pvt *prev = NULL;
06546 
06547    tmp = iflist;
06548    while (tmp) {
06549       if (tmp->channel == channel) {
06550          destroy_channel(prev, tmp, 1);
06551          return RESULT_SUCCESS;
06552       }
06553       prev = tmp;
06554       tmp = tmp->next;
06555    }
06556    return RESULT_FAILURE;
06557 }

static int zap_fake_event ( struct zt_pvt p,
int  mode 
) [static]

Definition at line 10128 of file chan_zap.c.

References ast_log(), zt_pvt::fake_event, HANGUP, LOG_WARNING, zt_pvt::owner, and TRANSFER.

Referenced by action_transfer(), and action_transferhangup().

10129 {
10130    if (p) {
10131       switch (mode) {
10132          case TRANSFER:
10133             p->fake_event = ZT_EVENT_WINKFLASH;
10134             break;
10135          case HANGUP:
10136             p->fake_event = ZT_EVENT_ONHOOK;
10137             break;
10138          default:
10139             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10140       }
10141    }
10142    return 0;
10143 }

static void zap_queue_frame ( struct zt_pvt p,
struct ast_frame f,
void *  pri 
) [static]

Definition at line 813 of file chan_zap.c.

References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), zt_pvt::lock, ast_channel::lock, and zt_pvt::owner.

Referenced by action_zapdialoffhook().

00815 {
00816    /* We must unlock the PRI to avoid the possibility of a deadlock */
00817 #ifdef HAVE_PRI
00818    if (pri)
00819       ast_mutex_unlock(&pri->lock);
00820 #endif      
00821    for (;;) {
00822       if (p->owner) {
00823          if (ast_mutex_trylock(&p->owner->lock)) {
00824             ast_mutex_unlock(&p->lock);
00825             usleep(1);
00826             ast_mutex_lock(&p->lock);
00827          } else {
00828             ast_queue_frame(p->owner, f);
00829             ast_mutex_unlock(&p->owner->lock);
00830             break;
00831          }
00832       } else
00833          break;
00834    }
00835 #ifdef HAVE_PRI
00836    if (pri)
00837       ast_mutex_lock(&pri->lock);
00838 #endif      
00839 }

static int zap_restart ( void   )  [static]

Definition at line 9753 of file chan_zap.c.

References ast_log(), ast_verbose(), destroy_channel(), iflist, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, setup_zap(), and VERBOSE_PREFIX_1.

Referenced by action_zaprestart(), and zap_restart_cmd().

09754 {
09755    if (option_verbose > 0)
09756       ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
09757    while (iflist) {
09758       if (option_debug)
09759          ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
09760       /* Also updates iflist: */
09761       destroy_channel(NULL, iflist, 1);
09762    }
09763    if (option_debug)
09764       ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
09765    if (setup_zap(0) != 0) {
09766       ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
09767       return 1;
09768    }
09769    return 0;
09770 }

static int zap_restart_cmd ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 9772 of file chan_zap.c.

References RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and zap_restart().

09773 {
09774    if (argc != 2) {
09775       return RESULT_SHOWUSAGE;
09776    }
09777 
09778    if (zap_restart() != 0)
09779       return RESULT_FAILURE;
09780    return RESULT_SUCCESS;
09781 }

static int zap_show_channel ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 9854 of file chan_zap.c.

References ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), zt_pvt::callwaitcas, zt_pvt::channel, zt_pvt::cid_name, zt_pvt::cid_num, zt_pvt::cid_ton, zt_pvt::confno, zt_pvt::context, zt_pvt::destroy, zt_pvt::dialing, zt_pvt::dsp, zt_pvt::dtmfrelax, zt_pvt::echocanbridged, zt_pvt::echocancel, zt_pvt::echocanon, zt_pvt::exten, zt_pvt::faxhandled, iflist, zt_pvt::inalarm, zt_pvt::inconference, zt_subchannel::inthreeway, zt_pvt::law, zt_subchannel::linear, lock, LOG_WARNING, zt_pvt::master, MAX_SLAVES, zt_pvt::next, zt_subchannel::owner, zt_pvt::owner, zt_pvt::propconfno, zt_pvt::pulsedial, zt_pvt::radio, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, zt_pvt::sig, sig2str, zt_pvt::slaves, zt_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, and zt_subchannel::zfd.

09855 {
09856    int channel;
09857    struct zt_pvt *tmp = NULL;
09858    ZT_CONFINFO ci;
09859    ZT_PARAMS ps;
09860    int x;
09861    ast_mutex_t *lock;
09862    struct zt_pvt *start;
09863 #ifdef HAVE_PRI
09864    char *c;
09865    int trunkgroup;
09866    struct zt_pri *pri=NULL;
09867 #endif
09868 
09869    lock = &iflock;
09870    start = iflist;
09871 
09872    if (argc != 4)
09873       return RESULT_SHOWUSAGE;
09874 #ifdef HAVE_PRI
09875    if ((c = strchr(argv[3], ':'))) {
09876       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
09877          return RESULT_SHOWUSAGE;
09878       if ((trunkgroup < 1) || (channel < 1))
09879          return RESULT_SHOWUSAGE;
09880       for (x = 0; x < NUM_SPANS; x++) {
09881          if (pris[x].trunkgroup == trunkgroup) {
09882             pri = pris + x;
09883             break;
09884          }
09885       }
09886       if (pri) {
09887          start = pri->crvs;
09888          lock = &pri->lock;
09889       } else {
09890          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
09891          return RESULT_FAILURE;
09892       }
09893    } else
09894 #endif
09895       channel = atoi(argv[3]);
09896 
09897    ast_mutex_lock(lock);
09898    tmp = start;
09899    while (tmp) {
09900       if (tmp->channel == channel) {
09901 #ifdef HAVE_PRI
09902          if (pri) 
09903             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
09904          else
09905 #endif         
09906          ast_cli(fd, "Channel: %d\n", tmp->channel);
09907          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
09908          ast_cli(fd, "Span: %d\n", tmp->span);
09909          ast_cli(fd, "Extension: %s\n", tmp->exten);
09910          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
09911          ast_cli(fd, "Context: %s\n", tmp->context);
09912          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
09913          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
09914          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
09915          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
09916          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
09917          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
09918          ast_cli(fd, "Radio: %d\n", tmp->radio);
09919          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
09920          ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
09921          ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
09922          ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
09923          ast_cli(fd, "Confno: %d\n", tmp->confno);
09924          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
09925          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
09926          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
09927          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
09928          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
09929          ast_cli(fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
09930          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
09931          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
09932          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
09933          if (tmp->master)
09934             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
09935          for (x = 0; x < MAX_SLAVES; x++) {
09936             if (tmp->slaves[x])
09937                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
09938          }
09939 #ifdef HAVE_PRI
09940          if (tmp->pri) {
09941             ast_cli(fd, "PRI Flags: ");
09942             if (tmp->resetting)
09943                ast_cli(fd, "Resetting ");
09944             if (tmp->call)
09945                ast_cli(fd, "Call ");
09946             if (tmp->bearer)
09947                ast_cli(fd, "Bearer ");
09948             ast_cli(fd, "\n");
09949             if (tmp->logicalspan) 
09950                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
09951             else
09952                ast_cli(fd, "PRI Logical Span: Implicit\n");
09953          }
09954             
09955 #endif
09956          memset(&ci, 0, sizeof(ci));
09957          ps.channo = tmp->channel;
09958          if (tmp->subs[SUB_REAL].zfd > -1) {
09959             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
09960                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
09961             }
09962 #ifdef ZT_GETCONFMUTE
09963             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) {
09964                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
09965             }
09966 #endif
09967             if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
09968                ast_log(LOG_WARNING, "Failed to get parameters on channel %d\n", tmp->channel);
09969             } else {
09970                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
09971             }
09972          }
09973          ast_mutex_unlock(lock);
09974          return RESULT_SUCCESS;
09975       }
09976       tmp = tmp->next;
09977    }
09978    
09979    ast_cli(fd, "Unable to find given channel %d\n", channel);
09980    ast_mutex_unlock(lock);
09981    return RESULT_FAILURE;
09982 }

static int zap_show_channels ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 9793 of file chan_zap.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), zt_pvt::channel, zt_pvt::context, zt_pvt::exten, FORMAT, FORMAT2, iflist, zt_pvt::language, lock, zt_pvt::mohinterpret, zt_pvt::next, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

09794 {
09795 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
09796 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
09797    struct zt_pvt *tmp = NULL;
09798    char tmps[20] = "";
09799    ast_mutex_t *lock;
09800    struct zt_pvt *start;
09801 #ifdef HAVE_PRI
09802    int trunkgroup;
09803    struct zt_pri *pri = NULL;
09804    int x;
09805 #endif
09806 
09807    lock = &iflock;
09808    start = iflist;
09809 
09810 #ifdef HAVE_PRI
09811    if (argc == 4) {
09812       if ((trunkgroup = atoi(argv[3])) < 1)
09813          return RESULT_SHOWUSAGE;
09814       for (x = 0; x < NUM_SPANS; x++) {
09815          if (pris[x].trunkgroup == trunkgroup) {
09816             pri = pris + x;
09817             break;
09818          }
09819       }
09820       if (pri) {
09821          start = pri->crvs;
09822          lock = &pri->lock;
09823       } else {
09824          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
09825          return RESULT_FAILURE;
09826       }
09827    } else
09828 #endif
09829    if (argc != 3)
09830       return RESULT_SHOWUSAGE;
09831 
09832    ast_mutex_lock(lock);
09833 #ifdef HAVE_PRI
09834    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
09835 #else
09836    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
09837 #endif   
09838    
09839    tmp = start;
09840    while (tmp) {
09841       if (tmp->channel > 0) {
09842          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
09843       } else
09844          ast_copy_string(tmps, "pseudo", sizeof(tmps));
09845       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
09846       tmp = tmp->next;
09847    }
09848    ast_mutex_unlock(lock);
09849    return RESULT_SUCCESS;
09850 #undef FORMAT
09851 #undef FORMAT2
09852 }

static int zap_show_status ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10015 of file chan_zap.c.

References alarms, ast_cli(), ast_log(), FORMAT, FORMAT2, LOG_WARNING, RESULT_FAILURE, and RESULT_SUCCESS.

10015                                                            {
10016    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10017    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10018 
10019    int span;
10020    int res;
10021    char alarms[50];
10022 
10023    int ctl;
10024    ZT_SPANINFO s;
10025 
10026    ctl = open("/dev/zap/ctl", O_RDWR);
10027    if (ctl < 0) {
10028       ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10029       ast_cli(fd, "No Zaptel interface found.\n");
10030       return RESULT_FAILURE;
10031    }
10032    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10033 
10034    for (span = 1; span < ZT_MAX_SPANS; ++span) {
10035       s.spanno = span;
10036       res = ioctl(ctl, ZT_SPANSTAT, &s);
10037       if (res) {
10038          continue;
10039       }
10040       alarms[0] = '\0';
10041       if (s.alarms > 0) {
10042          if (s.alarms & ZT_ALARM_BLUE)
10043             strcat(alarms, "BLU/");
10044          if (s.alarms & ZT_ALARM_YELLOW)
10045             strcat(alarms, "YEL/");
10046          if (s.alarms & ZT_ALARM_RED)
10047             strcat(alarms, "RED/");
10048          if (s.alarms & ZT_ALARM_LOOPBACK)
10049             strcat(alarms, "LB/");
10050          if (s.alarms & ZT_ALARM_RECOVER)
10051             strcat(alarms, "REC/");
10052          if (s.alarms & ZT_ALARM_NOTOPEN)
10053             strcat(alarms, "NOP/");
10054          if (!strlen(alarms))
10055             strcat(alarms, "UUU/");
10056          if (strlen(alarms)) {
10057             /* Strip trailing / */
10058             alarms[strlen(alarms) - 1] = '\0';
10059          }
10060       } else {
10061          if (s.numchans)
10062             strcpy(alarms, "OK");
10063          else
10064             strcpy(alarms, "UNCONFIGURED");
10065       }
10066 
10067       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10068    }
10069    close(ctl);
10070 
10071    return RESULT_SUCCESS;
10072 #undef FORMAT
10073 #undef FORMAT2
10074 }

static char* zap_sig2str ( int  sig  )  [static]

Definition at line 1159 of file chan_zap.c.

References SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

01160 {
01161    static char buf[256];
01162    switch (sig) {
01163    case SIG_EM:
01164       return "E & M Immediate";
01165    case SIG_EMWINK:
01166       return "E & M Wink";
01167    case SIG_EM_E1:
01168       return "E & M E1";
01169    case SIG_FEATD:
01170       return "Feature Group D (DTMF)";
01171    case SIG_FEATDMF:
01172       return "Feature Group D (MF)";
01173    case SIG_FEATDMF_TA:
01174       return "Feature Groud D (MF) Tandem Access";
01175    case SIG_FEATB:
01176       return "Feature Group B (MF)";
01177    case SIG_E911:
01178       return "E911 (MF)";
01179    case SIG_FGC_CAMA:
01180       return "FGC/CAMA (Dialpulse)";
01181    case SIG_FGC_CAMAMF:
01182       return "FGC/CAMA (MF)";
01183    case SIG_FXSLS:
01184       return "FXS Loopstart";
01185    case SIG_FXSGS:
01186       return "FXS Groundstart";
01187    case SIG_FXSKS:
01188       return "FXS Kewlstart";
01189    case SIG_FXOLS:
01190       return "FXO Loopstart";
01191    case SIG_FXOGS:
01192       return "FXO Groundstart";
01193    case SIG_FXOKS:
01194       return "FXO Kewlstart";
01195    case SIG_PRI:
01196       return "PRI Signalling";
01197    case SIG_SF:
01198       return "SF (Tone) Signalling Immediate";
01199    case SIG_SFWINK:
01200       return "SF (Tone) Signalling Wink";
01201    case SIG_SF_FEATD:
01202       return "SF (Tone) Signalling with Feature Group D (DTMF)";
01203    case SIG_SF_FEATDMF:
01204       return "SF (Tone) Signalling with Feature Group D (MF)";
01205    case SIG_SF_FEATB:
01206       return "SF (Tone) Signalling with Feature Group B (MF)";
01207    case SIG_GR303FXOKS:
01208       return "GR-303 Signalling with FXOKS";
01209    case SIG_GR303FXSKS:
01210       return "GR-303 Signalling with FXSKS";
01211    case 0:
01212       return "Pseudo Signalling";
01213    default:
01214       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01215       return buf;
01216    }
01217 }

static int zt_answer ( struct ast_channel ast  )  [static]

Definition at line 2732 of file chan_zap.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, zt_pvt::channel, zt_pvt::dialing, zt_pvt::digital, zt_pvt::hanguponpolarityswitch, zt_subchannel::inthreeway, zt_pvt::lock, LOG_DEBUG, LOG_WARNING, zt_pvt::oprmode, zt_subchannel::owner, zt_pvt::owner, zt_pvt::polaritydelaytv, zt_pvt::radio, zt_pvt::ringt, zt_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, zt_pvt::span, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, swap_subs(), ast_channel::tech_pvt, zt_subchannel::zfd, zt_enable_ec(), zt_get_index(), zt_set_hook(), and zt_train_ec().

02733 {
02734    struct zt_pvt *p = ast->tech_pvt;
02735    int res = 0;
02736    int index;
02737    int oldstate = ast->_state;
02738    ast_setstate(ast, AST_STATE_UP);
02739    ast_mutex_lock(&p->lock);
02740    index = zt_get_index(ast, p, 0);
02741    if (index < 0)
02742       index = SUB_REAL;
02743    /* nothing to do if a radio channel */
02744    if ((p->radio || (p->oprmode < 0))) {
02745       ast_mutex_unlock(&p->lock);
02746       return 0;
02747    }
02748    switch (p->sig) {
02749    case SIG_FXSLS:
02750    case SIG_FXSGS:
02751    case SIG_FXSKS:
02752       p->ringt = 0;
02753       /* Fall through */
02754    case SIG_EM:
02755    case SIG_EM_E1:
02756    case SIG_EMWINK:
02757    case SIG_FEATD:
02758    case SIG_FEATDMF:
02759    case SIG_FEATDMF_TA:
02760    case SIG_E911:
02761    case SIG_FGC_CAMA:
02762    case SIG_FGC_CAMAMF:
02763    case SIG_FEATB:
02764    case SIG_SF:
02765    case SIG_SFWINK:
02766    case SIG_SF_FEATD:
02767    case SIG_SF_FEATDMF:
02768    case SIG_SF_FEATB:
02769    case SIG_FXOLS:
02770    case SIG_FXOGS:
02771    case SIG_FXOKS:
02772       /* Pick up the line */
02773       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
02774       if (p->hanguponpolarityswitch) {
02775          gettimeofday(&p->polaritydelaytv, NULL);
02776       }
02777       res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
02778       tone_zone_play_tone(p->subs[index].zfd, -1);
02779       p->dialing = 0;
02780       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
02781          if (oldstate == AST_STATE_RINGING) {
02782             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
02783             tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, -1);
02784             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02785             p->owner = p->subs[SUB_REAL].owner;
02786          }
02787       }
02788       if (p->sig & __ZT_SIG_FXS) {
02789          zt_enable_ec(p);
02790          zt_train_ec(p);
02791       }
02792       break;
02793 #ifdef HAVE_PRI
02794    case SIG_PRI:
02795       /* Send a pri acknowledge */
02796       if (!pri_grab(p, p->pri)) {
02797          p->proceeding = 1;
02798          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
02799          pri_rel(p->pri);
02800       } else {
02801          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02802          res = -1;
02803       }
02804       break;
02805 #endif
02806    case 0:
02807       ast_mutex_unlock(&p->lock);
02808       return 0;
02809    default:
02810       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
02811       res = -1;
02812    }
02813    ast_mutex_unlock(&p->lock);
02814    return res;
02815 }

static enum ast_bridge_result zt_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
) [static]

Definition at line 3141 of file chan_zap.c.

References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verbose(), ast_waitfor_n(), ast_write(), zt_pvt::channel, disable_dtmf_detect(), zt_pvt::echocanbridged, enable_dtmf_detect(), ast_channel::fds, ast_frame::frametype, zt_pvt::inconference, zt_subchannel::inthreeway, zt_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, master, option_verbose, zt_subchannel::owner, zt_pvt::owner, zt_pvt::pulsedial, zt_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, ast_channel::tech_pvt, zt_pvt::transfer, update_conf(), VERBOSE_PREFIX_3, zt_subchannel::zfd, zt_disable_ec(), zt_enable_ec(), zt_get_index(), zt_link(), and zt_unlink().

03142 {
03143    struct ast_channel *who;
03144    struct zt_pvt *p0, *p1, *op0, *op1;
03145    struct zt_pvt *master = NULL, *slave = NULL;
03146    struct ast_frame *f;
03147    int inconf = 0;
03148    int nothingok = 1;
03149    int ofd0, ofd1;
03150    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03151    int os0 = -1, os1 = -1;
03152    int priority = 0;
03153    struct ast_channel *oc0, *oc1;
03154    enum ast_bridge_result res;
03155 
03156 #ifdef PRI_2BCT
03157    int triedtopribridge = 0;
03158    q931_call *q931c0 = NULL, *q931c1 = NULL;
03159 #endif
03160 
03161    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
03162       There is code below to handle it properly until DTMF is actually seen,
03163       but due to currently unresolved issues it's ignored...
03164    */
03165 
03166    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03167       return AST_BRIDGE_FAILED_NOWARN;
03168 
03169    ast_mutex_lock(&c0->lock);
03170    ast_mutex_lock(&c1->lock);
03171 
03172    p0 = c0->tech_pvt;
03173    p1 = c1->tech_pvt;
03174    /* cant do pseudo-channels here */
03175    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03176       ast_mutex_unlock(&c0->lock);
03177       ast_mutex_unlock(&c1->lock);
03178       return AST_BRIDGE_FAILED_NOWARN;
03179    }
03180 
03181    oi0 = zt_get_index(c0, p0, 0);
03182    oi1 = zt_get_index(c1, p1, 0);
03183    if ((oi0 < 0) || (oi1 < 0)) {
03184       ast_mutex_unlock(&c0->lock);
03185       ast_mutex_unlock(&c1->lock);
03186       return AST_BRIDGE_FAILED;
03187    }
03188 
03189    op0 = p0 = c0->tech_pvt;
03190    op1 = p1 = c1->tech_pvt;
03191    ofd0 = c0->fds[0];
03192    ofd1 = c1->fds[0];
03193    oc0 = p0->owner;
03194    oc1 = p1->owner;
03195 
03196    if (ast_mutex_trylock(&p0->lock)) {
03197       /* Don't block, due to potential for deadlock */
03198       ast_mutex_unlock(&c0->lock);
03199       ast_mutex_unlock(&c1->lock);
03200       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03201       return AST_BRIDGE_RETRY;
03202    }
03203    if (ast_mutex_trylock(&p1->lock)) {
03204       /* Don't block, due to potential for deadlock */
03205       ast_mutex_unlock(&p0->lock);
03206       ast_mutex_unlock(&c0->lock);
03207       ast_mutex_unlock(&c1->lock);
03208       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03209       return AST_BRIDGE_RETRY;
03210    }
03211 
03212    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03213       if (p0->owner && p1->owner) {
03214          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
03215          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03216             master = p0;
03217             slave = p1;
03218             inconf = 1;
03219          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03220             master = p1;
03221             slave = p0;
03222             inconf = 1;
03223          } else {
03224             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
03225             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03226                p0->channel,
03227                oi0, (p0->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
03228                p0->subs[SUB_REAL].inthreeway, p0->channel,
03229                oi0, (p1->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
03230                p1->subs[SUB_REAL].inthreeway);
03231          }
03232          nothingok = 0;
03233       }
03234    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03235       if (p1->subs[SUB_THREEWAY].inthreeway) {
03236          master = p1;
03237          slave = p0;
03238          nothingok = 0;
03239       }
03240    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03241       if (p0->subs[SUB_THREEWAY].inthreeway) {
03242          master = p0;
03243          slave = p1;
03244          nothingok = 0;
03245       }
03246    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03247       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
03248          don't put us in anything */
03249       if (p1->subs[SUB_CALLWAIT].inthreeway) {
03250          master = p1;
03251          slave = p0;
03252          nothingok = 0;
03253       }
03254    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03255       /* Same as previous */
03256       if (p0->subs[SUB_CALLWAIT].inthreeway) {
03257          master = p0;
03258          slave = p1;
03259          nothingok = 0;
03260       }
03261    }
03262    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03263       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03264    if (master && slave) {
03265       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
03266          in an active threeway call with a channel that is ringing, we should
03267          indicate ringing. */
03268       if ((oi1 == SUB_THREEWAY) && 
03269           p1->subs[SUB_THREEWAY].inthreeway && 
03270           p1->subs[SUB_REAL].owner && 
03271           p1->subs[SUB_REAL].inthreeway && 
03272           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03273          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03274          tone_zone_play_tone(p0->subs[oi0].zfd, ZT_TONE_RINGTONE);
03275          os1 = p1->subs[SUB_REAL].owner->_state;
03276       } else {
03277          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03278          tone_zone_play_tone(p0->subs[oi0].zfd, -1);
03279       }
03280       if ((oi0 == SUB_THREEWAY) && 
03281           p0->subs[SUB_THREEWAY].inthreeway && 
03282           p0->subs[SUB_REAL].owner && 
03283           p0->subs[SUB_REAL].inthreeway && 
03284           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03285          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03286          tone_zone_play_tone(p1->subs[oi1].zfd, ZT_TONE_RINGTONE);
03287          os0 = p0->subs[SUB_REAL].owner->_state;
03288       } else {
03289          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03290          tone_zone_play_tone(p1->subs[oi0].zfd, -1);
03291       }
03292       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03293          if (!p0->echocanbridged || !p1->echocanbridged) {
03294             /* Disable echo cancellation if appropriate */
03295             zt_disable_ec(p0);
03296             zt_disable_ec(p1);
03297          }
03298       }
03299       zt_link(slave, master);
03300       master->inconference = inconf;
03301    } else if (!nothingok)
03302       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03303 
03304    update_conf(p0);
03305    update_conf(p1);
03306    t0 = p0->subs[SUB_REAL].inthreeway;
03307    t1 = p1->subs[SUB_REAL].inthreeway;
03308 
03309    ast_mutex_unlock(&p0->lock);
03310    ast_mutex_unlock(&p1->lock);
03311 
03312    ast_mutex_unlock(&c0->lock);
03313    ast_mutex_unlock(&c1->lock);
03314 
03315    /* Native bridge failed */
03316    if ((!master || !slave) && !nothingok) {
03317       zt_enable_ec(p0);
03318       zt_enable_ec(p1);
03319       return AST_BRIDGE_FAILED;
03320    }
03321    
03322    if (option_verbose > 2) 
03323       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03324 
03325    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03326       disable_dtmf_detect(op0);
03327 
03328    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03329       disable_dtmf_detect(op1);
03330 
03331    for (;;) {
03332       struct ast_channel *c0_priority[2] = {c0, c1};
03333       struct ast_channel *c1_priority[2] = {c1, c0};
03334 
03335       /* Here's our main loop...  Start by locking things, looking for private parts, 
03336          and then balking if anything is wrong */
03337       ast_mutex_lock(&c0->lock);
03338       ast_mutex_lock(&c1->lock);
03339       p0 = c0->tech_pvt;
03340       p1 = c1->tech_pvt;
03341 
03342       if (op0 == p0)
03343          i0 = zt_get_index(c0, p0, 1);
03344       if (op1 == p1)
03345          i1 = zt_get_index(c1, p1, 1);
03346       ast_mutex_unlock(&c0->lock);
03347       ast_mutex_unlock(&c1->lock);
03348 
03349       if (!timeoutms || 
03350           (op0 != p0) ||
03351           (op1 != p1) || 
03352           (ofd0 != c0->fds[0]) || 
03353           (ofd1 != c1->fds[0]) ||
03354           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
03355           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
03356           (oc0 != p0->owner) || 
03357           (oc1 != p1->owner) ||
03358           (t0 != p0->subs[SUB_REAL].inthreeway) ||
03359           (t1 != p1->subs[SUB_REAL].inthreeway) ||
03360           (oi0 != i0) ||
03361           (oi1 != i1)) {
03362          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03363             op0->channel, oi0, op1->channel, oi1);
03364          res = AST_BRIDGE_RETRY;
03365          goto return_from_bridge;
03366       }
03367 
03368 #ifdef PRI_2BCT
03369       q931c0 = p0->call;
03370       q931c1 = p1->call;
03371       if (p0->transfer && p1->transfer 
03372           && q931c0 && q931c1 
03373           && !triedtopribridge) {
03374          pri_channel_bridge(q931c0, q931c1);
03375          triedtopribridge = 1;
03376       }
03377 #endif
03378 
03379       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03380       if (!who) {
03381          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03382          continue;
03383       }
03384       f = ast_read(who);
03385       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03386          *fo = f;
03387          *rc = who;
03388          res = AST_BRIDGE_COMPLETE;
03389          goto return_from_bridge;
03390       }
03391       if (f->frametype == AST_FRAME_DTMF) {
03392          if ((who == c0) && p0->pulsedial) {
03393             ast_write(c1, f);
03394          } else if ((who == c1) && p1->pulsedial) {
03395             ast_write(c0, f);
03396          } else {
03397             *fo = f;
03398             *rc = who;
03399             res = AST_BRIDGE_COMPLETE;
03400             goto return_from_bridge;
03401          }
03402       }
03403       ast_frfree(f);
03404       
03405       /* Swap who gets priority */
03406       priority = !priority;
03407    }
03408 
03409 return_from_bridge:
03410    if (op0 == p0)
03411       zt_enable_ec(p0);
03412 
03413    if (op1 == p1)
03414       zt_enable_ec(p1);
03415 
03416    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03417       enable_dtmf_detect(op0);
03418 
03419    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03420       enable_dtmf_detect(op1);
03421 
03422    zt_unlink(slave, master, 1);
03423 
03424    return res;
03425 }

static int zt_call ( struct ast_channel ast,
char *  rdest,
int  timeout 
) [static]

Definition at line 1769 of file chan_zap.c.

References ast_channel::_state, ast_callerid_generate(), AST_LAW, ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), zt_pvt::callwait_name, zt_pvt::callwait_num, zt_pvt::callwaitcas, zt_pvt::callwaitrings, zt_pvt::channel, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, zt_pvt::cidlen, zt_pvt::cidpos, zt_pvt::cidrings, zt_pvt::cidspill, zt_pvt::dialdest, zt_pvt::dialednone, zt_pvt::dialing, zt_pvt::digital, zt_pvt::distinctivering, zt_pvt::dop, zt_pvt::echobreak, zt_pvt::echorest, zt_pvt::echotraining, zt_pvt::finaldial, free, zt_pvt::hidecallerid, zt_pvt::hidecalleridname, IS_DIGITAL, zt_pvt::lastcid_name, zt_pvt::lastcid_num, zt_pvt::law, zt_pvt::lock, LOG_DEBUG, LOG_WARNING, MAX_CALLERID_SIZE, zt_subchannel::needbusy, zt_subchannel::needringing, zt_pvt::oprmode, option_verbose, zt_pvt::outgoing, zt_pvt::outsigmod, zt_pvt::owner, pbx_builtin_getvar_helper(), PRI_TRANS_CAP_DIGITAL, zt_pvt::priexclusive, zt_pvt::pulse, zt_pvt::radio, zt_pvt::rxgain, s, send_callerid(), zt_pvt::sendcalleridafter, set_actual_gain(), zt_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, zt_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, zt_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, zt_pvt::txgain, zt_pvt::use_callerid, zt_pvt::use_callingpres, VERBOSE_PREFIX_3, zt_pvt::whichwink, zt_subchannel::zfd, zt_callwait(), and zt_get_index().

01770 {
01771    struct zt_pvt *p = ast->tech_pvt;
01772    int x, res, index,mysig;
01773    char *c, *n, *l;
01774 #ifdef HAVE_PRI
01775    char *s = NULL;
01776 #endif
01777    char dest[256]; /* must be same length as p->dialdest */
01778    ast_mutex_lock(&p->lock);
01779    ast_copy_string(dest, rdest, sizeof(dest));
01780    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
01781    if ((ast->_state == AST_STATE_BUSY)) {
01782       p->subs[SUB_REAL].needbusy = 1;
01783       ast_mutex_unlock(&p->lock);
01784       return 0;
01785    }
01786    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01787       ast_log(LOG_WARNING, "zt_call called on %s, neither down nor reserved\n", ast->name);
01788       ast_mutex_unlock(&p->lock);
01789       return -1;
01790    }
01791    p->dialednone = 0;
01792    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
01793    {
01794       /* Special pseudo -- automatically up */
01795       ast_setstate(ast, AST_STATE_UP); 
01796       ast_mutex_unlock(&p->lock);
01797       return 0;
01798    }
01799    x = ZT_FLUSH_READ | ZT_FLUSH_WRITE;
01800    res = ioctl(p->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
01801    if (res)
01802       ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
01803    p->outgoing = 1;
01804 
01805    set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
01806 
01807    mysig = p->sig;
01808    if (p->outsigmod > -1)
01809       mysig = p->outsigmod;
01810 
01811    switch (mysig) {
01812    case SIG_FXOLS:
01813    case SIG_FXOGS:
01814    case SIG_FXOKS:
01815       if (p->owner == ast) {
01816          /* Normal ring, on hook */
01817          
01818          /* Don't send audio while on hook, until the call is answered */
01819          p->dialing = 1;
01820          if (p->use_callerid) {
01821             /* Generate the Caller-ID spill if desired */
01822             if (p->cidspill) {
01823                ast_log(LOG_WARNING, "cidspill already exists??\n");
01824                free(p->cidspill);
01825             }
01826             p->callwaitcas = 0;
01827             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01828                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
01829                p->cidpos = 0;
01830                send_callerid(p);
01831             }
01832          }
01833          /* Choose proper cadence */
01834          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
01835             if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCADENCE, &cadences[p->distinctivering - 1]))
01836                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s'\n", p->distinctivering, ast->name);
01837             p->cidrings = cidrings[p->distinctivering - 1];
01838          } else {
01839             if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCADENCE, NULL))
01840                ast_log(LOG_WARNING, "Unable to reset default ring on '%s'\n", ast->name);
01841             p->cidrings = p->sendcalleridafter;
01842          }
01843 
01844          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
01845          c = strchr(dest, '/');
01846          if (c)
01847             c++;
01848          if (c && (strlen(c) < p->stripmsd)) {
01849             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01850             c = NULL;
01851          }
01852          if (c) {
01853             p->dop.op = ZT_DIAL_OP_REPLACE;
01854             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
01855             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
01856          } else {
01857             p->dop.dialstr[0] = '\0';
01858          }
01859          x = ZT_RING;
01860          if (ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x) && (errno != EINPROGRESS)) {
01861             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
01862             ast_mutex_unlock(&p->lock);
01863             return -1;
01864          }
01865          p->dialing = 1;
01866       } else {
01867          /* Call waiting call */
01868          p->callwaitrings = 0;
01869          if (ast->cid.cid_num)
01870             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
01871          else
01872             p->callwait_num[0] = '\0';
01873          if (ast->cid.cid_name)
01874             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
01875          else
01876             p->callwait_name[0] = '\0';
01877          /* Call waiting tone instead */
01878          if (zt_callwait(ast)) {
01879             ast_mutex_unlock(&p->lock);
01880             return -1;
01881          }
01882          /* Make ring-back */
01883          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].zfd, ZT_TONE_RINGTONE))
01884             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
01885             
01886       }
01887       n = ast->cid.cid_name;
01888       l = ast->cid.cid_num;
01889       if (l)
01890          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
01891       else
01892          p->lastcid_num[0] = '\0';
01893       if (n)
01894          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
01895       else
01896          p->lastcid_name[0] = '\0';
01897       ast_setstate(ast, AST_STATE_RINGING);
01898       index = zt_get_index(ast, p, 0);
01899       if (index > -1) {
01900          p->subs[index].needringing = 1;
01901       }
01902       break;
01903    case SIG_FXSLS:
01904    case SIG_FXSGS:
01905    case SIG_FXSKS:
01906    case SIG_EMWINK:
01907    case SIG_EM:
01908    case SIG_EM_E1:
01909    case SIG_FEATD:
01910    case SIG_FEATDMF:
01911    case SIG_E911:
01912    case SIG_FGC_CAMA:
01913    case SIG_FGC_CAMAMF:
01914    case SIG_FEATB:
01915    case SIG_SFWINK:
01916    case SIG_SF:
01917    case SIG_SF_FEATD:
01918    case SIG_SF_FEATDMF:
01919    case SIG_FEATDMF_TA:
01920    case SIG_SF_FEATB:
01921       c = strchr(dest, '/');
01922       if (c)
01923          c++;
01924       else
01925          c = "";
01926       if (strlen(c) < p->stripmsd) {
01927          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01928          ast_mutex_unlock(&p->lock);
01929          return -1;
01930       }
01931 #ifdef HAVE_PRI
01932       /* Start the trunk, if not GR-303 */
01933       if (!p->pri) {
01934 #endif
01935          x = ZT_START;
01936          res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
01937          if (res < 0) {
01938             if (errno != EINPROGRESS) {
01939                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
01940                ast_mutex_unlock(&p->lock);
01941                return -1;
01942             }
01943          }
01944 #ifdef HAVE_PRI
01945       }
01946 #endif
01947       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
01948       p->dop.op = ZT_DIAL_OP_REPLACE;
01949 
01950       c += p->stripmsd;
01951 
01952       switch (mysig) {
01953       case SIG_FEATD:
01954          l = ast->cid.cid_num;
01955          if (l) 
01956             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
01957          else
01958             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
01959          break;
01960       case SIG_FEATDMF:
01961          l = ast->cid.cid_num;
01962          if (l) 
01963             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
01964          else
01965             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
01966          break;
01967       case SIG_FEATDMF_TA:
01968       {
01969          const char *cic, *ozz;
01970 
01971          /* If you have to go through a Tandem Access point you need to use this */
01972          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
01973          if (!ozz)
01974             ozz = defaultozz;
01975          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
01976          if (!cic)
01977             cic = defaultcic;
01978          if (!ozz || !cic) {
01979             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
01980             ast_mutex_unlock(&p->lock);
01981             return -1;
01982          }
01983          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
01984          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
01985          p->whichwink = 0;
01986       }
01987          break;
01988       case SIG_E911:
01989          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
01990          break;
01991       case SIG_FGC_CAMA:
01992          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
01993          break;
01994       case SIG_FGC_CAMAMF:
01995       case SIG_FEATB:
01996          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
01997          break;
01998       default:
01999          if (p->pulse)
02000             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02001          else
02002             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02003          break;
02004       }
02005 
02006       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02007          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02008          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02009          p->echorest[sizeof(p->echorest) - 1] = '\0';
02010          p->echobreak = 1;
02011          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02012       } else
02013          p->echobreak = 0;
02014       if (!res) {
02015          if (ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop)) {
02016             x = ZT_ONHOOK;
02017             ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
02018             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno));
02019             ast_mutex_unlock(&p->lock);
02020             return -1;
02021          }
02022       } else
02023          ast_log(LOG_DEBUG, "Deferring dialing...\n");
02024       p->dialing = 1;
02025       if (ast_strlen_zero(c))
02026          p->dialednone = 1;
02027       ast_setstate(ast, AST_STATE_DIALING);
02028       break;
02029    case 0:
02030       /* Special pseudo -- automatically up*/
02031       ast_setstate(ast, AST_STATE_UP);
02032       break;      
02033    case SIG_PRI:
02034       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02035       p->dialdest[0] = '\0';
02036       break;
02037    default:
02038       ast_log(LOG_DEBUG, "not yet implemented\n");
02039       ast_mutex_unlock(&p->lock);
02040       return -1;
02041    }
02042 #ifdef HAVE_PRI
02043    if (p->pri) {
02044       struct pri_sr *sr;
02045 #ifdef SUPPORT_USERUSER
02046       const char *useruser;
02047 #endif
02048       int pridialplan;
02049       int dp_strip;
02050       int prilocaldialplan;
02051       int ldp_strip;
02052       int exclusive;
02053       const char *rr_str;
02054       int redirect_reason;
02055 
02056       c = strchr(dest, '/');
02057       if (c)
02058          c++;
02059       else
02060          c = dest;
02061       if (!p->hidecalleridname)
02062          n = ast->cid.cid_name;
02063       else
02064          n = NULL;
02065       if (!p->hidecallerid) {
02066          l = ast->cid.cid_num;
02067          n = ast->cid.cid_name;
02068       } else {
02069          l = NULL;
02070          n = NULL;
02071       }
02072       if (strlen(c) < p->stripmsd) {
02073          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02074          ast_mutex_unlock(&p->lock);
02075          return -1;
02076       }
02077       if (mysig != SIG_FXSKS) {
02078          p->dop.op = ZT_DIAL_OP_REPLACE;
02079          s = strchr(c + p->stripmsd, 'w');
02080          if (s) {
02081             if (strlen(s) > 1)
02082                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02083             else
02084                p->dop.dialstr[0] = '\0';
02085             *s = '\0';
02086          } else {
02087             p->dop.dialstr[0] = '\0';
02088          }
02089       }
02090       if (pri_grab(p, p->pri)) {
02091          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02092          ast_mutex_unlock(&p->lock);
02093          return -1;
02094       }
02095       if (!(p->call = pri_new_call(p->pri->pri))) {
02096          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02097          pri_rel(p->pri);
02098          ast_mutex_unlock(&p->lock);
02099          return -1;
02100       }
02101       if (!(sr = pri_sr_new())) {
02102          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02103          pri_rel(p->pri);
02104          ast_mutex_unlock(&p->lock);
02105       }
02106       if (p->bearer || (mysig == SIG_FXSKS)) {
02107          if (p->bearer) {
02108             ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02109             p->bearer->call = p->call;
02110          } else
02111             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02112          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02113       }
02114       p->digital = IS_DIGITAL(ast->transfercapability);
02115       /* Add support for exclusive override */
02116       if (p->priexclusive)
02117          exclusive = 1;
02118       else {
02119       /* otherwise, traditional behavior */
02120          if (p->pri->nodetype == PRI_NETWORK)
02121             exclusive = 0;
02122          else
02123             exclusive = 1;
02124       }
02125       
02126       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02127       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02128                (p->digital ? -1 : 
02129                   ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02130       if (p->pri->facilityenable)
02131          pri_facility_enable(p->pri->pri);
02132 
02133       if (option_verbose > 2)
02134          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02135       dp_strip = 0;
02136       pridialplan = p->pri->dialplan - 1;
02137       if (pridialplan == -2) { /* compute dynamically */
02138          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02139             dp_strip = strlen(p->pri->internationalprefix);
02140             pridialplan = PRI_INTERNATIONAL_ISDN;
02141          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02142             dp_strip = strlen(p->pri->nationalprefix);
02143             pridialplan = PRI_NATIONAL_ISDN;
02144          } else {
02145             pridialplan = PRI_LOCAL_ISDN;
02146          }
02147       }
02148       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02149 
02150       ldp_strip = 0;
02151       prilocaldialplan = p->pri->localdialplan - 1;
02152       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
02153          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02154             ldp_strip = strlen(p->pri->internationalprefix);
02155             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02156          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02157             ldp_strip = strlen(p->pri->nationalprefix);
02158             prilocaldialplan = PRI_NATIONAL_ISDN;
02159          } else {
02160             prilocaldialplan = PRI_LOCAL_ISDN;
02161          }
02162       }
02163       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02164          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02165       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02166          if (!strcasecmp(rr_str, "UNKNOWN"))
02167             redirect_reason = 0;
02168          else if (!strcasecmp(rr_str, "BUSY"))
02169             redirect_reason = 1;
02170          else if (!strcasecmp(rr_str, "NO_REPLY"))
02171             redirect_reason = 2;
02172          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02173             redirect_reason = 15;
02174          else
02175             redirect_reason = PRI_REDIR_UNCONDITIONAL;
02176       } else
02177          redirect_reason = PRI_REDIR_UNCONDITIONAL;
02178       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02179 
02180 #ifdef SUPPORT_USERUSER
02181       /* User-user info */
02182       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02183 
02184       if (useruser)
02185          pri_sr_set_useruser(sr, useruser);
02186 #endif
02187 
02188       if (pri_setup(p->pri->pri, p->call, sr)) {
02189          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
02190             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02191          pri_rel(p->pri);
02192          ast_mutex_unlock(&p->lock);
02193          pri_sr_free(sr);
02194          return -1;
02195       }
02196       pri_sr_free(sr);
02197       ast_setstate(ast, AST_STATE_DIALING);
02198       pri_rel(p->pri);
02199    }
02200 #endif      
02201    ast_mutex_unlock(&p->lock);
02202    return 0;
02203 }

static int zt_callwait ( struct ast_channel ast  )  [static]

Definition at line 1741 of file chan_zap.c.

References ast_gen_cas(), AST_LAW, ast_log(), ast_malloc, zt_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, zt_pvt::callwaitingcallerid, zt_pvt::callwaitingrepeat, zt_pvt::callwaitrings, zt_pvt::cidlen, zt_pvt::cidpos, zt_pvt::cidspill, free, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.

Referenced by zt_call(), and zt_read().

01742 {
01743    struct zt_pvt *p = ast->tech_pvt;
01744    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01745    if (p->cidspill) {
01746       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01747       free(p->cidspill);
01748    }
01749    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01750       return -1;
01751    save_conference(p);
01752    /* Silence */
01753    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01754    if (!p->callwaitrings && p->callwaitingcallerid) {
01755       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01756       p->callwaitcas = 1;
01757       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01758    } else {
01759       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01760       p->callwaitcas = 0;
01761       p->cidlen = 2400 + READ_SIZE * 4;
01762    }
01763    p->cidpos = 0;
01764    send_callerid(p);
01765    
01766    return 0;
01767 }

static struct zt_chan_conf zt_chan_conf_default ( void   )  [static, read]

returns a new zt_chan_conf with default values (by-value)

Definition at line 599 of file chan_zap.c.

References zt_chan_conf::chan, CID_SIG_BELL, CID_START_RING, zt_pvt::context, and DEFAULT_CIDRINGS.

Referenced by setup_zap().

00599                                                       {
00600    /* recall that if a field is not included here it is initialized
00601     * to 0 or equivalent
00602     */
00603    struct zt_chan_conf conf = {
00604 #ifdef HAVE_PRI
00605       .pri = {
00606          .nsf = PRI_NSF_NONE,
00607          .switchtype = PRI_SWITCH_NI2,
00608          .dialplan = PRI_NATIONAL_ISDN + 1,
00609          .localdialplan = PRI_NATIONAL_ISDN + 1,
00610          .nodetype = PRI_CPE,
00611 
00612          .minunused = 2,
00613          .idleext = "",
00614          .idledial = "",
00615          .internationalprefix = "",
00616          .nationalprefix = "",
00617          .localprefix = "",
00618          .privateprefix = "",
00619          .unknownprefix = "",
00620 
00621          .resetinterval = 3600
00622       },
00623 #endif
00624       .chan = {
00625          .context = "default",
00626          .cid_num = "",
00627          .cid_name = "",
00628          .mohinterpret = "default",
00629          .mohsuggest = "",
00630          .transfertobusy = 1,
00631 
00632          .cid_signalling = CID_SIG_BELL,
00633          .cid_start = CID_START_RING,
00634          .zaptrcallerid = 0,
00635          .use_callerid = 1,
00636          .sig = -1,
00637          .outsigmod = -1,
00638 
00639          .tonezone = -1,
00640 
00641          .echocancel = 1,
00642 
00643          .busycount = 3,
00644 
00645          .accountcode = "",
00646 
00647          .mailbox = "",
00648 
00649 
00650          .polarityonanswerdelay = 600,
00651 
00652          .sendcalleridafter = DEFAULT_CIDRINGS
00653       },
00654       .timing = {
00655          .prewinktime = -1,
00656          .preflashtime = -1,
00657          .winktime = -1,
00658          .flashtime = -1,
00659          .starttime = -1,
00660          .rxwinktime = -1,
00661          .rxflashtime = -1,
00662          .debouncetime = -1
00663       },
00664       .smdi_port = "/dev/ttyS0",
00665    };
00666 
00667    return conf;
00668 }

static void zt_close ( int  fd  )  [static]

Definition at line 912 of file chan_zap.c.

Referenced by __unload_module(), alloc_sub(), destroy_channel(), and unalloc_sub().

00913 {
00914    if (fd > 0)
00915       close(fd);
00916 }

static int zt_confmute ( struct zt_pvt p,
int  muted 
) [inline, static]

Definition at line 1624 of file chan_zap.c.

References ast_log(), zt_pvt::channel, LOG_WARNING, zt_pvt::sig, SIG_PRI, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by zt_handle_dtmfup(), zt_handle_event(), zt_hangup(), and zt_new().

01625 {
01626    int x, y, res;
01627    x = muted;
01628    if (p->sig == SIG_PRI) {
01629       y = 1;
01630       res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
01631       if (res)
01632          ast_log(LOG_WARNING, "Unable to set audio mode on '%d'\n", p->channel);
01633    }
01634    res = ioctl(p->subs[SUB_REAL].zfd, ZT_CONFMUTE, &x);
01635    if (res < 0)
01636       ast_log(LOG_WARNING, "zt confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01637    return res;
01638 }

static int zt_digit_begin ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 999 of file chan_zap.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, zt_pvt::begindigit, zt_pvt::dialdest, zt_pvt::dialing, digit_to_dtmfindex(), zt_pvt::lock, LOG_DEBUG, LOG_WARNING, zt_pvt::owner, zt_pvt::pulse, zt_pvt::sig, SIG_PRI, zt_pvt::span, SUB_REAL, zt_pvt::subs, ast_channel::tech_pvt, zt_subchannel::zfd, and zt_get_index().

01000 {
01001    struct zt_pvt *pvt;
01002    int index;
01003    int dtmf = -1;
01004    
01005    pvt = chan->tech_pvt;
01006 
01007    ast_mutex_lock(&pvt->lock);
01008 
01009    index = zt_get_index(chan, pvt, 0);
01010 
01011    if ((index != SUB_REAL) || !pvt->owner)
01012       goto out;
01013 
01014 #ifdef HAVE_PRI
01015    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01016       if (pvt->setup_ack) {
01017          if (!pri_grab(pvt, pvt->pri)) {
01018             pri_information(pvt->pri->pri, pvt->call, digit);
01019             pri_rel(pvt->pri);
01020          } else
01021             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01022       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01023          int res;
01024          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01025          res = strlen(pvt->dialdest);
01026          pvt->dialdest[res++] = digit;
01027          pvt->dialdest[res] = '\0';
01028       }
01029       goto out;
01030    }
01031 #endif
01032    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01033       goto out;
01034 
01035    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &dtmf)) {
01036       int res;
01037       ZT_DIAL_OPERATION zo = {
01038          .op = ZT_DIAL_OP_APPEND,
01039          .dialstr[0] = 'T',
01040          .dialstr[1] = digit,
01041          .dialstr[2] = 0,
01042       };
01043       if ((res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_DIAL, &zo)))
01044          ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
01045       else
01046          pvt->dialing = 1;
01047    } else {
01048       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01049       pvt->dialing = 1;
01050       pvt->begindigit = digit;
01051    }
01052 
01053 out:
01054    ast_mutex_unlock(&pvt->lock);
01055 
01056    return 0;
01057 }

static int zt_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 1059 of file chan_zap.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), zt_pvt::begindigit, zt_pvt::dialing, zt_pvt::lock, LOG_DEBUG, zt_pvt::owner, zt_pvt::pulse, zt_pvt::sig, SIG_PRI, SUB_REAL, zt_pvt::subs, ast_channel::tech_pvt, zt_subchannel::zfd, and zt_get_index().

01060 {
01061    struct zt_pvt *pvt;
01062    int res = 0;
01063    int index;
01064    int x;
01065    
01066    pvt = chan->tech_pvt;
01067 
01068    ast_mutex_lock(&pvt->lock);
01069    
01070    index = zt_get_index(chan, pvt, 0);
01071 
01072    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01073       goto out;
01074 
01075 #ifdef HAVE_PRI
01076    /* This means that the digit was already sent via PRI signalling */
01077    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01078       goto out;
01079 #endif
01080 
01081    if (pvt->begindigit) {
01082       x = -1;
01083       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01084       res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &x);
01085       pvt->dialing = 0;
01086       pvt->begindigit = 0;
01087    }
01088 
01089 out:
01090    ast_mutex_unlock(&pvt->lock);
01091 
01092    return res;
01093 }

static void zt_disable_ec ( struct zt_pvt p  )  [static]

Definition at line 1456 of file chan_zap.c.

References ast_log(), zt_pvt::channel, zt_pvt::echocancel, zt_pvt::echocanon, LOG_DEBUG, LOG_WARNING, option_debug, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by __zt_exception(), handle_init_event(), zt_bridge(), zt_handle_event(), zt_hangup(), and zt_setoption().

01457 {
01458    int x;
01459    int res;
01460    if (p->echocancel) {
01461       x = 0;
01462       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01463       if (res)
01464          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
01465       else if (option_debug)
01466          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01467    }
01468    p->echocanon = 0;
01469 }

static void zt_enable_ec ( struct zt_pvt p  )  [static]

Definition at line 1406 of file chan_zap.c.

References ast_log(), zt_pvt::channel, zt_pvt::digital, zt_pvt::echocancel, zt_pvt::echocanon, LOG_DEBUG, LOG_WARNING, option_debug, zt_pvt::sig, SIG_PRI, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by handle_init_event(), ss_thread(), zt_answer(), zt_bridge(), zt_handle_event(), and zt_setoption().

01407 {
01408    int x;
01409    int res;
01410    if (!p)
01411       return;
01412    if (p->echocanon) {
01413       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01414       return;
01415    }
01416    if (p->digital) {
01417       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01418       return;
01419    }
01420    if (p->echocancel) {
01421       if (p->sig == SIG_PRI) {
01422          x = 1;
01423          res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x);
01424          if (res)
01425             ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d\n", p->channel);
01426       }
01427       x = p->echocancel;
01428       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01429       if (res) 
01430          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d\n", p->channel);
01431       else {
01432          p->echocanon = 1;
01433          if (option_debug)
01434             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01435       }
01436    } else if (option_debug)
01437       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01438 }

static struct ast_frame * zt_exception ( struct ast_channel ast  )  [static, read]

Definition at line 4593 of file chan_zap.c.

References __zt_exception(), ast_mutex_lock(), ast_mutex_unlock(), zt_pvt::lock, and ast_channel::tech_pvt.

04594 {
04595    struct zt_pvt *p = ast->tech_pvt;
04596    struct ast_frame *f;
04597    ast_mutex_lock(&p->lock);
04598    f = __zt_exception(ast);
04599    ast_mutex_unlock(&p->lock);
04600    return f;
04601 }

static int zt_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 3427 of file chan_zap.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, zt_pvt::channel, zt_pvt::lock, LOG_DEBUG, zt_subchannel::owner, zt_pvt::owner, zt_pvt::subs, ast_channel::tech_pvt, update_conf(), zt_indicate(), and zt_unlink().

03428 {
03429    struct zt_pvt *p = newchan->tech_pvt;
03430    int x;
03431    ast_mutex_lock(&p->lock);
03432    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03433    if (p->owner == oldchan) {
03434       p->owner = newchan;
03435    }
03436    for (x = 0; x < 3; x++)
03437       if (p->subs[x].owner == oldchan) {
03438          if (!x)
03439             zt_unlink(NULL, p, 0);
03440          p->subs[x].owner = newchan;
03441       }
03442    if (newchan->_state == AST_STATE_RINGING) 
03443       zt_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03444    update_conf(p);
03445    ast_mutex_unlock(&p->lock);
03446    return 0;
03447 }

static int zt_func_read ( struct ast_channel chan,
char *  function,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 3002 of file chan_zap.c.

References ast_mutex_lock(), ast_mutex_unlock(), zt_pvt::lock, zt_pvt::rxgain, ast_channel::tech_pvt, and zt_pvt::txgain.

03003 {
03004    struct zt_pvt *p = chan->tech_pvt;
03005    
03006    if (!strcasecmp(data, "rxgain")) {
03007       ast_mutex_lock(&p->lock);
03008       snprintf(buf, len, "%f", p->rxgain);
03009       ast_mutex_unlock(&p->lock);   
03010    } else if (!strcasecmp(data, "txgain")) {
03011       ast_mutex_lock(&p->lock);
03012       snprintf(buf, len, "%f", p->txgain);
03013       ast_mutex_unlock(&p->lock);   
03014    } else {
03015       ast_copy_string(buf, "", len);
03016    }
03017    return 0;
03018 }

static int zt_get_event ( int  fd  )  [inline, static]

Avoid the silly zt_getevent which ignores a bunch of events.

Definition at line 256 of file chan_zap.c.

Referenced by __zt_exception(), do_monitor(), ss_thread(), and zt_handle_event().

00257 {
00258    int j;
00259    if (ioctl(fd, ZT_GETEVENT, &j) == -1)
00260       return -1;
00261    return j;
00262 }

static int zt_get_index ( struct ast_channel ast,
struct zt_pvt p,
int  nullok 
) [static]

Definition at line 763 of file chan_zap.c.

References ast_log(), LOG_WARNING, zt_subchannel::owner, and zt_pvt::subs.

Referenced by __zt_exception(), ss_thread(), zt_answer(), zt_bridge(), zt_call(), zt_digit_begin(), zt_digit_end(), zt_handle_event(), zt_hangup(), zt_indicate(), zt_read(), zt_sendtext(), zt_setoption(), and zt_write().

00764 {
00765    int res;
00766    if (p->subs[0].owner == ast)
00767       res = 0;
00768    else if (p->subs[1].owner == ast)
00769       res = 1;
00770    else if (p->subs[2].owner == ast)
00771       res = 2;
00772    else {
00773       res = -1;
00774       if (!nullok)
00775          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
00776    }
00777    return res;
00778 }

static void zt_handle_dtmfup ( struct ast_channel ast,
int  index,
struct ast_frame **  dest 
) [static]

Definition at line 3595 of file chan_zap.c.

References ast_async_goto(), AST_CONTROL_ANSWER, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_log(), ast_verbose(), zt_pvt::callprogress, zt_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, zt_pvt::cidspill, zt_pvt::confirmanswer, ast_channel::context, ast_channel::exten, zt_subchannel::f, zt_pvt::faxhandled, ast_frame::frametype, free, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, option_debug, option_verbose, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, zt_pvt::subs, ast_channel::tech_pvt, VERBOSE_PREFIX_3, and zt_confmute().

Referenced by zt_handle_event(), and zt_read().

03596 {
03597    struct zt_pvt *p = ast->tech_pvt;
03598    struct ast_frame *f = *dest;
03599 
03600    if (option_debug)
03601       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
03602 
03603    if (p->confirmanswer) {
03604       if (option_debug)
03605          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
03606       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
03607          of a DTMF digit */
03608       p->subs[index].f.frametype = AST_FRAME_CONTROL;
03609       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03610       *dest = &p->subs[index].f;
03611       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
03612       p->confirmanswer = 0;
03613    } else if (p->callwaitcas) {
03614       if ((f->subclass == 'A') || (f->subclass == 'D')) {
03615          if (option_debug)
03616             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
03617          if (p->cidspill)
03618             free(p->cidspill);
03619          send_cwcidspill(p);
03620       }
03621       if ((f->subclass != 'm') && (f->subclass != 'u')) 
03622          p->callwaitcas = 0;
03623       p->subs[index].f.frametype = AST_FRAME_NULL;
03624       p->subs[index].f.subclass = 0;
03625       *dest = &p->subs[index].f;
03626    } else if (f->subclass == 'f') {
03627       /* Fax tone -- Handle and return NULL */
03628       if ((p->callprogress & 0x6) && !p->faxhandled) {
03629          p->faxhandled++;
03630          if (strcmp(ast->exten, "fax")) {
03631             const char *target_context = S_OR(ast->macrocontext, ast->context);
03632 
03633             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
03634                if (option_verbose > 2)
03635                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
03636                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
03637                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
03638                if (ast_async_goto(ast, target_context, "fax", 1))
03639                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
03640             } else
03641                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
03642          } else if (option_debug)
03643             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
03644       } else if (option_debug)
03645             ast_log(LOG_DEBUG, "Fax already handled\n");
03646       zt_confmute(p, 0);
03647       p->subs[index].f.frametype = AST_FRAME_NULL;
03648       p->subs[index].f.subclass = 0;
03649       *dest = &p->subs[index].f;
03650    } else if (f->subclass == 'm') {
03651       /* Confmute request */
03652       zt_confmute(p, 1);
03653       p->subs[index].f.frametype = AST_FRAME_NULL;
03654       p->subs[index].f.subclass = 0;
03655       *dest = &p->subs[index].f;    
03656    } else if (f->subclass == 'u') {
03657       /* Unmute */
03658       zt_confmute(p, 0);
03659       p->subs[index].f.frametype = AST_FRAME_NULL;
03660       p->subs[index].f.subclass = 0;
03661       *dest = &p->subs[index].f;    
03662    } else
03663       zt_confmute(p, 0);
03664 }

static struct ast_frame* zt_handle_event ( struct ast_channel ast  )  [static, read]

Definition at line 3666 of file chan_zap.c.

References ast_channel::_softhangup, ast_channel::_state, alarm2str(), alloc_sub(), zt_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_pthread_create, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_verbose(), attempt_transfer(), zt_pvt::callprogress, zt_pvt::callwaitcas, zt_pvt::callwaitingrepeat, CANPROGRESSDETECT, zt_pvt::channel, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, zt_pvt::cid_name, ast_callerid::cid_name, cid_name, zt_pvt::cid_num, ast_callerid::cid_num, cid_num, zt_pvt::cidcwexpire, zt_pvt::cidrings, zt_pvt::cidspill, zt_pvt::confirmanswer, ast_frame::data, ast_frame::datalen, zt_pvt::dialdest, zt_pvt::dialednone, zt_pvt::dialing, zt_pvt::dop, zt_pvt::dsp, zt_pvt::echobreak, zt_pvt::echocanon, zt_pvt::echorest, zt_pvt::echotraining, event2str(), EVENT_FLAG_SYSTEM, zt_subchannel::f, zt_pvt::fake_event, zt_pvt::finaldial, zt_pvt::flashtime, ast_frame::frametype, free, get_alarms(), zt_pvt::hanguponpolarityswitch, has_voicemail(), zt_pvt::inalarm, zt_subchannel::inthreeway, zt_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, zt_pvt::mohsuggest, zt_pvt::msgstate, zt_subchannel::needanswer, zt_subchannel::needflash, zt_subchannel::needhold, zt_subchannel::needringing, zt_subchannel::needunhold, ast_frame::offset, zt_pvt::onhooktime, zt_pvt::oprmode, zt_pvt::oprpeer, option_debug, option_verbose, zt_pvt::origcid_name, zt_pvt::origcid_num, zt_pvt::outgoing, zt_pvt::outsigmod, zt_pvt::overlapdial, zt_subchannel::owner, zt_pvt::owner, ast_channel::pbx, zt_pvt::polarity, POLARITY_IDLE, POLARITY_REV, zt_pvt::polaritydelaytv, zt_pvt::polarityonanswerdelay, zt_pvt::pulsedial, zt_pvt::radio, restore_conference(), ast_channel::rings, zt_pvt::ringt, zt_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), zt_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ast_frame::src, ss_thread(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, zt_pvt::subs, swap_subs(), ast_channel::tech_pvt, zt_pvt::threewaycalling, zt_pvt::transfer, zt_pvt::transfertobusy, unalloc_sub(), update_conf(), VERBOSE_PREFIX_3, zt_pvt::whichwink, zt_pvt::zaptrcallerid, zt_subchannel::zfd, zt_confmute(), zt_disable_ec(), zt_enable_ec(), ZT_EVENT_DTMFDOWN, ZT_EVENT_DTMFUP, zt_get_event(), zt_get_index(), zt_handle_dtmfup(), zt_new(), zt_ring_phone(), zt_set_hook(), and zt_train_ec().

Referenced by __zt_exception().

03667 {
03668    int res, x;
03669    int index, mysig;
03670    char *c;
03671    struct zt_pvt *p = ast->tech_pvt;
03672    pthread_t threadid;
03673    pthread_attr_t attr;
03674    struct ast_channel *chan;
03675    struct ast_frame *f;
03676 
03677    index = zt_get_index(ast, p, 0);
03678    mysig = p->sig;
03679    if (p->outsigmod > -1)
03680       mysig = p->outsigmod;
03681    p->subs[index].f.frametype = AST_FRAME_NULL;
03682    p->subs[index].f.subclass = 0;
03683    p->subs[index].f.datalen = 0;
03684    p->subs[index].f.samples = 0;
03685    p->subs[index].f.mallocd = 0;
03686    p->subs[index].f.offset = 0;
03687    p->subs[index].f.src = "zt_handle_event";
03688    p->subs[index].f.data = NULL;
03689    f = &p->subs[index].f;
03690 
03691    if (index < 0)
03692       return &p->subs[index].f;
03693    if (p->fake_event) {
03694       res = p->fake_event;
03695       p->fake_event = 0;
03696    } else
03697       res = zt_get_event(p->subs[index].zfd);
03698 
03699    if (option_debug)
03700       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
03701 
03702    if (res & (ZT_EVENT_PULSEDIGIT | ZT_EVENT_DTMFUP)) {
03703       p->pulsedial =  (res & ZT_EVENT_PULSEDIGIT) ? 1 : 0;
03704 
03705       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
03706 #ifdef HAVE_PRI
03707       if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
03708          /* absorb event */
03709       } else {
03710 #endif
03711          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
03712          p->subs[index].f.subclass = res & 0xff;
03713 #ifdef HAVE_PRI
03714       }
03715 #endif
03716       zt_handle_dtmfup(ast, index, &f);
03717       return f;
03718    }
03719 
03720    if (res & ZT_EVENT_DTMFDOWN) {
03721       if (option_debug)
03722          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
03723       /* Mute conference */
03724       zt_confmute(p, 1);
03725       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
03726       p->subs[index].f.subclass = res & 0xff;
03727       return &p->subs[index].f;
03728    }
03729 
03730    switch (res) {
03731 #ifdef ZT_EVENT_EC_DISABLED
03732       case ZT_EVENT_EC_DISABLED:
03733          if (option_verbose > 2) 
03734             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
03735          p->echocanon = 0;
03736          break;
03737 #endif
03738       case ZT_EVENT_BITSCHANGED:
03739          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
03740       case ZT_EVENT_PULSE_START:
03741          /* Stop tone if there's a pulse start and the PBX isn't started */
03742          if (!ast->pbx)
03743             tone_zone_play_tone(p->subs[index].zfd, -1);
03744          break;   
03745       case ZT_EVENT_DIALCOMPLETE:
03746          if (p->inalarm) break;
03747          if ((p->radio || (p->oprmode < 0))) break;
03748          if (ioctl(p->subs[index].zfd,ZT_DIALING,&x) == -1) {
03749             ast_log(LOG_DEBUG, "ZT_DIALING ioctl failed on %s\n",ast->name);
03750             return NULL;
03751          }
03752          if (!x) { /* if not still dialing in driver */
03753             zt_enable_ec(p);
03754             if (p->echobreak) {
03755                zt_train_ec(p);
03756                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
03757                p->dop.op = ZT_DIAL_OP_REPLACE;
03758                res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop);
03759                p->echobreak = 0;
03760             } else {
03761                p->dialing = 0;
03762                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
03763                   /* if thru with dialing after offhook */
03764                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
03765                      ast_setstate(ast, AST_STATE_UP);
03766                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
03767                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03768                      break;
03769                   } else { /* if to state wait for offhook to dial rest */
03770                      /* we now wait for off hook */
03771                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
03772                   }
03773                }
03774                if (ast->_state == AST_STATE_DIALING) {
03775                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03776                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
03777                   } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) ||  (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
03778                      ast_setstate(ast, AST_STATE_RINGING);
03779                   } else if (!p->answeronpolarityswitch) {
03780                      ast_setstate(ast, AST_STATE_UP);
03781                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
03782                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03783                   }
03784                }
03785             }
03786          }
03787          break;
03788       case ZT_EVENT_ALARM:
03789 #ifdef HAVE_PRI
03790          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
03791             /* T309 is not enabled : hangup calls when alarm occurs */
03792             if (p->call) {
03793                if (p->pri && p->pri->pri) {
03794                   if (!pri_grab(p, p->pri)) {
03795                      pri_hangup(p->pri->pri, p->call, -1);
03796                      pri_destroycall(p->pri->pri, p->call);
03797                      p->call = NULL;
03798                      pri_rel(p->pri);
03799                   } else
03800                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03801                } else
03802                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
03803             }
03804             if (p->owner)
03805                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03806          }
03807          if (p->bearer)
03808             p->bearer->inalarm = 1;
03809          else
03810 #endif
03811          p->inalarm = 1;
03812          res = get_alarms(p);
03813          ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm2str(res));
03814          manager_event(EVENT_FLAG_SYSTEM, "Alarm",
03815                         "Alarm: %s\r\n"
03816                         "Channel: %d\r\n",
03817                         alarm2str(res), p->channel);
03818 #ifdef HAVE_LIBPRI
03819          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
03820             /* fall through intentionally */
03821          } else {
03822             break;
03823          }
03824 #endif
03825       case ZT_EVENT_ONHOOK:
03826          if (p->radio) {
03827             p->subs[index].f.frametype = AST_FRAME_CONTROL;
03828             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
03829             break;
03830          }
03831          if (p->oprmode < 0)
03832          {
03833             if (p->oprmode != -1) break;
03834             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
03835             {
03836                /* Make sure it starts ringing */
03837                zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RINGOFF);
03838                zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RING);
03839                save_conference(p->oprpeer);
03840                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
03841             }
03842             break;
03843          }
03844          switch (p->sig) {
03845          case SIG_FXOLS:
03846          case SIG_FXOGS:
03847          case SIG_FXOKS:
03848             p->onhooktime = time(NULL);
03849             p->msgstate = -1;
03850             /* Check for some special conditions regarding call waiting */
03851             if (index == SUB_REAL) {
03852                /* The normal line was hung up */
03853                if (p->subs[SUB_CALLWAIT].owner) {
03854                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
03855                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03856                   if (option_verbose > 2) 
03857                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
03858                   unalloc_sub(p, SUB_CALLWAIT); 
03859 #if 0
03860                   p->subs[index].needanswer = 0;
03861                   p->subs[index].needringing = 0;
03862 #endif                  
03863                   p->callwaitingrepeat = 0;
03864                   p->cidcwexpire = 0;
03865                   p->owner = NULL;
03866                   /* Don't start streaming audio yet if the incoming call isn't up yet */
03867                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
03868                      p->dialing = 1;
03869                   zt_ring_phone(p);
03870                } else if (p->subs[SUB_THREEWAY].owner) {
03871                   unsigned int mssinceflash;
03872                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
03873                      the private structure -- not especially easy or clean */
03874                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
03875                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
03876                      ast_mutex_unlock(&p->lock);
03877                      ast_mutex_unlock(&ast->lock);
03878                      usleep(1);
03879                      /* We can grab ast and p in that order, without worry.  We should make sure
03880                         nothing seriously bad has happened though like some sort of bizarre double
03881                         masquerade! */
03882                      ast_mutex_lock(&ast->lock);
03883                      ast_mutex_lock(&p->lock);
03884                      if (p->owner != ast) {
03885                         ast_log(LOG_WARNING, "This isn't good...\n");
03886                         return NULL;
03887                      }
03888                   }
03889                   if (!p->subs[SUB_THREEWAY].owner) {
03890                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
03891                      return NULL;
03892                   }
03893                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
03894                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
03895                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
03896                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
03897                         hanging up.  Hangup both channels now */
03898                      if (p->subs[SUB_THREEWAY].owner)
03899                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
03900                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03901                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
03902                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03903                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
03904                      if (p->transfer) {
03905                         /* In any case this isn't a threeway call anymore */
03906                         p->subs[SUB_REAL].inthreeway = 0;
03907                         p->subs[SUB_THREEWAY].inthreeway = 0;
03908                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
03909                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
03910                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03911                            /* Swap subs and dis-own channel */
03912                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
03913                            p->owner = NULL;
03914                            /* Ring the phone */
03915                            zt_ring_phone(p);
03916                         } else {
03917                            if ((res = attempt_transfer(p)) < 0) {
03918                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03919                               if (p->subs[SUB_THREEWAY].owner)
03920                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03921                            } else if (res) {
03922                               /* Don't actually hang up at this point */
03923                               if (p->subs[SUB_THREEWAY].owner)
03924                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03925                               break;
03926                            }
03927                         }
03928                      } else {
03929                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03930                         if (p->subs[SUB_THREEWAY].owner)
03931                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03932                      }
03933                   } else {
03934                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03935                      /* Swap subs and dis-own channel */
03936                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
03937                      p->owner = NULL;
03938                      /* Ring the phone */
03939                      zt_ring_phone(p);
03940                   }
03941                }
03942             } else {
03943                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
03944             }
03945             /* Fall through */
03946          default:
03947             zt_disable_ec(p);
03948             return NULL;
03949          }
03950          break;
03951       case ZT_EVENT_RINGOFFHOOK:
03952          if (p->inalarm) break;
03953          if (p->oprmode < 0)
03954          {
03955             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
03956             {
03957                /* Make sure it stops ringing */
03958                zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RINGOFF);
03959                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, -1);
03960                restore_conference(p->oprpeer);
03961             }
03962             break;
03963          }
03964          if (p->radio)
03965          {
03966             p->subs[index].f.frametype = AST_FRAME_CONTROL;
03967             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
03968             break;
03969          }
03970          /* for E911, its supposed to wait for offhook then dial
03971             the second half of the dial string */
03972          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
03973             c = strchr(p->dialdest, '/');
03974             if (c)
03975                c++;
03976             else
03977                c = p->dialdest;
03978             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
03979             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
03980             if (strlen(p->dop.dialstr) > 4) {
03981                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03982                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03983                p->echorest[sizeof(p->echorest) - 1] = '\0';
03984                p->echobreak = 1;
03985                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03986             } else
03987                p->echobreak = 0;
03988             if (ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop)) {
03989                x = ZT_ONHOOK;
03990                ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03991                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno));
03992                return NULL;
03993                }
03994             p->dialing = 1;
03995             return &p->subs[index].f;
03996          }
03997          switch (p->sig) {
03998          case SIG_FXOLS:
03999          case SIG_FXOGS:
04000          case SIG_FXOKS:
04001             switch (ast->_state) {
04002             case AST_STATE_RINGING:
04003                zt_enable_ec(p);
04004                zt_train_ec(p);
04005                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04006                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04007                /* Make sure it stops ringing */
04008                zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
04009                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04010                if (p->cidspill) {
04011                   /* Cancel any running CallerID spill */
04012                   free(p->cidspill);
04013                   p->cidspill = NULL;
04014                }
04015                p->dialing = 0;
04016                p->callwaitcas = 0;
04017                if (p->confirmanswer) {
04018                   /* Ignore answer if "confirm answer" is enabled */
04019                   p->subs[index].f.frametype = AST_FRAME_NULL;
04020                   p->subs[index].f.subclass = 0;
04021                } else if (!ast_strlen_zero(p->dop.dialstr)) {
04022                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
04023                   res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop);
04024                   if (res < 0) {
04025                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
04026                      p->dop.dialstr[0] = '\0';
04027                      return NULL;
04028                   } else {
04029                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04030                      p->subs[index].f.frametype = AST_FRAME_NULL;
04031                      p->subs[index].f.subclass = 0;
04032                      p->dialing = 1;
04033                   }
04034                   p->dop.dialstr[0] = '\0';
04035                   ast_setstate(ast, AST_STATE_DIALING);
04036                } else
04037                   ast_setstate(ast, AST_STATE_UP);
04038                return &p->subs[index].f;
04039             case AST_STATE_DOWN:
04040                ast_setstate(ast, AST_STATE_RING);
04041                ast->rings = 1;
04042                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04043                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04044                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04045                return &p->subs[index].f;
04046             case AST_STATE_UP:
04047                /* Make sure it stops ringing */
04048                zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
04049                /* Okay -- probably call waiting*/
04050                if (ast_bridged_channel(p->owner))
04051                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04052                p->subs[index].needunhold = 1;
04053                break;
04054             case AST_STATE_RESERVED:
04055                /* Start up dialtone */
04056                if (has_voicemail(p))
04057                   res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_STUTTER);
04058                else
04059                   res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
04060                break;
04061             default:
04062                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04063             }
04064             break;
04065          case SIG_FXSLS:
04066          case SIG_FXSGS:
04067          case SIG_FXSKS:
04068             if (ast->_state == AST_STATE_RING) {
04069                p->ringt = p->ringt_base;
04070             }
04071 
04072             /* If we get a ring then we cannot be in 
04073              * reversed polarity. So we reset to idle */
04074             if (option_debug)
04075                ast_log(LOG_DEBUG, "Setting IDLE polarity due "
04076                   "to ring. Old polarity was %d\n", 
04077                   p->polarity);
04078             p->polarity = POLARITY_IDLE;
04079 
04080             /* Fall through */
04081          case SIG_EM:
04082          case SIG_EM_E1:
04083          case SIG_EMWINK:
04084          case SIG_FEATD:
04085          case SIG_FEATDMF:
04086          case SIG_FEATDMF_TA:
04087          case SIG_E911:
04088          case SIG_FGC_CAMA:
04089          case SIG_FGC_CAMAMF:
04090          case SIG_FEATB:
04091          case SIG_SF:
04092          case SIG_SFWINK:
04093          case SIG_SF_FEATD:
04094          case SIG_SF_FEATDMF:
04095          case SIG_SF_FEATB:
04096             if (ast->_state == AST_STATE_PRERING)
04097                ast_setstate(ast, AST_STATE_RING);
04098             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04099                if (option_debug)
04100                   ast_log(LOG_DEBUG, "Ring detected\n");
04101                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04102                p->subs[index].f.subclass = AST_CONTROL_RING;
04103             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04104                if (option_debug)
04105                   ast_log(LOG_DEBUG, "Line answered\n");
04106                if (p->confirmanswer) {
04107                   p->subs[index].f.frametype = AST_FRAME_NULL;
04108                   p->subs[index].f.subclass = 0;
04109                } else {
04110                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
04111                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04112                   ast_setstate(ast, AST_STATE_UP);
04113                }
04114             } else if (ast->_state != AST_STATE_RING)
04115                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04116             break;
04117          default:
04118             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04119          }
04120          break;
04121 #ifdef ZT_EVENT_RINGBEGIN
04122       case ZT_EVENT_RINGBEGIN:
04123          switch (p->sig) {
04124          case SIG_FXSLS:
04125          case SIG_FXSGS:
04126          case SIG_FXSKS:
04127             if (ast->_state == AST_STATE_RING) {
04128                p->ringt = p->ringt_base;
04129             }
04130             break;
04131          }
04132          break;
04133 #endif         
04134       case ZT_EVENT_RINGEROFF:
04135          if (p->inalarm) break;
04136          if ((p->radio || (p->oprmode < 0))) break;
04137          ast->rings++;
04138          if ((ast->rings > p->cidrings) && (p->cidspill)) {
04139             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
04140             free(p->cidspill);
04141             p->cidspill = NULL;
04142             p->callwaitcas = 0;
04143          }
04144          p->subs[index].f.frametype = AST_FRAME_CONTROL;
04145          p->subs[index].f.subclass = AST_CONTROL_RINGING;
04146          break;
04147       case ZT_EVENT_RINGERON:
04148          break;
04149       case ZT_EVENT_NOALARM:
04150          p->inalarm = 0;
04151 #ifdef HAVE_PRI
04152          /* Extremely unlikely but just in case */
04153          if (p->bearer)
04154             p->bearer->inalarm = 0;
04155 #endif            
04156          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04157          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04158                         "Channel: %d\r\n", p->channel);
04159          break;
04160       case ZT_EVENT_WINKFLASH:
04161          if (p->inalarm) break;
04162          if (p->radio) break;
04163          if (p->oprmode < 0) break;
04164          if (p->oprmode > 1)
04165          {
04166             struct zt_params par;
04167 
04168             if (ioctl(p->oprpeer->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par) != -1)
04169             {
04170                if (!par.rxisoffhook)
04171                {
04172                   /* Make sure it stops ringing */
04173                   zt_set_hook(p->oprpeer->subs[SUB_REAL].zfd, ZT_RINGOFF);
04174                   zt_set_hook(p->oprpeer->subs[SUB_REAL].zfd, ZT_RING);
04175                   save_conference(p);
04176                   tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
04177                }
04178             }
04179             break;
04180          }
04181          /* Remember last time we got a flash-hook */
04182          gettimeofday(&p->flashtime, NULL);
04183          switch (mysig) {
04184          case SIG_FXOLS:
04185          case SIG_FXOGS:
04186          case SIG_FXOKS:
04187             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04188                index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
04189             p->callwaitcas = 0;
04190 
04191             if (index != SUB_REAL) {
04192                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04193                goto winkflashdone;
04194             }
04195             
04196             if (p->subs[SUB_CALLWAIT].owner) {
04197                /* Swap to call-wait */
04198                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04199                tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
04200                p->owner = p->subs[SUB_REAL].owner;
04201                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04202                if (p->owner->_state == AST_STATE_RINGING) {
04203                   ast_setstate(p->owner, AST_STATE_UP);
04204                   p->subs[SUB_REAL].needanswer = 1;
04205                }
04206                p->callwaitingrepeat = 0;
04207                p->cidcwexpire = 0;
04208                /* Start music on hold if appropriate */
04209                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04210                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04211                      S_OR(p->mohsuggest, NULL),
04212                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04213                }
04214                p->subs[SUB_CALLWAIT].needhold = 1;
04215                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04216                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04217                      S_OR(p->mohsuggest, NULL),
04218                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04219                }
04220                p->subs[SUB_REAL].needunhold = 1;
04221             } else if (!p->subs[SUB_THREEWAY].owner) {
04222                char cid_num[256];
04223                char cid_name[256];
04224 
04225                if (!p->threewaycalling) {
04226                   /* Just send a flash if no 3-way calling */
04227                   p->subs[SUB_REAL].needflash = 1;
04228                   goto winkflashdone;
04229                } else if (!check_for_conference(p)) {
04230                   if (p->zaptrcallerid && p->owner) {
04231                      if (p->owner->cid.cid_num)
04232                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04233                      if (p->owner->cid.cid_name)
04234                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04235                   }
04236                   /* XXX This section needs much more error checking!!! XXX */
04237                   /* Start a 3-way call if feasible */
04238                   if (!((ast->pbx) ||
04239                         (ast->_state == AST_STATE_UP) ||
04240                         (ast->_state == AST_STATE_RING))) {
04241                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04242                         goto winkflashdone;
04243                   }
04244                   if (alloc_sub(p, SUB_THREEWAY)) {
04245                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04246                      goto winkflashdone;
04247                   }
04248                   /* Make new channel */
04249                   chan = zt_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04250                   if (p->zaptrcallerid) {
04251                      if (!p->origcid_num)
04252                         p->origcid_num = ast_strdup(p->cid_num);
04253                      if (!p->origcid_name)
04254                         p->origcid_name = ast_strdup(p->cid_name);
04255                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04256                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04257                   }
04258                   /* Swap things around between the three-way and real call */
04259                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
04260                   /* Disable echo canceller for better dialing */
04261                   zt_disable_ec(p);
04262                   res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_DIALRECALL);
04263                   if (res)
04264                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04265                   p->owner = chan;
04266                   pthread_attr_init(&attr);
04267                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04268                   if (!chan) {
04269                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04270                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04271                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04272                      res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
04273                      zt_enable_ec(p);
04274                      ast_hangup(chan);
04275                   } else {
04276                      if (option_verbose > 2) 
04277                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04278                      /* Start music on hold if appropriate */
04279                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04280                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04281                            S_OR(p->mohsuggest, NULL),
04282                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04283                      }
04284                      p->subs[SUB_THREEWAY].needhold = 1;
04285                   }
04286                   pthread_attr_destroy(&attr);
04287                }
04288             } else {
04289                /* Already have a 3 way call */
04290                if (p->subs[SUB_THREEWAY].inthreeway) {
04291                   /* Call is already up, drop the last person */
04292                   if (option_debug)
04293                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04294                   /* If the primary call isn't answered yet, use it */
04295                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04296                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
04297                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04298                      p->owner = p->subs[SUB_REAL].owner;
04299                   }
04300                   /* Drop the last call and stop the conference */
04301                   if (option_verbose > 2)
04302                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04303                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04304                   p->subs[SUB_REAL].inthreeway = 0;
04305                   p->subs[SUB_THREEWAY].inthreeway = 0;
04306                } else {
04307                   /* Lets see what we're up to */
04308                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
04309                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04310                      int otherindex = SUB_THREEWAY;
04311 
04312                      if (option_verbose > 2)
04313                         ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
04314                      /* Put them in the threeway, and flip */
04315                      p->subs[SUB_THREEWAY].inthreeway = 1;
04316                      p->subs[SUB_REAL].inthreeway = 1;
04317                      if (ast->_state == AST_STATE_UP) {
04318                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
04319                         otherindex = SUB_REAL;
04320                      }
04321                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04322                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04323                      p->subs[otherindex].needunhold = 1;
04324                      p->owner = p->subs[SUB_REAL].owner;
04325                      if (ast->_state == AST_STATE_RINGING) {
04326                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04327                         res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
04328                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, ZT_TONE_RINGTONE);
04329                      }
04330                   } else {
04331                      if (option_verbose > 2)
04332                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04333                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04334                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04335                      p->owner = p->subs[SUB_REAL].owner;
04336                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04337                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04338                      p->subs[SUB_REAL].needunhold = 1;
04339                      zt_enable_ec(p);
04340                   }
04341                      
04342                }
04343             }
04344          winkflashdone:              
04345             update_conf(p);
04346             break;
04347          case SIG_EM:
04348          case SIG_EM_E1:
04349          case SIG_EMWINK:
04350          case SIG_FEATD:
04351          case SIG_SF:
04352          case SIG_SFWINK:
04353          case SIG_SF_FEATD:
04354          case SIG_FXSLS:
04355          case SIG_FXSGS:
04356             if (p->dialing)
04357                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04358             else
04359                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04360             break;
04361          case SIG_FEATDMF_TA:
04362             switch (p->whichwink) {
04363             case 0:
04364                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04365                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04366                break;
04367             case 1:
04368                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04369                break;
04370             case 2:
04371                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04372                return NULL;
04373             }
04374             p->whichwink++;
04375             /* Fall through */
04376          case SIG_FEATDMF:
04377          case SIG_E911:
04378          case SIG_FGC_CAMAMF:
04379          case SIG_FGC_CAMA:
04380          case SIG_FEATB:
04381          case SIG_SF_FEATDMF:
04382          case SIG_SF_FEATB:
04383             /* FGD MF *Must* wait for wink */
04384             if (!ast_strlen_zero(p->dop.dialstr))
04385                res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop);
04386             else if (res < 0) {
04387                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
04388                p->dop.dialstr[0] = '\0';
04389                return NULL;
04390             } else 
04391                ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04392             p->dop.dialstr[0] = '\0';
04393             break;
04394          default:
04395             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04396          }
04397          break;
04398       case ZT_EVENT_HOOKCOMPLETE:
04399          if (p->inalarm) break;
04400          if ((p->radio || (p->oprmode < 0))) break;
04401          switch (mysig) {
04402          case SIG_FXSLS:  /* only interesting for FXS */
04403          case SIG_FXSGS:
04404          case SIG_FXSKS:
04405          case SIG_EM:
04406          case SIG_EM_E1:
04407          case SIG_EMWINK:
04408          case SIG_FEATD:
04409          case SIG_SF:
04410          case SIG_SFWINK:
04411          case SIG_SF_FEATD:
04412             if (!ast_strlen_zero(p->dop.dialstr)) 
04413                res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop);
04414             else if (res < 0) {
04415                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
04416                p->dop.dialstr[0] = '\0';
04417                return NULL;
04418             } else 
04419                ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04420             p->dop.dialstr[0] = '\0';
04421             p->dop.op = ZT_DIAL_OP_REPLACE;
04422             break;
04423          case SIG_FEATDMF:
04424          case SIG_FEATDMF_TA:
04425          case SIG_E911:
04426          case SIG_FGC_CAMA:
04427          case SIG_FGC_CAMAMF:
04428          case SIG_FEATB:
04429          case SIG_SF_FEATDMF:
04430          case SIG_SF_FEATB:
04431             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04432             break;
04433          default:
04434             break;
04435          }
04436          break;
04437       case ZT_EVENT_POLARITY:
04438          /*
04439           * If we get a Polarity Switch event, check to see
04440           * if we should change the polarity state and
04441           * mark the channel as UP or if this is an indication
04442           * of remote end disconnect.
04443           */
04444          if (p->polarity == POLARITY_IDLE) {
04445             p->polarity = POLARITY_REV;
04446             if (p->answeronpolarityswitch &&
04447                 ((ast->_state == AST_STATE_DIALING) ||
04448                 (ast->_state == AST_STATE_RINGING))) {
04449                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04450                ast_setstate(p->owner, AST_STATE_UP);
04451                if (p->hanguponpolarityswitch) {
04452                   gettimeofday(&p->polaritydelaytv, NULL);
04453                }
04454             } else
04455                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04456          } 
04457          /* Removed else statement from here as it was preventing hangups from ever happening*/
04458          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
04459          if (p->hanguponpolarityswitch &&
04460             (p->polarityonanswerdelay > 0) &&
04461                 (p->polarity == POLARITY_REV) &&
04462             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04463                                 /* Added log_debug information below to provide a better indication of what is going on */
04464             ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
04465          
04466             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04467                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04468                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04469                p->polarity = POLARITY_IDLE;
04470             } else {
04471                ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
04472             }
04473          } else {
04474             p->polarity = POLARITY_IDLE;
04475             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04476          }
04477                         /* Added more log_debug information below to provide a better indication of what is going on */
04478          ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
04479          break;
04480       default:
04481          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04482    }
04483    return &p->subs[index].f;
04484 }

static int zt_hangup ( struct ast_channel ast  )  [static]

Definition at line 2404 of file chan_zap.c.

References ast_channel::_state, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_dsp_digitmode(), ast_dsp_free(), ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verbose(), zt_pvt::callwaitcas, zt_pvt::callwaiting, zt_pvt::callwaitingrepeat, zt_pvt::channel, zt_pvt::cid_name, zt_pvt::cid_num, zt_pvt::cidcwexpire, zt_pvt::cidrings, zt_pvt::cidspill, zt_pvt::confirmanswer, zt_pvt::destroy, destroy_channel(), zt_pvt::dialing, zt_pvt::didtdd, zt_pvt::digital, zt_pvt::distinctivering, zt_pvt::dsp, DSP_DIGITMODE_DTMF, zt_pvt::dtmfrelax, zt_pvt::exten, zt_pvt::faxhandled, free, zt_pvt::guardtime, ast_channel::hangupcause, zt_pvt::hidecallerid, iflist, zt_pvt::ignoredtmf, zt_subchannel::inthreeway, zt_subchannel::linear, zt_pvt::lock, LOG_DEBUG, LOG_WARNING, zt_pvt::mohsuggest, zt_subchannel::needanswer, zt_subchannel::needbusy, zt_subchannel::needcallerid, zt_subchannel::needcongestion, zt_subchannel::needflash, zt_subchannel::needringing, zt_pvt::next, zt_pvt::onhooktime, zt_pvt::oprmode, option_debug, option_verbose, zt_pvt::origcid_name, zt_pvt::origcid_num, zt_pvt::outgoing, zt_pvt::owner, zt_subchannel::owner, pbx_builtin_getvar_helper(), zt_pvt::permcallwaiting, zt_pvt::permhidecallerid, zt_pvt::polarity, POLARITY_IDLE, zt_pvt::prev, zt_pvt::pulsedial, zt_pvt::radio, zt_pvt::rdnis, reset_conf(), restart_monitor(), restore_gains(), zt_pvt::ringt, S_OR, zt_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, zt_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), VERBOSE_PREFIX_3, zt_subchannel::zfd, zt_confmute(), zt_disable_ec(), zt_get_index(), zt_set_hook(), and zt_setlinear().

02405 {
02406    int res;
02407    int index,x, law;
02408    /*static int restore_gains(struct zt_pvt *p);*/
02409    struct zt_pvt *p = ast->tech_pvt;
02410    struct zt_pvt *tmp = NULL;
02411    struct zt_pvt *prev = NULL;
02412    ZT_PARAMS par;
02413 
02414    if (option_debug)
02415       ast_log(LOG_DEBUG, "zt_hangup(%s)\n", ast->name);
02416    if (!ast->tech_pvt) {
02417       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02418       return 0;
02419    }
02420    
02421    ast_mutex_lock(&p->lock);
02422    
02423    index = zt_get_index(ast, p, 1);
02424 
02425    if (p->sig == SIG_PRI) {
02426       x = 1;
02427       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02428    }
02429 
02430    x = 0;
02431    zt_confmute(p, 0);
02432    restore_gains(p);
02433    if (p->origcid_num) {
02434       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02435       free(p->origcid_num);
02436       p->origcid_num = NULL;
02437    }  
02438    if (p->origcid_name) {
02439       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02440       free(p->origcid_name);
02441       p->origcid_name = NULL;
02442    }  
02443    if (p->dsp)
02444       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02445    if (p->exten)
02446       p->exten[0] = '\0';
02447 
02448    if (option_debug)
02449       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02450       p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
02451    p->ignoredtmf = 0;
02452    
02453    if (index > -1) {
02454       /* Real channel, do some fixup */
02455       p->subs[index].owner = NULL;
02456       p->subs[index].needanswer = 0;
02457       p->subs[index].needflash = 0;
02458       p->subs[index].needringing = 0;
02459       p->subs[index].needbusy = 0;
02460       p->subs[index].needcongestion = 0;
02461       p->subs[index].linear = 0;
02462       p->subs[index].needcallerid = 0;
02463       p->polarity = POLARITY_IDLE;
02464       zt_setlinear(p->subs[index].zfd, 0);
02465       if (index == SUB_REAL) {
02466          if ((p->subs[SUB_CALLWAIT].zfd > -1) && (p->subs[SUB_THREEWAY].zfd > -1)) {
02467             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02468             if (p->subs[SUB_CALLWAIT].inthreeway) {
02469                /* We had flipped over to answer a callwait and now it's gone */
02470                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02471                /* Move to the call-wait, but un-own us until they flip back. */
02472                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02473                unalloc_sub(p, SUB_CALLWAIT);
02474                p->owner = NULL;
02475             } else {
02476                /* The three way hung up, but we still have a call wait */
02477                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
02478                swap_subs(p, SUB_THREEWAY, SUB_REAL);
02479                unalloc_sub(p, SUB_THREEWAY);
02480                if (p->subs[SUB_REAL].inthreeway) {
02481                   /* This was part of a three way call.  Immediately make way for
02482                      another call */
02483                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02484                   p->owner = p->subs[SUB_REAL].owner;
02485                } else {
02486                   /* This call hasn't been completed yet...  Set owner to NULL */
02487                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02488                   p->owner = NULL;
02489                }
02490                p->subs[SUB_REAL].inthreeway = 0;
02491             }
02492          } else if (p->subs[SUB_CALLWAIT].zfd > -1) {
02493             /* Move to the call-wait and switch back to them. */
02494             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02495             unalloc_sub(p, SUB_CALLWAIT);
02496             p->owner = p->subs[SUB_REAL].owner;
02497             if (p->owner->_state != AST_STATE_UP)
02498                p->subs[SUB_REAL].needanswer = 1;
02499             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02500                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02501          } else if (p->subs[SUB_THREEWAY].zfd > -1) {
02502             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02503             unalloc_sub(p, SUB_THREEWAY);
02504             if (p->subs[SUB_REAL].inthreeway) {
02505                /* This was part of a three way call.  Immediately make way for
02506                   another call */
02507                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02508                p->owner = p->subs[SUB_REAL].owner;
02509             } else {
02510                /* This call hasn't been completed yet...  Set owner to NULL */
02511                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02512                p->owner = NULL;
02513             }
02514             p->subs[SUB_REAL].inthreeway = 0;
02515          }
02516       } else if (index == SUB_CALLWAIT) {
02517          /* Ditch the holding callwait call, and immediately make it availabe */
02518          if (p->subs[SUB_CALLWAIT].inthreeway) {
02519             /* This is actually part of a three way, placed on hold.  Place the third part
02520                on music on hold now */
02521             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02522                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
02523                   S_OR(p->mohsuggest, NULL),
02524                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02525             }
02526             p->subs[SUB_THREEWAY].inthreeway = 0;
02527             /* Make it the call wait now */
02528             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02529             unalloc_sub(p, SUB_THREEWAY);
02530          } else
02531             unalloc_sub(p, SUB_CALLWAIT);
02532       } else if (index == SUB_THREEWAY) {
02533          if (p->subs[SUB_CALLWAIT].inthreeway) {
02534             /* The other party of the three way call is currently in a call-wait state.
02535                Start music on hold for them, and take the main guy out of the third call */
02536             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02537                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
02538                   S_OR(p->mohsuggest, NULL),
02539                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02540             }
02541             p->subs[SUB_CALLWAIT].inthreeway = 0;
02542          }
02543          p->subs[SUB_REAL].inthreeway = 0;
02544          /* If this was part of a three way call index, let us make
02545             another three way call */
02546          unalloc_sub(p, SUB_THREEWAY);
02547       } else {
02548          /* This wasn't any sort of call, but how are we an index? */
02549          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02550       }
02551    }
02552 
02553    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02554       p->owner = NULL;
02555       p->ringt = 0;
02556       p->distinctivering = 0;
02557       p->confirmanswer = 0;
02558       p->cidrings = 1;
02559       p->outgoing = 0;
02560       p->digital = 0;
02561       p->faxhandled = 0;
02562       p->pulsedial = 0;
02563       p->onhooktime = time(NULL);
02564 #ifdef HAVE_PRI
02565       p->proceeding = 0;
02566       p->progress = 0;
02567       p->alerting = 0;
02568       p->setup_ack = 0;
02569 #endif      
02570       if (p->dsp) {
02571          ast_dsp_free(p->dsp);
02572          p->dsp = NULL;
02573       }
02574 
02575       law = ZT_LAW_DEFAULT;
02576       res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETLAW, &law);
02577       if (res < 0) 
02578          ast_log(LOG_WARNING, "Unable to set law on channel %d to default\n", p->channel);
02579       /* Perform low level hangup if no owner left */
02580 #ifdef HAVE_PRI
02581       if (p->pri) {
02582 #ifdef SUPPORT_USERUSER
02583          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02584 #endif
02585 
02586          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
02587          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02588             if (!pri_grab(p, p->pri)) {
02589                if (p->alreadyhungup) {
02590                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
02591 
02592 #ifdef SUPPORT_USERUSER
02593                   pri_call_set_useruser(p->call, useruser);
02594 #endif
02595 
02596                   pri_hangup(p->pri->pri, p->call, -1);
02597                   p->call = NULL;
02598                   if (p->bearer) 
02599                      p->bearer->call = NULL;
02600                } else {
02601                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
02602                   int icause = ast->hangupcause ? ast->hangupcause : -1;
02603                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
02604 
02605 #ifdef SUPPORT_USERUSER
02606                   pri_call_set_useruser(p->call, useruser);
02607 #endif
02608 
02609                   p->alreadyhungup = 1;
02610                   if (p->bearer)
02611                      p->bearer->alreadyhungup = 1;
02612                   if (cause) {
02613                      if (atoi(cause))
02614                         icause = atoi(cause);
02615                   }
02616                   pri_hangup(p->pri->pri, p->call, icause);
02617                }
02618                if (res < 0) 
02619                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
02620                pri_rel(p->pri);        
02621             } else {
02622                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02623                res = -1;
02624             }
02625          } else {
02626             if (p->bearer)
02627                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02628             p->call = NULL;
02629             res = 0;
02630          }
02631       }
02632 #endif
02633       if (p->sig && (p->sig != SIG_PRI))
02634          res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
02635       if (res < 0) {
02636          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02637       }
02638       switch (p->sig) {
02639       case SIG_FXOGS:
02640       case SIG_FXOLS:
02641       case SIG_FXOKS:
02642          res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
02643          if (!res) {
02644 #if 0
02645             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02646 #endif
02647             /* If they're off hook, try playing congestion */
02648             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02649                tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
02650             else
02651                tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
02652          }
02653          break;
02654       case SIG_FXSGS:
02655       case SIG_FXSLS:
02656       case SIG_FXSKS:
02657          /* Make sure we're not made available for at least two seconds assuming
02658             we were actually used for an inbound or outbound call. */
02659          if (ast->_state != AST_STATE_RESERVED) {
02660             time(&p->guardtime);
02661             p->guardtime += 2;
02662          }
02663          break;
02664       default:
02665          tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
02666       }
02667       if (p->cidspill)
02668          free(p->cidspill);
02669       if (p->sig)
02670          zt_disable_ec(p);
02671       x = 0;
02672       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02673       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02674       p->didtdd = 0;
02675       p->cidspill = NULL;
02676       p->callwaitcas = 0;
02677       p->callwaiting = p->permcallwaiting;
02678       p->hidecallerid = p->permhidecallerid;
02679       p->dialing = 0;
02680       p->rdnis[0] = '\0';
02681       update_conf(p);
02682       reset_conf(p);
02683       /* Restore data mode */
02684       if (p->sig == SIG_PRI) {
02685          x = 0;
02686          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02687       }
02688 #ifdef HAVE_PRI
02689       if (p->bearer) {
02690          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02691          /* Free up the bearer channel as well, and
02692             don't use its file descriptor anymore */
02693          update_conf(p->bearer);
02694          reset_conf(p->bearer);
02695          p->bearer->owner = NULL;
02696          p->bearer->realcall = NULL;
02697          p->bearer = NULL;
02698          p->subs[SUB_REAL].zfd = -1;
02699          p->pri = NULL;
02700       }
02701 #endif
02702       restart_monitor();
02703    }
02704 
02705    p->callwaitingrepeat = 0;
02706    p->cidcwexpire = 0;
02707    p->oprmode = 0;
02708    ast->tech_pvt = NULL;
02709    ast_mutex_unlock(&p->lock);
02710    ast_module_unref(ast_module_info->self);
02711    if (option_verbose > 2) 
02712       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02713 
02714    ast_mutex_lock(&iflock);
02715    tmp = iflist;
02716    prev = NULL;
02717    if (p->destroy) {
02718       while (tmp) {
02719          if (tmp == p) {
02720             destroy_channel(prev, tmp, 0);
02721             break;
02722          } else {
02723             prev = tmp;
02724             tmp = tmp->next;
02725          }
02726       }
02727    }
02728    ast_mutex_unlock(&iflock);
02729    return 0;
02730 }

static int zt_indicate ( struct ast_channel chan,
int  condition,
const void *  data,
size_t  datalen 
) [static]

Definition at line 5001 of file chan_zap.c.

References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, zt_pvt::digital, zt_pvt::dop, func, ast_channel::hangupcause, ISTRUNK, zt_pvt::lock, LOG_DEBUG, LOG_WARNING, zt_pvt::mohinterpret, option_debug, zt_pvt::outgoing, zt_pvt::priindication_oob, zt_pvt::radio, zt_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, zt_pvt::span, SUB_REAL, zt_pvt::subs, ast_channel::tech_pvt, zt_subchannel::zfd, zt_get_index(), and zt_set_hook().

Referenced by zt_fixup().

05002 {
05003    struct zt_pvt *p = chan->tech_pvt;
05004    int res=-1;
05005    int index;
05006    int func = ZT_FLASH;
05007    ast_mutex_lock(&p->lock);
05008    index = zt_get_index(chan, p, 0);
05009    if (option_debug)
05010       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05011    if (index == SUB_REAL) {
05012       switch (condition) {
05013       case AST_CONTROL_BUSY:
05014 #ifdef HAVE_PRI
05015          if (p->priindication_oob && p->sig == SIG_PRI) {
05016             chan->hangupcause = AST_CAUSE_USER_BUSY;
05017             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05018             res = 0;
05019          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05020             if (p->pri->pri) {      
05021                if (!pri_grab(p, p->pri)) {
05022                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05023                   pri_rel(p->pri);
05024                }
05025                else
05026                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05027             }
05028             p->progress = 1;
05029             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_BUSY);
05030          } else
05031 #endif
05032             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_BUSY);
05033          break;
05034       case AST_CONTROL_RINGING:
05035 #ifdef HAVE_PRI
05036          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05037             if (p->pri->pri) {      
05038                if (!pri_grab(p, p->pri)) {
05039                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05040                   pri_rel(p->pri);
05041                }
05042                else
05043                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05044             }
05045             p->alerting = 1;
05046          }
05047 #endif
05048          res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_RINGTONE);
05049          if (chan->_state != AST_STATE_UP) {
05050             if ((chan->_state != AST_STATE_RING) ||
05051                ((p->sig != SIG_FXSKS) &&
05052                 (p->sig != SIG_FXSLS) &&
05053                 (p->sig != SIG_FXSGS)))
05054                ast_setstate(chan, AST_STATE_RINGING);
05055          }
05056          break;
05057       case AST_CONTROL_PROCEEDING:
05058          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05059 #ifdef HAVE_PRI
05060          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05061             if (p->pri->pri) {      
05062                if (!pri_grab(p, p->pri)) {
05063                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05064                   pri_rel(p->pri);
05065                }
05066                else
05067                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05068             }
05069             p->proceeding = 1;
05070          }
05071 #endif
05072          /* don't continue in ast_indicate */
05073          res = 0;
05074          break;
05075       case AST_CONTROL_PROGRESS:
05076          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05077 #ifdef HAVE_PRI
05078          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
05079          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05080             if (p->pri->pri) {      
05081                if (!pri_grab(p, p->pri)) {
05082                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05083                   pri_rel(p->pri);
05084                }
05085                else
05086                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05087             }
05088             p->progress = 1;
05089          }
05090 #endif
05091          /* don't continue in ast_indicate */
05092          res = 0;
05093          break;
05094       case AST_CONTROL_CONGESTION:
05095          chan->hangupcause = AST_CAUSE_CONGESTION;
05096 #ifdef HAVE_PRI
05097          if (p->priindication_oob && p->sig == SIG_PRI) {
05098             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05099             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05100             res = 0;
05101          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05102             if (p->pri) {     
05103                if (!pri_grab(p, p->pri)) {
05104                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05105                   pri_rel(p->pri);
05106                } else
05107                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05108             }
05109             p->progress = 1;
05110             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05111          } else
05112 #endif
05113             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05114          break;
05115       case AST_CONTROL_HOLD:
05116 #ifdef HAVE_PRI
05117          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05118             if (!pri_grab(p, p->pri)) {
05119                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05120                pri_rel(p->pri);
05121             } else
05122                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05123          } else
05124 #endif
05125             ast_moh_start(chan, data, p->mohinterpret);
05126          break;
05127       case AST_CONTROL_UNHOLD:
05128 #ifdef HAVE_PRI
05129          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05130             if (!pri_grab(p, p->pri)) {
05131                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05132                pri_rel(p->pri);
05133             } else
05134                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05135          } else
05136 #endif
05137             ast_moh_stop(chan);
05138          break;
05139       case AST_CONTROL_RADIO_KEY:
05140          if (p->radio) 
05141              res =  zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
05142          res = 0;
05143          break;
05144       case AST_CONTROL_RADIO_UNKEY:
05145          if (p->radio)
05146              res =  zt_set_hook(p->subs[index].zfd, ZT_RINGOFF);
05147          res = 0;
05148          break;
05149       case AST_CONTROL_FLASH:
05150          /* flash hookswitch */
05151          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05152             /* Clear out the dial buffer */
05153             p->dop.dialstr[0] = '\0';
05154             if ((ioctl(p->subs[SUB_REAL].zfd,ZT_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05155                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
05156                   chan->name, strerror(errno));
05157             } else
05158                res = 0;
05159          } else
05160             res = 0;
05161          break;
05162       case -1:
05163          res = tone_zone_play_tone(p->subs[index].zfd, -1);
05164          break;
05165       }
05166    } else
05167       res = 0;
05168    ast_mutex_unlock(&p->lock);
05169    return res;
05170 }

static void zt_link ( struct zt_pvt slave,
struct zt_pvt master 
) [static]

Definition at line 3079 of file chan_zap.c.

References ast_log(), zt_pvt::channel, LOG_DEBUG, LOG_WARNING, zt_pvt::master, MAX_SLAVES, and zt_pvt::slaves.

Referenced by zt_bridge().

03079                                                                  {
03080    int x;
03081    if (!slave || !master) {
03082       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03083       return;
03084    }
03085    for (x = 0; x < MAX_SLAVES; x++) {
03086       if (!master->slaves[x]) {
03087          master->slaves[x] = slave;
03088          break;
03089       }
03090    }
03091    if (x >= MAX_SLAVES) {
03092       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03093       master->slaves[MAX_SLAVES - 1] = slave;
03094    }
03095    if (slave->master) 
03096       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03097    slave->master = master;
03098    
03099    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03100 }

static struct ast_channel * zt_new ( struct zt_pvt i,
int  state,
int  startpbx,
int  index,
int  law,
int  transfercapability 
) [static, read]

> b2 can be freed now, it's been copied into the channel structure

Definition at line 5172 of file chan_zap.c.

References accountcode, zt_pvt::accountcode, zt_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, zt_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), zt_pvt::busy_quietlength, zt_pvt::busy_tonelength, zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::call_forward, zt_pvt::callgroup, ast_channel::callgroup, zt_pvt::callingpres, zt_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, zt_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, zt_pvt::cid_name, ast_callerid::cid_num, zt_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, zt_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, zt_pvt::context, zt_pvt::digital, zt_pvt::dnid, zt_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, zt_pvt::dsp_features, DSP_PROGRESS_TALK, zt_pvt::dtmfrelax, ast_channel::exten, zt_pvt::exten, zt_pvt::fake_event, ast_channel::fds, free, global_jbconf, zt_pvt::hardwaredtmf, language, zt_pvt::language, zt_subchannel::linear, LOG_DEBUG, LOG_WARNING, ast_channel::nativeformats, NEED_MFDETECT, zt_pvt::outgoing, zt_pvt::owner, zt_subchannel::owner, pbx_builtin_setvar_helper(), zt_pvt::pickupgroup, ast_channel::pickupgroup, PRI_TRANS_CAP_DIGITAL, ast_channel::rawreadformat, ast_channel::rawwriteformat, zt_pvt::rdnis, ast_channel::readformat, ast_channel::rings, zt_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, SUB_REAL, zt_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, ast_channel::writeformat, zt_subchannel::zfd, zt_confmute(), and zt_setlinear().

Referenced by handle_init_event(), zt_handle_event(), and zt_request().

05173 {
05174    struct ast_channel *tmp;
05175    int deflaw;
05176    int res;
05177    int x,y;
05178    int features;
05179    char *b2 = NULL;
05180    ZT_PARAMS ps;
05181    if (i->subs[index].owner) {
05182       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05183       return NULL;
05184    }
05185    y = 1;
05186    do {
05187       if (b2)
05188          free(b2);
05189 #ifdef HAVE_PRI
05190       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05191          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05192       else
05193 #endif
05194       if (i->channel == CHAN_PSEUDO)
05195          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05196       else  
05197          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05198       for (x = 0; x < 3; x++) {
05199          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name))
05200             break;
05201       }
05202       y++;
05203    } while (x < 3);
05204    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "Zap/%s", b2);
05205    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
05206       free(b2);
05207    if (!tmp)
05208       return NULL;
05209    tmp->tech = &zap_tech;
05210    ps.channo = i->channel;
05211    res = ioctl(i->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps);
05212    if (res) {
05213       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW\n");
05214       ps.curlaw = ZT_LAW_MULAW;
05215    }
05216    if (ps.curlaw == ZT_LAW_ALAW)
05217       deflaw = AST_FORMAT_ALAW;
05218    else
05219       deflaw = AST_FORMAT_ULAW;
05220    if (law) {
05221       if (law == ZT_LAW_ALAW)
05222          deflaw = AST_FORMAT_ALAW;
05223       else
05224          deflaw = AST_FORMAT_ULAW;
05225    }
05226    tmp->fds[0] = i->subs[index].zfd;
05227    tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05228    /* Start out assuming ulaw since it's smaller :) */
05229    tmp->rawreadformat = deflaw;
05230    tmp->readformat = deflaw;
05231    tmp->rawwriteformat = deflaw;
05232    tmp->writeformat = deflaw;
05233    i->subs[index].linear = 0;
05234    zt_setlinear(i->subs[index].zfd, i->subs[index].linear);
05235    features = 0;
05236    if (index == SUB_REAL) {
05237       if (i->busydetect && CANBUSYDETECT(i))
05238          features |= DSP_FEATURE_BUSY_DETECT;
05239       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05240          features |= DSP_FEATURE_CALL_PROGRESS;
05241       if ((!i->outgoing && (i->callprogress & 4)) || 
05242           (i->outgoing && (i->callprogress & 2))) {
05243          features |= DSP_FEATURE_FAX_DETECT;
05244       }
05245 #ifdef ZT_TONEDETECT
05246       x = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
05247       if (ioctl(i->subs[index].zfd, ZT_TONEDETECT, &x)) {
05248 #endif      
05249          i->hardwaredtmf = 0;
05250          features |= DSP_FEATURE_DTMF_DETECT;
05251 #ifdef ZT_TONEDETECT
05252       } else if (NEED_MFDETECT(i)) {
05253          i->hardwaredtmf = 1;
05254          features |= DSP_FEATURE_DTMF_DETECT;
05255       }
05256 #endif
05257    }
05258    if (features) {
05259       if (i->dsp) {
05260          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05261       } else {
05262          if (i->channel != CHAN_PSEUDO)
05263             i->dsp = ast_dsp_new();
05264          else
05265             i->dsp = NULL;
05266          if (i->dsp) {
05267             i->dsp_features = features & ~DSP_PROGRESS_TALK;
05268 #ifdef HAVE_PRI
05269             /* We cannot do progress detection until receives PROGRESS message */
05270             if (i->outgoing && (i->sig == SIG_PRI)) {
05271                /* Remember requested DSP features, don't treat
05272                   talking as ANSWER */
05273                features = 0;
05274             }
05275 #endif
05276             ast_dsp_set_features(i->dsp, features);
05277             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05278             if (!ast_strlen_zero(progzone))
05279                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05280             if (i->busydetect && CANBUSYDETECT(i)) {
05281                ast_dsp_set_busy_count(i->dsp, i->busycount);
05282                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
05283             }
05284          }
05285       }
05286    }
05287       
05288    if (state == AST_STATE_RING)
05289       tmp->rings = 1;
05290    tmp->tech_pvt = i;
05291    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05292       /* Only FXO signalled stuff can be picked up */
05293       tmp->callgroup = i->callgroup;
05294       tmp->pickupgroup = i->pickupgroup;
05295    }
05296    if (!ast_strlen_zero(i->language))
05297       ast_string_field_set(tmp, language, i->language);
05298    if (!i->owner)
05299       i->owner = tmp;
05300    if (!ast_strlen_zero(i->accountcode))
05301       ast_string_field_set(tmp, accountcode, i->accountcode);
05302    if (i->amaflags)
05303       tmp->amaflags = i->amaflags;
05304    i->subs[index].owner = tmp;
05305    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05306    ast_string_field_set(tmp, call_forward, i->call_forward);
05307    /* If we've been told "no ADSI" then enforce it */
05308    if (!i->adsi)
05309       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05310    if (!ast_strlen_zero(i->exten))
05311       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05312    if (!ast_strlen_zero(i->rdnis))
05313       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05314    if (!ast_strlen_zero(i->dnid))
05315       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05316 
05317    /* Don't use ast_set_callerid() here because it will
05318     * generate a needless NewCallerID event */
05319 #ifdef PRI_ANI
05320    tmp->cid.cid_num = ast_strdup(i->cid_num);
05321    tmp->cid.cid_name = ast_strdup(i->cid_name);
05322    if (!ast_strlen_zero(i->cid_ani))
05323       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05324    else  
05325       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05326 #else
05327    tmp->cid.cid_num = ast_strdup(i->cid_num);
05328    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05329    tmp->cid.cid_name = ast_strdup(i->cid_name);
05330 #endif
05331    tmp->cid.cid_pres = i->callingpres;
05332    tmp->cid.cid_ton = i->cid_ton;
05333 #ifdef HAVE_PRI
05334    tmp->transfercapability = transfercapability;
05335    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05336    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05337       i->digital = 1;
05338    /* Assume calls are not idle calls unless we're told differently */
05339    i->isidlecall = 0;
05340    i->alreadyhungup = 0;
05341 #endif
05342    /* clear the fake event in case we posted one before we had ast_channel */
05343    i->fake_event = 0;
05344    /* Assure there is no confmute on this channel */
05345    zt_confmute(i, 0);
05346    /* Configure the new channel jb */
05347    ast_jb_configure(tmp, &global_jbconf);
05348    if (startpbx) {
05349       if (ast_pbx_start(tmp)) {
05350          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05351          ast_hangup(tmp);
05352          i->owner = NULL;
05353          return NULL;
05354       }
05355    }
05356 
05357    ast_module_ref(ast_module_info->self);
05358    
05359    return tmp;
05360 }

static int zt_open ( char *  fn  )  [static]

Definition at line 871 of file chan_zap.c.

References ast_log(), LOG_WARNING, and READ_SIZE.

Referenced by alloc_sub(), chandup(), and mkintf().

00872 {
00873    int fd;
00874    int isnum;
00875    int chan = 0;
00876    int bs;
00877    int x;
00878    isnum = 1;
00879    for (x = 0; x < strlen(fn); x++) {
00880       if (!isdigit(fn[x])) {
00881          isnum = 0;
00882          break;
00883       }
00884    }
00885    if (isnum) {
00886       chan = atoi(fn);
00887       if (chan < 1) {
00888          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
00889          return -1;
00890       }
00891       fn = "/dev/zap/channel";
00892    }
00893    fd = open(fn, O_RDWR | O_NONBLOCK);
00894    if (fd < 0) {
00895       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
00896       return -1;
00897    }
00898    if (chan) {
00899       if (ioctl(fd, ZT_SPECIFY, &chan)) {
00900          x = errno;
00901          close(fd);
00902          errno = x;
00903          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
00904          return -1;
00905       }
00906    }
00907    bs = READ_SIZE;
00908    if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) return -1;
00909    return fd;
00910 }

static struct ast_frame * zt_read ( struct ast_channel ast  )  [static, read]

Definition at line 4603 of file chan_zap.c.

References __zt_exception(), ast_channel::_state, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_dsp_process(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_verbose(), zt_subchannel::buffer, zt_pvt::busydetect, zt_pvt::callprogress, zt_pvt::callwaitcas, zt_pvt::callwaitingrepeat, zt_pvt::callwaitrings, zt_pvt::channel, CHECK_BLOCKING, zt_pvt::cidcwexpire, zt_pvt::cidrings, zt_pvt::cidspill, ast_frame::data, ast_frame::datalen, ast_frame::delivery, zt_pvt::dialing, zt_pvt::dsp, zt_subchannel::f, zt_pvt::fake_event, zt_pvt::firstradio, ast_frame::frametype, zt_pvt::ignoredtmf, zt_pvt::inalarm, zt_subchannel::inthreeway, zt_pvt::lastcid_name, zt_pvt::lastcid_num, zt_subchannel::linear, zt_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, zt_subchannel::needanswer, zt_subchannel::needbusy, zt_subchannel::needcallerid, zt_subchannel::needcongestion, zt_subchannel::needflash, zt_subchannel::needhold, zt_subchannel::needringing, zt_subchannel::needunhold, ast_frame::offset, zt_pvt::oprmode, option_verbose, zt_pvt::outgoing, zt_pvt::overlapdial, zt_pvt::owner, zt_pvt::pulsedial, zt_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), ast_channel::rings, zt_pvt::ringt, S_OR, ast_frame::samples, send_callerid(), zt_pvt::sig, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, zt_pvt::subs, zt_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, VERBOSE_PREFIX_3, zt_subchannel::zfd, zt_callwait(), zt_get_index(), zt_handle_dtmfup(), and zt_setlinear().

04604 {
04605    struct zt_pvt *p = ast->tech_pvt;
04606    int res;
04607    int index;
04608    void *readbuf;
04609    struct ast_frame *f;
04610    
04611 
04612    ast_mutex_lock(&p->lock);
04613    
04614    index = zt_get_index(ast, p, 0);
04615    
04616    /* Hang up if we don't really exist */
04617    if (index < 0) {
04618       ast_log(LOG_WARNING, "We dont exist?\n");
04619       ast_mutex_unlock(&p->lock);
04620       return NULL;
04621    }
04622    
04623    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
04624 
04625    p->subs[index].f.frametype = AST_FRAME_NULL;
04626    p->subs[index].f.datalen = 0;
04627    p->subs[index].f.samples = 0;
04628    p->subs[index].f.mallocd = 0;
04629    p->subs[index].f.offset = 0;
04630    p->subs[index].f.subclass = 0;
04631    p->subs[index].f.delivery = ast_tv(0,0);
04632    p->subs[index].f.src = "zt_read";
04633    p->subs[index].f.data = NULL;
04634    
04635    /* make sure it sends initial key state as first frame */
04636    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
04637    {
04638       ZT_PARAMS ps;
04639 
04640       ps.channo = p->channel;
04641       if (ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
04642          ast_mutex_unlock(&p->lock);
04643          return NULL;
04644       }
04645       p->firstradio = 1;
04646       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04647       if (ps.rxisoffhook)
04648       {
04649          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04650       }
04651       else
04652       {
04653          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04654       }
04655       ast_mutex_unlock(&p->lock);
04656       return &p->subs[index].f;
04657    }
04658    if (p->ringt == 1) {
04659       ast_mutex_unlock(&p->lock);
04660       return NULL;
04661    }
04662    else if (p->ringt > 0) 
04663       p->ringt--;
04664 
04665    if (p->subs[index].needringing) {
04666       /* Send ringing frame if requested */
04667       p->subs[index].needringing = 0;
04668       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04669       p->subs[index].f.subclass = AST_CONTROL_RINGING;
04670       ast_setstate(ast, AST_STATE_RINGING);
04671       ast_mutex_unlock(&p->lock);
04672       return &p->subs[index].f;
04673    }
04674 
04675    if (p->subs[index].needbusy) {
04676       /* Send busy frame if requested */
04677       p->subs[index].needbusy = 0;
04678       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04679       p->subs[index].f.subclass = AST_CONTROL_BUSY;
04680       ast_mutex_unlock(&p->lock);
04681       return &p->subs[index].f;
04682    }
04683 
04684    if (p->subs[index].needcongestion) {
04685       /* Send congestion frame if requested */
04686       p->subs[index].needcongestion = 0;
04687       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04688       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
04689       ast_mutex_unlock(&p->lock);
04690       return &p->subs[index].f;
04691    }
04692 
04693    if (p->subs[index].needcallerid) {
04694       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
04695                      S_OR(p->lastcid_name, NULL),
04696                      S_OR(p->lastcid_num, NULL)
04697                      );
04698       p->subs[index].needcallerid = 0;
04699    }
04700    
04701    if (p->subs[index].needanswer) {
04702       /* Send answer frame if requested */
04703       p->subs[index].needanswer = 0;
04704       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04705       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04706       ast_mutex_unlock(&p->lock);
04707       return &p->subs[index].f;
04708    }  
04709    
04710    if (p->subs[index].needflash) {
04711       /* Send answer frame if requested */
04712       p->subs[index].needflash = 0;
04713       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04714       p->subs[index].f.subclass = AST_CONTROL_FLASH;
04715       ast_mutex_unlock(&p->lock);
04716       return &p->subs[index].f;
04717    }  
04718    
04719    if (p->subs[index].needhold) {
04720       /* Send answer frame if requested */
04721       p->subs[index].needhold = 0;
04722       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04723       p->subs[index].f.subclass = AST_CONTROL_HOLD;
04724       ast_mutex_unlock(&p->lock);
04725       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
04726       return &p->subs[index].f;
04727    }  
04728    
04729    if (p->subs[index].needunhold) {
04730       /* Send answer frame if requested */
04731       p->subs[index].needunhold = 0;
04732       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04733       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
04734       ast_mutex_unlock(&p->lock);
04735       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
04736       return &p->subs[index].f;
04737    }  
04738    
04739    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
04740       if (!p->subs[index].linear) {
04741          p->subs[index].linear = 1;
04742          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
04743          if (res) 
04744             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
04745       }
04746    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
04747          (ast->rawreadformat == AST_FORMAT_ALAW)) {
04748       if (p->subs[index].linear) {
04749          p->subs[index].linear = 0;
04750          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
04751          if (res) 
04752             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
04753       }
04754    } else {
04755       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
04756       ast_mutex_unlock(&p->lock);
04757       return NULL;
04758    }
04759    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
04760    CHECK_BLOCKING(ast);
04761    res = read(p->subs[index].zfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04762    ast_clear_flag(ast, AST_FLAG_BLOCKING);
04763    /* Check for hangup */
04764    if (res < 0) {
04765       f = NULL;
04766       if (res == -1)  {
04767          if (errno == EAGAIN) {
04768             /* Return "NULL" frame if there is nobody there */
04769             ast_mutex_unlock(&p->lock);
04770             return &p->subs[index].f;
04771          } else if (errno == ELAST) {
04772             f = __zt_exception(ast);
04773          } else
04774             ast_log(LOG_WARNING, "zt_rec: %s\n", strerror(errno));
04775       }
04776       ast_mutex_unlock(&p->lock);
04777       return f;
04778    }
04779    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
04780       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04781       f = __zt_exception(ast);
04782       ast_mutex_unlock(&p->lock);
04783       return f;
04784    }
04785    if (p->tdd) { /* if in TDD mode, see if we receive that */
04786       int c;
04787 
04788       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
04789       if (c < 0) {
04790          ast_log(LOG_DEBUG,"tdd_feed failed\n");
04791          ast_mutex_unlock(&p->lock);
04792          return NULL;
04793       }
04794       if (c) { /* if a char to return */
04795          p->subs[index].f.subclass = 0;
04796          p->subs[index].f.frametype = AST_FRAME_TEXT;
04797          p->subs[index].f.mallocd = 0;
04798          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04799          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
04800          p->subs[index].f.datalen = 1;
04801          *((char *) p->subs[index].f.data) = c;
04802          ast_mutex_unlock(&p->lock);
04803          return &p->subs[index].f;
04804       }
04805    }
04806    if (p->callwaitingrepeat)
04807       p->callwaitingrepeat--;
04808    if (p->cidcwexpire)
04809       p->cidcwexpire--;
04810    /* Repeat callwaiting */
04811    if (p->callwaitingrepeat == 1) {
04812       p->callwaitrings++;
04813       zt_callwait(ast);
04814    }
04815    /* Expire CID/CW */
04816    if (p->cidcwexpire == 1) {
04817       if (option_verbose > 2)
04818          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
04819       restore_conference(p);
04820    }
04821    if (p->subs[index].linear) {
04822       p->subs[index].f.datalen = READ_SIZE * 2;
04823    } else 
04824       p->subs[index].f.datalen = READ_SIZE;
04825 
04826    /* Handle CallerID Transmission */
04827    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
04828       send_callerid(p);
04829    }
04830 
04831    p->subs[index].f.frametype = AST_FRAME_VOICE;
04832    p->subs[index].f.subclass = ast->rawreadformat;
04833    p->subs[index].f.samples = READ_SIZE;
04834    p->subs[index].f.mallocd = 0;
04835    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04836    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
04837 #if 0
04838    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
04839 #endif   
04840    if (p->dialing || /* Transmitting something */
04841       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
04842       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
04843       ) {
04844       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
04845          don't send anything */
04846       p->subs[index].f.frametype = AST_FRAME_NULL;
04847       p->subs[index].f.subclass = 0;
04848       p->subs[index].f.samples = 0;
04849       p->subs[index].f.mallocd = 0;
04850       p->subs[index].f.offset = 0;
04851       p->subs[index].f.data = NULL;
04852       p->subs[index].f.datalen= 0;
04853    }
04854    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
04855       /* Perform busy detection. etc on the zap line */
04856       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
04857       if (f) {
04858          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
04859             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
04860                /* Treat this as a "hangup" instead of a "busy" on the assumption that
04861                   a busy  */
04862                f = NULL;
04863             }
04864          } else if (f->frametype == AST_FRAME_DTMF) {
04865 #ifdef HAVE_PRI
04866             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
04867                /* Don't accept in-band DTMF when in overlap dial mode */
04868                f->frametype = AST_FRAME_NULL;
04869                f->subclass = 0;
04870             }
04871 #endif            
04872             /* DSP clears us of being pulse */
04873             p->pulsedial = 0;
04874          }
04875       }
04876    } else 
04877       f = &p->subs[index].f; 
04878 
04879    if (f && (f->frametype == AST_FRAME_DTMF))
04880       zt_handle_dtmfup(ast, index, &f);
04881 
04882    /* If we have a fake_event, trigger exception to handle it */
04883    if (p->fake_event)
04884       ast_set_flag(ast, AST_FLAG_EXCEPTION);
04885 
04886    ast_mutex_unlock(&p->lock);
04887    return f;
04888 }

static struct ast_channel * zt_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static, read]

Definition at line 7717 of file chan_zap.c.

References alloc_sub(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, ast_verbose(), available(), busy, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), zt_pvt::channel, zt_pvt::confirmanswer, zt_pvt::digital, zt_pvt::distinctivering, iflist, zt_pvt::inalarm, lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, zt_pvt::next, option_debug, zt_pvt::outgoing, zt_pvt::owner, zt_pvt::prev, restart_monitor(), s, zt_pvt::sig, SIG_FXSKS, strsep(), SUB_CALLWAIT, SUB_REAL, zt_pvt::subs, ast_channel::transfercapability, zt_subchannel::zfd, and zt_new().

07718 {
07719    int groupmatch = 0;
07720    int channelmatch = -1;
07721    int roundrobin = 0;
07722    int callwait = 0;
07723    int busy = 0;
07724    struct zt_pvt *p;
07725    struct ast_channel *tmp = NULL;
07726    char *dest=NULL;
07727    int x;
07728    char *s;
07729    char opt=0;
07730    int res=0, y=0;
07731    int backwards = 0;
07732 #ifdef HAVE_PRI
07733    int crv;
07734    int bearer = -1;
07735    int trunkgroup;
07736    struct zt_pri *pri=NULL;
07737 #endif   
07738    struct zt_pvt *exit, *start, *end;
07739    ast_mutex_t *lock;
07740    int channelmatched = 0;
07741    int groupmatched = 0;
07742    
07743    /* Assume we're locking the iflock */
07744    lock = &iflock;
07745    start = iflist;
07746    end = ifend;
07747    if (data) {
07748       dest = ast_strdupa((char *)data);
07749    } else {
07750       ast_log(LOG_WARNING, "Channel requested with no data\n");
07751       return NULL;
07752    }
07753    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
07754       /* Retrieve the group number */
07755       char *stringp=NULL;
07756       stringp=dest + 1;
07757       s = strsep(&stringp, "/");
07758       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
07759          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
07760          return NULL;
07761       }
07762       groupmatch = 1 << x;
07763       if (toupper(dest[0]) == 'G') {
07764          if (dest[0] == 'G') {
07765             backwards = 1;
07766             p = ifend;
07767          } else
07768             p = iflist;
07769       } else {
07770          if (dest[0] == 'R') {
07771             backwards = 1;
07772             p = round_robin[x]?round_robin[x]->prev:ifend;
07773             if (!p)
07774                p = ifend;
07775          } else {
07776             p = round_robin[x]?round_robin[x]->next:iflist;
07777             if (!p)
07778                p = iflist;
07779          }
07780          roundrobin = 1;
07781       }
07782    } else {
07783       char *stringp=NULL;
07784       stringp=dest;
07785       s = strsep(&stringp, "/");
07786       p = iflist;
07787       if (!strcasecmp(s, "pseudo")) {
07788          /* Special case for pseudo */
07789          x = CHAN_PSEUDO;
07790          channelmatch = x;
07791       } 
07792 #ifdef HAVE_PRI
07793       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
07794          if ((trunkgroup < 1) || (crv < 1)) {
07795             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
07796             return NULL;
07797          }
07798          res--;
07799          for (x = 0; x < NUM_SPANS; x++) {
07800             if (pris[x].trunkgroup == trunkgroup) {
07801                pri = pris + x;
07802                lock = &pri->lock;
07803                start = pri->crvs;
07804                end = pri->crvend;
07805                break;
07806             }
07807          }
07808          if (!pri) {
07809             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
07810             return NULL;
07811          }
07812          channelmatch = crv;
07813          p = pris[x].crvs;
07814       }
07815 #endif   
07816       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
07817          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
07818          return NULL;
07819       } else {
07820          channelmatch = x;
07821       }
07822    }
07823    /* Search for an unowned channel */
07824    ast_mutex_lock(lock);
07825    exit = p;
07826    while (p && !tmp) {
07827       if (roundrobin)
07828          round_robin[x] = p;
07829 #if 0
07830       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
07831 #endif
07832 
07833       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
07834          if (option_debug)
07835             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
07836             if (p->inalarm) 
07837                goto next;
07838 
07839          callwait = (p->owner != NULL);
07840 #ifdef HAVE_PRI
07841          if (pri && (p->subs[SUB_REAL].zfd < 0)) {
07842             if (p->sig != SIG_FXSKS) {
07843                /* Gotta find an actual channel to use for this
07844                   CRV if this isn't a callwait */
07845                bearer = pri_find_empty_chan(pri, 0);
07846                if (bearer < 0) {
07847                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
07848                   p = NULL;
07849                   break;
07850                }
07851                pri_assign_bearer(p, pri, pri->pvts[bearer]);
07852             } else {
07853                if (alloc_sub(p, 0)) {
07854                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
07855                   p = NULL;
07856                   break;
07857                } else
07858                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
07859                p->pri = pri;
07860             }
07861          }
07862 #endif         
07863          if (p->channel == CHAN_PSEUDO) {
07864             p = chandup(p);
07865             if (!p) {
07866                break;
07867             }
07868          }
07869          if (p->owner) {
07870             if (alloc_sub(p, SUB_CALLWAIT)) {
07871                p = NULL;
07872                break;
07873             }
07874          }
07875          p->outgoing = 1;
07876          tmp = zt_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
07877 #ifdef HAVE_PRI
07878          if (p->bearer) {
07879             /* Log owner to bearer channel, too */
07880             p->bearer->owner = tmp;
07881          }
07882 #endif         
07883          /* Make special notes */
07884          if (res > 1) {
07885             if (opt == 'c') {
07886                /* Confirm answer */
07887                p->confirmanswer = 1;
07888             } else if (opt == 'r') {
07889                /* Distinctive ring */
07890                if (res < 3)
07891                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
07892                else
07893                   p->distinctivering = y;
07894             } else if (opt == 'd') {
07895                /* If this is an ISDN call, make it digital */
07896                p->digital = 1;
07897                if (tmp)
07898                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
07899             } else {
07900                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
07901             }
07902          }
07903          /* Note if the call is a call waiting call */
07904          if (tmp && callwait)
07905             tmp->cdrflags |= AST_CDR_CALLWAIT;
07906          break;
07907       }
07908 next:
07909       if (backwards) {
07910          p = p->prev;
07911          if (!p)
07912             p = end;
07913       } else {
07914          p = p->next;
07915          if (!p)
07916             p = start;
07917       }
07918       /* stop when you roll to the one that we started from */
07919       if (p == exit)
07920          break;
07921    }
07922    ast_mutex_unlock(lock);
07923    restart_monitor();
07924    if (callwait)
07925       *cause = AST_CAUSE_BUSY;
07926    else if (!tmp) {
07927       if (channelmatched) {
07928          if (busy)
07929             *cause = AST_CAUSE_BUSY;
07930       } else if (groupmatched) {
07931          *cause = AST_CAUSE_CONGESTION;
07932       }
07933    }
07934       
07935    return tmp;
07936 }

static int zt_ring_phone ( struct zt_pvt p  )  [static]

Definition at line 3449 of file chan_zap.c.

References ast_log(), LOG_WARNING, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by __zt_exception(), and zt_handle_event().

03450 {
03451    int x;
03452    int res;
03453    /* Make sure our transmit state is on hook */
03454    x = 0;
03455    x = ZT_ONHOOK;
03456    res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03457    do {
03458       x = ZT_RING;
03459       res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03460       if (res) {
03461          switch (errno) {
03462          case EBUSY:
03463          case EINTR:
03464             /* Wait just in case */
03465             usleep(10000);
03466             continue;
03467          case EINPROGRESS:
03468             res = 0;
03469             break;
03470          default:
03471             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03472             res = 0;
03473          }
03474       }
03475    } while (res);
03476    return res;
03477 }

static int zt_sendtext ( struct ast_channel c,
const char *  text 
) [static]

Definition at line 11328 of file chan_zap.c.

References ASCII_BYTES_PER_CHAR, ast_check_hangup(), AST_LAW, ast_log(), ast_malloc, zt_pvt::channel, END_SILENCE_LEN, pollfd::events, pollfd::fd, free, HEADER_LEN, HEADER_MS, LOG_DEBUG, LOG_ERROR, LOG_WARNING, zt_pvt::mate, option_debug, poll(), POLLOUT, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, pollfd::revents, zt_pvt::subs, zt_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, TRAILER_MS, zt_subchannel::zfd, and zt_get_index().

11329 {
11330 #define  END_SILENCE_LEN 400
11331 #define  HEADER_MS 50
11332 #define  TRAILER_MS 5
11333 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11334 #define  ASCII_BYTES_PER_CHAR 80
11335 
11336    unsigned char *buf,*mybuf;
11337    struct zt_pvt *p = c->tech_pvt;
11338    struct pollfd fds[1];
11339    int size,res,fd,len,x;
11340    int bytes=0;
11341    /* Initial carrier (imaginary) */
11342    float cr = 1.0;
11343    float ci = 0.0;
11344    float scont = 0.0;
11345    int index;
11346 
11347    index = zt_get_index(c, p, 0);
11348    if (index < 0) {
11349       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
11350       return -1;
11351    }
11352    if (!text[0]) return(0); /* if nothing to send, dont */
11353    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
11354    if (p->mate) 
11355       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11356    else
11357       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11358    if (!buf)
11359       return -1;
11360    mybuf = buf;
11361    if (p->mate) {
11362       int codec = AST_LAW(p);
11363       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
11364          PUT_CLID_MARKMS;
11365       }
11366       /* Put actual message */
11367       for (x = 0; text[x]; x++) {
11368          PUT_CLID(text[x]);
11369       }
11370       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
11371          PUT_CLID_MARKMS;
11372       }
11373       len = bytes;
11374       buf = mybuf;
11375    } else {
11376       len = tdd_generate(p->tdd, buf, text);
11377       if (len < 1) {
11378          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11379          free(mybuf);
11380          return -1;
11381       }
11382    }
11383    memset(buf + len, 0x7f, END_SILENCE_LEN);
11384    len += END_SILENCE_LEN;
11385    fd = p->subs[index].zfd;
11386    while (len) {
11387       if (ast_check_hangup(c)) {
11388          free(mybuf);
11389          return -1;
11390       }
11391       size = len;
11392       if (size > READ_SIZE)
11393          size = READ_SIZE;
11394       fds[0].fd = fd;
11395       fds[0].events = POLLOUT | POLLPRI;
11396       fds[0].revents = 0;
11397       res = poll(fds, 1, -1);
11398       if (!res) {
11399          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11400          continue;
11401       }
11402         /* if got exception */
11403       if (fds[0].revents & POLLPRI)
11404          return -1;
11405       if (!(fds[0].revents & POLLOUT)) {
11406          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11407          continue;
11408       }
11409       res = write(fd, buf, size);
11410       if (res != size) {
11411          if (res == -1) {
11412             free(mybuf);
11413             return -1;
11414          }
11415          if (option_debug)
11416             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11417          break;
11418       }
11419       len -= size;
11420       buf += size;
11421    }
11422    free(mybuf);
11423    return(0);
11424 }

static int zt_set_hook ( int  fd,
int  hs 
) [inline, static]

Definition at line 1608 of file chan_zap.c.

References ast_log(), and LOG_WARNING.

Referenced by __zt_exception(), handle_init_event(), mkintf(), ss_thread(), zt_answer(), zt_handle_event(), zt_hangup(), zt_indicate(), and zt_wink().

01609 {
01610    int x, res;
01611 
01612    x = hs;
01613    res = ioctl(fd, ZT_HOOK, &x);
01614 
01615    if (res < 0) {
01616       if (errno == EINPROGRESS)
01617          return 0;
01618       ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
01619    }
01620 
01621    return res;
01622 }

static int zt_setlinear ( int  zfd,
int  linear 
) [static]

Definition at line 918 of file chan_zap.c.

Referenced by send_callerid(), ss_thread(), zt_hangup(), zt_new(), zt_read(), and zt_write().

00919 {
00920    int res;
00921    res = ioctl(zfd, ZT_SETLINEAR, &linear);
00922    if (res)
00923       return res;
00924    return 0;
00925 }

static int zt_setoption ( struct ast_channel chan,
int  option,
void *  data,
int  datalen 
) [static]

Definition at line 2817 of file chan_zap.c.

References ast_check_hangup(), ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), zt_pvt::channel, zt_pvt::didtdd, zt_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, zt_pvt::dtmfrelax, pollfd::events, pollfd::fd, zt_pvt::law, len, LOG_DEBUG, LOG_WARNING, zt_pvt::mate, oprmode::mode, zt_pvt::oprmode, zt_pvt::oprpeer, option_debug, oprmode::peer, poll(), POLLOUT, POLLPRI, READ_SIZE, pollfd::revents, zt_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, zt_pvt::subs, zt_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, zt_pvt::txgain, zt_subchannel::zfd, zt_disable_ec(), zt_enable_ec(), and zt_get_index().

02818 {
02819    char *cp;
02820    signed char *scp;
02821    int x;
02822    int index;
02823    struct zt_pvt *p = chan->tech_pvt, *pp;
02824    struct oprmode *oprmode;
02825    
02826 
02827    /* all supported options require data */
02828    if (!data || (datalen < 1)) {
02829       errno = EINVAL;
02830       return -1;
02831    }
02832 
02833    switch (option) {
02834    case AST_OPTION_TXGAIN:
02835       scp = (signed char *) data;
02836       index = zt_get_index(chan, p, 0);
02837       if (index < 0) {
02838          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
02839          return -1;
02840       }
02841       if (option_debug)
02842          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
02843       return set_actual_txgain(p->subs[index].zfd, 0, p->txgain + (float) *scp, p->law);
02844    case AST_OPTION_RXGAIN:
02845       scp = (signed char *) data;
02846       index = zt_get_index(chan, p, 0);
02847       if (index < 0) {
02848          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
02849          return -1;
02850       }
02851       if (option_debug)
02852          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
02853       return set_actual_rxgain(p->subs[index].zfd, 0, p->rxgain + (float) *scp, p->law);
02854    case AST_OPTION_TONE_VERIFY:
02855       if (!p->dsp)
02856          break;
02857       cp = (char *) data;
02858       switch (*cp) {
02859       case 1:
02860          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
02861          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
02862          break;
02863       case 2:
02864          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
02865          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
02866          break;
02867       default:
02868          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
02869          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
02870          break;
02871       }
02872       break;
02873    case AST_OPTION_TDD:
02874       /* turn on or off TDD */
02875       cp = (char *) data;
02876       p->mate = 0;
02877       if (!*cp) { /* turn it off */
02878          if (option_debug)
02879             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
02880          if (p->tdd)
02881             tdd_free(p->tdd);
02882          p->tdd = 0;
02883          break;
02884       }
02885       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
02886          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
02887       zt_disable_ec(p);
02888       /* otherwise, turn it on */
02889       if (!p->didtdd) { /* if havent done it yet */
02890          unsigned char mybuf[41000], *buf;
02891          int size, res, fd, len;
02892          struct pollfd fds[1];
02893 
02894          buf = mybuf;
02895          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
02896          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
02897          len = 40000;
02898          index = zt_get_index(chan, p, 0);
02899          if (index < 0) {
02900             ast_log(LOG_WARNING, "No index in TDD?\n");
02901             return -1;
02902          }
02903          fd = p->subs[index].zfd;
02904          while (len) {
02905             if (ast_check_hangup(chan))
02906                return -1;
02907             size = len;
02908             if (size > READ_SIZE)
02909                size = READ_SIZE;
02910             fds[0].fd = fd;
02911             fds[0].events = POLLPRI | POLLOUT;
02912             fds[0].revents = 0;
02913             res = poll(fds, 1, -1);
02914             if (!res) {
02915                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
02916                continue;
02917             }
02918             /* if got exception */
02919             if (fds[0].revents & POLLPRI)
02920                return -1;
02921             if (!(fds[0].revents & POLLOUT)) {
02922                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
02923                continue;
02924             }
02925             res = write(fd, buf, size);
02926             if (res != size) {
02927                if (res == -1) return -1;
02928                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
02929                break;
02930             }
02931             len -= size;
02932             buf += size;
02933          }
02934          p->didtdd = 1; /* set to have done it now */    
02935       }
02936       if (*cp == 2) { /* Mate mode */
02937          if (p->tdd)
02938             tdd_free(p->tdd);
02939          p->tdd = 0;
02940          p->mate = 1;
02941          break;
02942       }     
02943       if (!p->tdd) { /* if we dont have one yet */
02944          p->tdd = tdd_new(); /* allocate one */
02945       }     
02946       break;
02947    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
02948       if (!p->dsp)
02949          break;
02950       cp = (char *) data;
02951       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
02952          *cp ? "ON" : "OFF", (int) *cp, chan->name);
02953                 p->dtmfrelax = 0;
02954                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
02955                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02956       break;
02957    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
02958       cp = (char *) data;
02959       if (!*cp) {    
02960          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
02961          x = 0;
02962          zt_disable_ec(p);
02963       } else {    
02964          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
02965          x = 1;
02966       }
02967       if (ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x) == -1)
02968          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", p->channel, x);
02969       break;
02970    case AST_OPTION_OPRMODE:  /* Operator services mode */
02971       oprmode = (struct oprmode *) data;
02972       pp = oprmode->peer->tech_pvt;
02973       p->oprmode = pp->oprmode = 0;
02974       /* setup peers */
02975       p->oprpeer = pp;
02976       pp->oprpeer = p;
02977       /* setup modes, if any */
02978       if (oprmode->mode) 
02979       {
02980          pp->oprmode = oprmode->mode;
02981          p->oprmode = -oprmode->mode;
02982       }
02983       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
02984          oprmode->mode, chan->name,oprmode->peer->name);;
02985       break;
02986    case AST_OPTION_ECHOCAN:
02987       cp = (char *) data;
02988       if (*cp) {
02989          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
02990          zt_enable_ec(p);
02991       } else {
02992          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
02993          zt_disable_ec(p);
02994       }
02995       break;
02996    }
02997    errno = 0;
02998 
02999    return 0;
03000 }

static void zt_train_ec ( struct zt_pvt p  )  [static]

Definition at line 1440 of file chan_zap.c.

References ast_log(), zt_pvt::channel, zt_pvt::echocancel, zt_pvt::echotraining, LOG_DEBUG, LOG_WARNING, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by zt_answer(), and zt_handle_event().

01441 {
01442    int x;
01443    int res;
01444    if (p && p->echocancel && p->echotraining) {
01445       x = p->echotraining;
01446       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
01447       if (res)
01448          ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
01449       else {
01450          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01451       }
01452    } else
01453       ast_log(LOG_DEBUG, "No echo training requested\n");
01454 }

static void zt_unlink ( struct zt_pvt slave,
struct zt_pvt master,
int  needlock 
) [static]

Definition at line 3021 of file chan_zap.c.

References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), zt_pvt::channel, conf_del(), zt_pvt::inconference, zt_pvt::lock, LOG_DEBUG, zt_pvt::master, MAX_SLAVES, zt_pvt::slaves, SUB_REAL, zt_pvt::subs, and update_conf().

Referenced by zt_bridge(), and zt_fixup().

03022 {
03023    /* Unlink a specific slave or all slaves/masters from a given master */
03024    int x;
03025    int hasslaves;
03026    if (!master)
03027       return;
03028    if (needlock) {
03029       ast_mutex_lock(&master->lock);
03030       if (slave) {
03031          while (ast_mutex_trylock(&slave->lock)) {
03032             ast_mutex_unlock(&master->lock);
03033             usleep(1);
03034             ast_mutex_lock(&master->lock);
03035          }
03036       }
03037    }
03038    hasslaves = 0;
03039    for (x = 0; x < MAX_SLAVES; x++) {
03040       if (master->slaves[x]) {
03041          if (!slave || (master->slaves[x] == slave)) {
03042             /* Take slave out of the conference */
03043             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03044             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03045             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03046             master->slaves[x]->master = NULL;
03047             master->slaves[x] = NULL;
03048          } else
03049             hasslaves = 1;
03050       }
03051       if (!hasslaves)
03052          master->inconference = 0;
03053    }
03054    if (!slave) {
03055       if (master->master) {
03056          /* Take master out of the conference */
03057          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03058          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03059          hasslaves = 0;
03060          for (x = 0; x < MAX_SLAVES; x++) {
03061             if (master->master->slaves[x] == master)
03062                master->master->slaves[x] = NULL;
03063             else if (master->master->slaves[x])
03064                hasslaves = 1;
03065          }
03066          if (!hasslaves)
03067             master->master->inconference = 0;
03068       }
03069       master->master = NULL;
03070    }
03071    update_conf(master);
03072    if (needlock) {
03073       if (slave)
03074          ast_mutex_unlock(&slave->lock);
03075       ast_mutex_unlock(&master->lock);
03076    }
03077 }

static int zt_wait_event ( int  fd  )  [inline, static]

Avoid the silly zt_waitevent which ignores a bunch of events.

Definition at line 265 of file chan_zap.c.

Referenced by flash_exec(), and ss_thread().

00266 {
00267    int i, j = 0;
00268    i = ZT_IOMUX_SIGEVENT;
00269    if (ioctl(fd, ZT_IOMUX, &i) == -1)
00270       return -1;
00271    if (ioctl(fd, ZT_GETEVENT, &j) == -1)
00272       return -1;
00273    return j;
00274 }

static int zt_wink ( struct zt_pvt p,
int  index 
) [static]

Definition at line 5382 of file chan_zap.c.

References zt_pvt::subs, zt_subchannel::zfd, and zt_set_hook().

Referenced by ss_thread().

05383 {
05384    int j;
05385    zt_set_hook(p->subs[index].zfd, ZT_WINK);
05386    for (;;)
05387    {
05388          /* set bits of interest */
05389       j = ZT_IOMUX_SIGEVENT;
05390           /* wait for some happening */
05391       if (ioctl(p->subs[index].zfd,ZT_IOMUX,&j) == -1) return(-1);
05392          /* exit loop if we have it */
05393       if (j & ZT_IOMUX_SIGEVENT) break;
05394    }
05395      /* get the event info */
05396    if (ioctl(p->subs[index].zfd,ZT_GETEVENT,&j) == -1) return(-1);
05397    return 0;
05398 }

static int zt_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]

Definition at line 4913 of file chan_zap.c.

References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), zt_pvt::channel, zt_pvt::cidspill, ast_frame::data, ast_frame::datalen, zt_pvt::dialing, zt_pvt::digital, ast_frame::frametype, zt_subchannel::linear, zt_pvt::lock, LOG_DEBUG, LOG_WARNING, my_zt_write(), option_debug, zt_pvt::outgoing, zt_pvt::owner, zt_pvt::sig, SIG_PRI, zt_pvt::span, ast_frame::subclass, zt_pvt::subs, ast_channel::tech_pvt, zt_subchannel::zfd, zt_get_index(), and zt_setlinear().

04914 {
04915    struct zt_pvt *p = ast->tech_pvt;
04916    int res;
04917    unsigned char outbuf[4096];
04918    int index;
04919    index = zt_get_index(ast, p, 0);
04920    if (index < 0) {
04921       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
04922       return -1;
04923    }
04924 
04925 #if 0
04926 #ifdef HAVE_PRI
04927    ast_mutex_lock(&p->lock);
04928    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
04929       if (p->pri->pri) {      
04930          if (!pri_grab(p, p->pri)) {
04931                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
04932                pri_rel(p->pri);
04933          } else
04934                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04935       }
04936       p->proceeding=1;
04937    }
04938    ast_mutex_unlock(&p->lock);
04939 #endif
04940 #endif
04941    /* Write a frame of (presumably voice) data */
04942    if (frame->frametype != AST_FRAME_VOICE) {
04943       if (frame->frametype != AST_FRAME_IMAGE)
04944          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
04945       return 0;
04946    }
04947    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
04948        (frame->subclass != AST_FORMAT_ULAW) &&
04949        (frame->subclass != AST_FORMAT_ALAW)) {
04950       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
04951       return -1;
04952    }
04953    if (p->dialing) {
04954       if (option_debug)
04955          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
04956       return 0;
04957    }
04958    if (!p->owner) {
04959       if (option_debug)
04960          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
04961       return 0;
04962    }
04963    if (p->cidspill) {
04964       if (option_debug)
04965          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
04966       return 0;
04967    }
04968    /* Return if it's not valid data */
04969    if (!frame->data || !frame->datalen)
04970       return 0;
04971    if (frame->datalen > sizeof(outbuf) * 2) {
04972       ast_log(LOG_WARNING, "Frame too large\n");
04973       return 0;
04974    }
04975 
04976    if (frame->subclass == AST_FORMAT_SLINEAR) {
04977       if (!p->subs[index].linear) {
04978          p->subs[index].linear = 1;
04979          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
04980          if (res)
04981             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
04982       }
04983       res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
04984    } else {
04985       /* x-law already */
04986       if (p->subs[index].linear) {
04987          p->subs[index].linear = 0;
04988          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
04989          if (res)
04990             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
04991       }
04992       res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
04993    }
04994    if (res < 0) {
04995       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
04996       return -1;
04997    } 
04998    return 0;
04999 }


Variable Documentation

int alarm

Definition at line 1118 of file chan_zap.c.

Referenced by action_zapshowchannels().

struct { ... } alarms[] [static]

Referenced by alarm2str(), and zap_show_status().

struct zt_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 739 of file chan_zap.c.

int cidrings[NUM_CADENCE_MAX] [static]

cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.

Definition at line 750 of file chan_zap.c.

const char config[] = "zapata.conf" [static]

Definition at line 165 of file chan_zap.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 109 of file chan_zap.c.

char defaultcic[64] = "" [static]

Definition at line 204 of file chan_zap.c.

char defaultozz[64] = "" [static]

Definition at line 205 of file chan_zap.c.

char destroy_channel_usage[] [static]

Initial value:

   "Usage: zap destroy channel <chan num>\n"
   "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n"

Definition at line 10088 of file chan_zap.c.

int distinctiveringaftercid = 0 [static]

Definition at line 209 of file chan_zap.c.

struct zt_distRings drings [static]

Definition at line 368 of file chan_zap.c.

Referenced by mkintf(), and process_zap().

char* events[] [static]

Definition at line 1095 of file chan_zap.c.

Referenced by authenticate().

int firstdigittimeout = 16000 [static]

Wait up to 16 seconds for first digit (FXO logic).

Definition at line 223 of file chan_zap.c.

int gendigittimeout = 8000 [static]

How long to wait for following digits (FXO logic).

Definition at line 226 of file chan_zap.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 116 of file chan_zap.c.

int ifcount = 0 [static]

Definition at line 235 of file chan_zap.c.

struct zt_pvt * ifend [static]

struct zt_pvt * iflist [static]

int matchdigittimeout = 3000 [static]

How long to wait for an extra digit, if there is an ambiguous match.

Definition at line 229 of file chan_zap.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

This is the thread for the monitor which checks for input on the channels which are not currently in use.

Definition at line 247 of file chan_zap.c.

char* name

Definition at line 1119 of file chan_zap.c.

int num_cadence = 4 [static]

Definition at line 736 of file chan_zap.c.

int numbufs = 4 [static]

Definition at line 211 of file chan_zap.c.

char progzone[10] = "" [static]

Definition at line 207 of file chan_zap.c.

int ringt_base = DEFAULT_RINGT [static]

Definition at line 290 of file chan_zap.c.

struct zt_pvt* round_robin[32]

Definition at line 713 of file chan_zap.c.

char show_channel_usage[] [static]

Initial value:

   "Usage: zap show channel <chan num>\n"
   "  Detailed information about a given channel\n"

Definition at line 10080 of file chan_zap.c.

char show_channels_usage[] [static]

Initial value:

   "Usage: zap show channels\n"
   "  Shows a list of available channels\n"

Definition at line 10076 of file chan_zap.c.

char* subnames[] [static]

Initial value:

 {
   "Real",
   "Callwait",
   "Threeway"
}

Definition at line 381 of file chan_zap.c.

const char tdesc[] = "Zapata Telephony Driver" [static]

Definition at line 159 of file chan_zap.c.

int user_has_defined_cadences = 0 [static]

Definition at line 737 of file chan_zap.c.

struct ast_cli_entry zap_cli[] [static]

Definition at line 10099 of file chan_zap.c.

char zap_restart_usage[] [static]

Definition at line 10092 of file chan_zap.c.

char zap_show_cadences_help[] [static]

Initial value:

"Usage: zap show cadences\n"
"       Shows all cadences currently defined\n"

Definition at line 9984 of file chan_zap.c.

char zap_show_status_usage[] [static]

Initial value:

   "Usage: zap show status\n"
   "       Shows a list of Zaptel cards with status\n"

Definition at line 10084 of file chan_zap.c.

struct ast_channel_tech zap_tech [static]

Definition at line 686 of file chan_zap.c.


Generated on Wed Aug 15 01:24:59 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.3