Mon Mar 31 07:39:44 2008

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, ast_group_t 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_channelzt_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_channelzt_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
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 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 761 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 762 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(), 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.

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 711 of file chan_zap.c.

#define HANGUP   1

Definition at line 10238 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 758 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 10593 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().

#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 736 of file chan_zap.c.

#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 1226 of file chan_zap.c.

Referenced by action_zapshowchannels(), build_channels(), handle_init_event(), mkintf(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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 11561 of file chan_zap.c.

Referenced by description(), and load_module().

#define TRAILER_MS   5

Referenced by zt_sendtext().

#define TRANSFER   0

Definition at line 10237 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 10419 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::channel, zt_pvt::cidspill, destroy_zt_pvt(), free, iflist, master, zt_pvt::next, zt_pvt::owner, SUB_REAL, zt_pvt::subs, VERBOSE_PREFIX_3, zap_cli, zap_tech, zt_subchannel::zfd, and zt_close().

10420 {
10421    int x;
10422    struct zt_pvt *p, *pl;
10423 
10424 #ifdef HAVE_PRI
10425    int i;
10426    for (i = 0; i < NUM_SPANS; i++) {
10427       if (pris[i].master != AST_PTHREADT_NULL) 
10428          pthread_cancel(pris[i].master);
10429    }
10430    ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
10431    ast_unregister_application(zap_send_keypad_facility_app);
10432 #endif
10433    ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
10434    ast_manager_unregister( "ZapDialOffhook" );
10435    ast_manager_unregister( "ZapHangup" );
10436    ast_manager_unregister( "ZapTransfer" );
10437    ast_manager_unregister( "ZapDNDoff" );
10438    ast_manager_unregister( "ZapDNDon" );
10439    ast_manager_unregister("ZapShowChannels");
10440    ast_manager_unregister("ZapRestart");
10441    ast_channel_unregister(&zap_tech);
10442    ast_mutex_lock(&iflock);
10443    /* Hangup all interfaces if they have an owner */
10444    p = iflist;
10445    while (p) {
10446       if (p->owner)
10447          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10448       p = p->next;
10449    }
10450    ast_mutex_unlock(&iflock);
10451    ast_mutex_lock(&monlock);
10452    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10453       pthread_cancel(monitor_thread);
10454       pthread_kill(monitor_thread, SIGURG);
10455       pthread_join(monitor_thread, NULL);
10456    }
10457    monitor_thread = AST_PTHREADT_STOP;
10458    ast_mutex_unlock(&monlock);
10459 
10460    ast_mutex_lock(&iflock);
10461    /* Destroy all the interfaces and free their memory */
10462    p = iflist;
10463    while (p) {
10464       /* Free any callerid */
10465       if (p->cidspill)
10466          free(p->cidspill);
10467       /* Close the zapata thingy */
10468       if (p->subs[SUB_REAL].zfd > -1)
10469          zt_close(p->subs[SUB_REAL].zfd);
10470       pl = p;
10471       p = p->next;
10472       x = pl->channel;
10473       /* Free associated memory */
10474       if (pl)
10475          destroy_zt_pvt(&pl);
10476       ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10477    }
10478    iflist = NULL;
10479    ifcount = 0;
10480    ast_mutex_unlock(&iflock);
10481 #ifdef HAVE_PRI      
10482    for (i = 0; i < NUM_SPANS; i++) {
10483       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10484          pthread_join(pris[i].master, NULL);
10485       zt_close(pris[i].fds[i]);
10486    }
10487 #endif
10488    return 0;
10489 }

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

Definition at line 4517 of file chan_zap.c.

References 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::channel, ast_frame::data, ast_frame::datalen, ast_frame::delivery, event2str(), zt_subchannel::f, f, zt_pvt::fake_event, ast_channel::fds, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, 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_enable_ec(), zt_get_event(), zt_get_index(), zt_handle_event(), zt_ring_phone(), and zt_set_hook().

Referenced by zt_exception(), and zt_read().

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

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

Definition at line 10306 of file chan_zap.c.

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

Referenced by load_module().

10307 {
10308    struct zt_pvt *p = NULL;
10309    const char *channel = astman_get_header(m, "ZapChannel");
10310 
10311    if (ast_strlen_zero(channel)) {
10312       astman_send_error(s, m, "No channel specified");
10313       return 0;
10314    }
10315    p = find_channel(atoi(channel));
10316    if (!p) {
10317       astman_send_error(s, m, "No such channel");
10318       return 0;
10319    }
10320    zap_fake_event(p,TRANSFER);
10321    astman_send_ack(s, m, "ZapTransfer");
10322    return 0;
10323 }

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

Definition at line 10325 of file chan_zap.c.

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

Referenced by load_module().

10326 {
10327    struct zt_pvt *p = NULL;
10328    const char *channel = astman_get_header(m, "ZapChannel");
10329 
10330    if (ast_strlen_zero(channel)) {
10331       astman_send_error(s, m, "No channel specified");
10332       return 0;
10333    }
10334    p = find_channel(atoi(channel));
10335    if (!p) {
10336       astman_send_error(s, m, "No such channel");
10337       return 0;
10338    }
10339    zap_fake_event(p,HANGUP);
10340    astman_send_ack(s, m, "ZapHangup");
10341    return 0;
10342 }

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

Definition at line 10344 of file chan_zap.c.

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

Referenced by load_module().

10345 {
10346    struct zt_pvt *p = NULL;
10347    const char *channel = astman_get_header(m, "ZapChannel");
10348    const char *number = astman_get_header(m, "Number");
10349    int i;
10350 
10351    if (ast_strlen_zero(channel)) {
10352       astman_send_error(s, m, "No channel specified");
10353       return 0;
10354    }
10355    if (ast_strlen_zero(number)) {
10356       astman_send_error(s, m, "No number specified");
10357       return 0;
10358    }
10359    p = find_channel(atoi(channel));
10360    if (!p) {
10361       astman_send_error(s, m, "No such channel");
10362       return 0;
10363    }
10364    if (!p->owner) {
10365       astman_send_error(s, m, "Channel does not have it's owner");
10366       return 0;
10367    }
10368    for (i = 0; i < strlen(number); i++) {
10369       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10370       zap_queue_frame(p, &f, NULL); 
10371    }
10372    astman_send_ack(s, m, "ZapDialOffhook");
10373    return 0;
10374 }

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

Definition at line 10287 of file chan_zap.c.

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

Referenced by load_module().

10288 {
10289    struct zt_pvt *p = NULL;
10290    const char *channel = astman_get_header(m, "ZapChannel");
10291 
10292    if (ast_strlen_zero(channel)) {
10293       astman_send_error(s, m, "No channel specified");
10294       return 0;
10295    }
10296    p = find_channel(atoi(channel));
10297    if (!p) {
10298       astman_send_error(s, m, "No such channel");
10299       return 0;
10300    }
10301    p->dnd = 0;
10302    astman_send_ack(s, m, "DND Disabled");
10303    return 0;
10304 }

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

Definition at line 10268 of file chan_zap.c.

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

Referenced by load_module().

10269 {
10270    struct zt_pvt *p = NULL;
10271    const char *channel = astman_get_header(m, "ZapChannel");
10272 
10273    if (ast_strlen_zero(channel)) {
10274       astman_send_error(s, m, "No channel specified");
10275       return 0;
10276    }
10277    p = find_channel(atoi(channel));
10278    if (!p) {
10279       astman_send_error(s, m, "No such channel");
10280       return 0;
10281    }
10282    p->dnd = 1;
10283    astman_send_ack(s, m, "DND Enabled");
10284    return 0;
10285 }

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

Definition at line 9895 of file chan_zap.c.

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

Referenced by load_module().

09896 {
09897    if (zap_restart() != 0) {
09898       astman_send_error(s, m, "Failed rereading zaptel configuration");
09899       return 1;
09900    }
09901    astman_send_ack(s, m, "ZapRestart: Success");
09902    return 0;
09903 }

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

Definition at line 10376 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, s, zt_pvt::sig, and sig2str.

Referenced by load_module().

10377 {
10378    struct zt_pvt *tmp = NULL;
10379    const char *id = astman_get_header(m, "ActionID");
10380    char idText[256] = "";
10381 
10382    astman_send_ack(s, m, "Zapata channel status will follow");
10383    if (!ast_strlen_zero(id))
10384       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10385 
10386    ast_mutex_lock(&iflock);
10387    
10388    tmp = iflist;
10389    while (tmp) {
10390       if (tmp->channel > 0) {
10391          int alarm = get_alarms(tmp);
10392          astman_append(s,
10393             "Event: ZapShowChannels\r\n"
10394             "Channel: %d\r\n"
10395             "Signalling: %s\r\n"
10396             "Context: %s\r\n"
10397             "DND: %s\r\n"
10398             "Alarm: %s\r\n"
10399             "%s"
10400             "\r\n",
10401             tmp->channel, sig2str(tmp->sig), tmp->context, 
10402             tmp->dnd ? "Enabled" : "Disabled",
10403             alarm2str(alarm), idText);
10404       } 
10405 
10406       tmp = tmp->next;
10407    }
10408 
10409    ast_mutex_unlock(&iflock);
10410    
10411    astman_append(s, 
10412       "Event: ZapShowChannelsComplete\r\n"
10413       "%s"
10414       "\r\n", 
10415       idText);
10416    return 0;
10417 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1137 of file chan_zap.c.

References alarms, and name.

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

01138 {
01139    int x;
01140    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01141       if (alarms[x].alarm & alarm)
01142          return alarms[x].name;
01143    }
01144    return alarm ? "Unknown Alarm" : "No Alarm";
01145 }

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

Definition at line 935 of file chan_zap.c.

References ast_log(), zt_subchannel::chan, zt_pvt::channel, errno, 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().

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

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 3500 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, zt_subchannel::owner, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, swap_subs(), unalloc_sub(), and zt_subchannel::zfd.

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

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

Definition at line 7613 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, 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().

07614 {
07615    int res;
07616    ZT_PARAMS par;
07617 
07618    /* First, check group matching */
07619    if (groupmatch) {
07620       if ((p->group & groupmatch) != groupmatch)
07621          return 0;
07622       *groupmatched = 1;
07623    }
07624    /* Check to see if we have a channel match */
07625    if (channelmatch != -1) {
07626       if (p->channel != channelmatch)
07627          return 0;
07628       *channelmatched = 1;
07629    }
07630    /* We're at least busy at this point */
07631    if (busy) {
07632       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07633          *busy = 1;
07634    }
07635    /* If do not disturb, definitely not */
07636    if (p->dnd)
07637       return 0;
07638    /* If guard time, definitely not */
07639    if (p->guardtime && (time(NULL) < p->guardtime)) 
07640       return 0;
07641       
07642    /* If no owner definitely available */
07643    if (!p->owner) {
07644 #ifdef HAVE_PRI
07645       /* Trust PRI */
07646       if (p->pri) {
07647          if (p->resetting || p->call)
07648             return 0;
07649          else
07650             return 1;
07651       }
07652 #endif
07653       if (!(p->radio || (p->oprmode < 0)))
07654       {
07655          if (!p->sig || (p->sig == SIG_FXSLS))
07656             return 1;
07657          /* Check hook state */
07658          if (p->subs[SUB_REAL].zfd > -1)
07659             res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
07660          else {
07661             /* Assume not off hook on CVRS */
07662             res = 0;
07663             par.rxisoffhook = 0;
07664          }
07665          if (res) {
07666             ast_log(LOG_WARNING, "Unable to check hook state on channel %d\n", p->channel);
07667          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07668             /* When "onhook" that means no battery on the line, and thus
07669               it is out of service..., if it's on a TDM card... If it's a channel
07670               bank, there is no telling... */
07671             if (par.rxbits > -1)
07672                return 1;
07673             if (par.rxisoffhook)
07674                return 1;
07675             else
07676 #ifdef ZAP_CHECK_HOOKSTATE
07677                return 0;
07678 #else
07679                return 1;
07680 #endif
07681          } else if (par.rxisoffhook) {
07682             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07683             /* Not available when the other end is off hook */
07684             return 0;
07685          }
07686       }
07687       return 1;
07688    }
07689 
07690    /* If it's not an FXO, forget about call wait */
07691    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
07692       return 0;
07693 
07694    if (!p->callwaiting) {
07695       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
07696       return 0;
07697    }
07698 
07699    if (p->subs[SUB_CALLWAIT].zfd > -1) {
07700       /* If there is already a call waiting call, then we can't take a second one */
07701       return 0;
07702    }
07703    
07704    if ((p->owner->_state != AST_STATE_UP) &&
07705        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07706       /* If the current call is not up, then don't allow the call */
07707       return 0;
07708    }
07709    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07710       /* Can't take a call wait when the three way calling hasn't been merged yet. */
07711       return 0;
07712    }
07713    /* We're cool */
07714    return 1;
07715 }

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 10501 of file chan_zap.c.

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

Referenced by process_zap().

10502 {
10503    char *c, *chan;
10504    int x, start, finish;
10505    struct zt_pvt *tmp;
10506 #ifdef HAVE_PRI
10507    struct zt_pri *pri;
10508    int trunkgroup, y;
10509 #endif
10510    
10511    if ((reload == 0) && (conf.chan.sig < 0)) {
10512       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10513       return -1;
10514    }
10515 
10516    c = ast_strdupa(value);
10517 
10518 #ifdef HAVE_PRI
10519    pri = NULL;
10520    if (iscrv) {
10521       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10522          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10523          return -1;
10524       }
10525       if (trunkgroup < 1) {
10526          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10527          return -1;
10528       }
10529       c += y;
10530       for (y = 0; y < NUM_SPANS; y++) {
10531          if (pris[y].trunkgroup == trunkgroup) {
10532             pri = pris + y;
10533             break;
10534          }
10535       }
10536       if (!pri) {
10537          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10538          return -1;
10539       }
10540    }
10541 #endif         
10542 
10543    while ((chan = strsep(&c, ","))) {
10544       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10545          /* Range */
10546       } else if (sscanf(chan, "%d", &start)) {
10547          /* Just one */
10548          finish = start;
10549       } else if (!strcasecmp(chan, "pseudo")) {
10550          finish = start = CHAN_PSEUDO;
10551          if (found_pseudo)
10552             *found_pseudo = 1;
10553       } else {
10554          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10555          return -1;
10556       }
10557       if (finish < start) {
10558          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10559          x = finish;
10560          finish = start;
10561          start = x;
10562       }
10563 
10564       for (x = start; x <= finish; x++) {
10565 #ifdef HAVE_PRI
10566          tmp = mkintf(x, conf, pri, reload);
10567 #else       
10568          tmp = mkintf(x, conf, NULL, reload);
10569 #endif         
10570 
10571          if (tmp) {
10572             if (option_verbose > 2) {
10573 #ifdef HAVE_PRI
10574                if (pri)
10575                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10576                else
10577 #endif
10578                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10579             }
10580          } else {
10581             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10582                (reload == 1) ? "reconfigure" : "register", value);
10583             return -1;
10584          }
10585       }
10586    }
10587 
10588    return 0;
10589 }

static int bump_gains ( struct zt_pvt p  )  [static]

Definition at line 1588 of file chan_zap.c.

References ast_log(), errno, 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().

01589 {
01590    int res;
01591 
01592    /* Bump receive gain by 5.0db */
01593    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01594    if (res) {
01595       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01596       return -1;
01597    }
01598 
01599    return 0;
01600 }

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

Definition at line 7717 of file chan_zap.c.

References ast_log(), ast_malloc, ast_mutex_init(), destroy_zt_pvt(), errno, iflist, LOG_ERROR, oh323_pvt::next, SUB_REAL, and zt_open().

Referenced by zt_request().

07718 {
07719    struct zt_pvt *p;
07720    ZT_BUFFERINFO bi;
07721    int res;
07722    
07723    if ((p = ast_malloc(sizeof(*p)))) {
07724       memcpy(p, src, sizeof(struct zt_pvt));
07725       ast_mutex_init(&p->lock);
07726       p->subs[SUB_REAL].zfd = zt_open("/dev/zap/pseudo");
07727       /* Allocate a zapata structure */
07728       if (p->subs[SUB_REAL].zfd < 0) {
07729          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
07730          destroy_zt_pvt(&p);
07731          return NULL;
07732       }
07733       res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
07734       if (!res) {
07735          bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
07736          bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
07737          bi.numbufs = numbufs;
07738          res = ioctl(p->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
07739          if (res < 0) {
07740             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel\n");
07741          }
07742       } else
07743          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel\n");
07744    }
07745    p->destroy = 1;
07746    p->next = iflist;
07747    p->prev = NULL;
07748    iflist = p;
07749    if (iflist->next)
07750       iflist->next->prev = p;
07751    return p;
07752 }

static int check_for_conference ( struct zt_pvt p  )  [static]

Definition at line 3576 of file chan_zap.c.

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

Referenced by zt_handle_event().

03577 {
03578    ZT_CONFINFO ci;
03579    /* Fine if we already have a master, etc */
03580    if (p->master || (p->confno > -1))
03581       return 0;
03582    memset(&ci, 0, sizeof(ci));
03583    if (ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
03584       ast_log(LOG_WARNING, "Failed to get conference info on channel %d\n", p->channel);
03585       return 0;
03586    }
03587    /* If we have no master and don't have a confno, then 
03588       if we're in a conference, it's probably a MeetMe room or
03589       some such, so don't let us 3-way out! */
03590    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03591       if (option_verbose > 2) 
03592          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03593       return 1;
03594    }
03595    return 0;
03596 }

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

Definition at line 1228 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().

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

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

Definition at line 1277 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().

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

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

Definition at line 2228 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().

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

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

Definition at line 2213 of file chan_zap.c.

References ast_mutex_destroy(), ast_smdi_interface_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().

02214 {
02215    struct zt_pvt *p = *pvt;
02216    /* Remove channel from the list */
02217    if (p->prev)
02218       p->prev->next = p->next;
02219    if (p->next)
02220       p->next->prev = p->prev;
02221    if (p->use_smdi)
02222       ast_smdi_interface_unref(p->smdi_iface);
02223    ast_mutex_destroy(&p->lock);
02224    free(p);
02225    *pvt = NULL;
02226 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 990 of file chan_zap.c.

Referenced by zt_digit_begin().

00991 {
00992    if (isdigit(digit))
00993       return ZT_TONE_DTMF_BASE + (digit - '0');
00994    else if (digit >= 'A' && digit <= 'D')
00995       return ZT_TONE_DTMF_A + (digit - 'A');
00996    else if (digit >= 'a' && digit <= 'd')
00997       return ZT_TONE_DTMF_A + (digit - 'a');
00998    else if (digit == '*')
00999       return ZT_TONE_DTMF_s;
01000    else if (digit == '#')
01001       return ZT_TONE_DTMF_p;
01002    else
01003       return -1;
01004 }

static void disable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3110 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().

03111 {
03112 #ifdef ZT_TONEDETECT
03113    int val;
03114 #endif
03115 
03116    p->ignoredtmf = 1;
03117 
03118 #ifdef ZT_TONEDETECT
03119    val = 0;
03120    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03121 #endif      
03122    if (!p->hardwaredtmf && p->dsp) {
03123       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03124       ast_dsp_set_features(p->dsp, p->dsp_features);
03125    }
03126 }

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

Definition at line 6820 of file chan_zap.c.

References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), zt_pvt::cidspill, pollfd::events, pollfd::fd, free, iflist, last, LOG_DEBUG, zt_pvt::next, zt_subchannel::owner, zt_pvt::owner, POLLIN, POLLPRI, zt_pvt::radio, pollfd::revents, zt_pvt::sig, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

06821 {
06822    int count, res, res2, spoint, pollres=0;
06823    struct zt_pvt *i;
06824    struct zt_pvt *last = NULL;
06825    time_t thispass = 0, lastpass = 0;
06826    int found;
06827    char buf[1024];
06828    struct pollfd *pfds=NULL;
06829    int lastalloc = -1;
06830    /* This thread monitors all the frame relay interfaces which are not yet in use
06831       (and thus do not have a separate thread) indefinitely */
06832    /* From here on out, we die whenever asked */
06833 #if 0
06834    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
06835       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
06836       return NULL;
06837    }
06838    ast_log(LOG_DEBUG, "Monitor starting...\n");
06839 #endif
06840    for (;;) {
06841       /* Lock the interface list */
06842       ast_mutex_lock(&iflock);
06843       if (!pfds || (lastalloc != ifcount)) {
06844          if (pfds) {
06845             free(pfds);
06846             pfds = NULL;
06847          }
06848          if (ifcount) {
06849             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
06850                ast_mutex_unlock(&iflock);
06851                return NULL;
06852             }
06853          }
06854          lastalloc = ifcount;
06855       }
06856       /* Build the stuff we're going to poll on, that is the socket of every
06857          zt_pvt that does not have an associated owner channel */
06858       count = 0;
06859       i = iflist;
06860       while (i) {
06861          if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
06862             if (!i->owner && !i->subs[SUB_REAL].owner) {
06863                /* This needs to be watched, as it lacks an owner */
06864                pfds[count].fd = i->subs[SUB_REAL].zfd;
06865                pfds[count].events = POLLPRI;
06866                pfds[count].revents = 0;
06867                /* Message waiting or r2 channels also get watched for reading */
06868                if (i->cidspill)
06869                   pfds[count].events |= POLLIN;
06870                count++;
06871             }
06872          }
06873          i = i->next;
06874       }
06875       /* Okay, now that we know what to do, release the interface lock */
06876       ast_mutex_unlock(&iflock);
06877       
06878       pthread_testcancel();
06879       /* Wait at least a second for something to happen */
06880       res = poll(pfds, count, 1000);
06881       pthread_testcancel();
06882       /* Okay, poll has finished.  Let's see what happened.  */
06883       if (res < 0) {
06884          if ((errno != EAGAIN) && (errno != EINTR))
06885             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
06886          continue;
06887       }
06888       /* Alright, lock the interface list again, and let's look and see what has
06889          happened */
06890       ast_mutex_lock(&iflock);
06891       found = 0;
06892       spoint = 0;
06893       lastpass = thispass;
06894       thispass = time(NULL);
06895       i = iflist;
06896       while (i) {
06897          if (thispass != lastpass) {
06898             if (!found && ((i == last) || ((i == iflist) && !last))) {
06899                last = i;
06900                if (last) {
06901                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
06902                      (last->sig & __ZT_SIG_FXO)) {
06903                      res = ast_app_has_voicemail(last->mailbox, NULL);
06904                      if (last->msgstate != res) {
06905                         int x;
06906                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
06907                         x = ZT_FLUSH_BOTH;
06908                         res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
06909                         if (res2)
06910                            ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
06911                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
06912                            /* Turn on on hook transfer for 4 seconds */
06913                            x = 4000;
06914                            ioctl(last->subs[SUB_REAL].zfd, ZT_ONHOOKTRANSFER, &x);
06915                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
06916                            last->cidpos = 0;
06917                            last->msgstate = res;
06918                            last->onhooktime = thispass;
06919                         }
06920                         found ++;
06921                      }
06922                   }
06923                   last = last->next;
06924                }
06925             }
06926          }
06927          if ((i->subs[SUB_REAL].zfd > -1) && i->sig) {
06928             if (i->radio && !i->owner)
06929             {
06930                res = zt_get_event(i->subs[SUB_REAL].zfd);
06931                if (res)
06932                {
06933                   if (option_debug)
06934                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
06935                   /* Don't hold iflock while handling init events */
06936                   ast_mutex_unlock(&iflock);
06937                   handle_init_event(i, res);
06938                   ast_mutex_lock(&iflock);   
06939                }
06940                i = i->next;
06941                continue;
06942             }              
06943             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint);
06944             if (pollres & POLLIN) {
06945                if (i->owner || i->subs[SUB_REAL].owner) {
06946 #ifdef HAVE_PRI
06947                   if (!i->pri)
06948 #endif                  
06949                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].zfd);
06950                   i = i->next;
06951                   continue;
06952                }
06953                if (!i->cidspill) {
06954                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
06955                   i = i->next;
06956                   continue;
06957                }
06958                res = read(i->subs[SUB_REAL].zfd, buf, sizeof(buf));
06959                if (res > 0) {
06960                   /* We read some number of bytes.  Write an equal amount of data */
06961                   if (res > i->cidlen - i->cidpos) 
06962                      res = i->cidlen - i->cidpos;
06963                   res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
06964                   if (res2 > 0) {
06965                      i->cidpos += res2;
06966                      if (i->cidpos >= i->cidlen) {
06967                         free(i->cidspill);
06968                         i->cidspill = 0;
06969                         i->cidpos = 0;
06970                         i->cidlen = 0;
06971                      }
06972                   } else {
06973                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
06974                      i->msgstate = -1;
06975                   }
06976                } else {
06977                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
06978                }
06979             }
06980             if (pollres & POLLPRI) {
06981                if (i->owner || i->subs[SUB_REAL].owner) {
06982 #ifdef HAVE_PRI
06983                   if (!i->pri)
06984 #endif                  
06985                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].zfd);
06986                   i = i->next;
06987                   continue;
06988                }
06989                res = zt_get_event(i->subs[SUB_REAL].zfd);
06990                if (option_debug)
06991                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
06992                /* Don't hold iflock while handling init events */
06993                ast_mutex_unlock(&iflock);
06994                handle_init_event(i, res);
06995                ast_mutex_lock(&iflock);   
06996             }
06997          }
06998          i=i->next;
06999       }
07000       ast_mutex_unlock(&iflock);
07001    }
07002    /* Never reached */
07003    return NULL;
07004    
07005 }

static void enable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3128 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().

03129 {
03130 #ifdef ZT_TONEDETECT
03131    int val;
03132 #endif
03133 
03134    if (p->channel == CHAN_PSEUDO)
03135       return;
03136 
03137    p->ignoredtmf = 0;
03138 
03139 #ifdef ZT_TONEDETECT
03140    val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
03141    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03142 #endif      
03143    if (!p->hardwaredtmf && p->dsp) {
03144       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03145       ast_dsp_set_features(p->dsp, p->dsp_features);
03146    }
03147 }

static char* event2str ( int  event  )  [static]

Definition at line 1147 of file chan_zap.c.

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

01148 {
01149    static char buf[256];
01150    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01151       return events[event];
01152    sprintf(buf, "Event %d", event); /* safe */
01153    return buf;
01154 }

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

Definition at line 1512 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

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

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

Definition at line 1478 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

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

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

Definition at line 10256 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().

10257 {
10258    struct zt_pvt *p = iflist;
10259    while (p) {
10260       if (p->channel == channel) {
10261          break;
10262       }
10263       p = p->next;
10264    }
10265    return p;
10266 }

static int get_alarms ( struct zt_pvt p  )  [static]

Definition at line 3598 of file chan_zap.c.

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

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

03599 {
03600    int res;
03601    ZT_SPANINFO zi;
03602    memset(&zi, 0, sizeof(zi));
03603    zi.spanno = p->span;
03604    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SPANSTAT, &zi);
03605    if (res < 0) {
03606       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03607       return 0;
03608    }
03609    return zi.alarms;
03610 }

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

Definition at line 6595 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, errno, EVENT_FLAG_SYSTEM, free, get_alarms(), zt_pvt::hanguponpolarityswitch, has_voicemail(), zt_pvt::immediate, zt_pvt::inalarm, LOG_NOTICE, 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, zt_pvt::unknown_alarm, VERBOSE_PREFIX_2, zap_destroy_channel_bynum(), zt_subchannel::zfd, zt_disable_ec(), zt_enable_ec(), zt_new(), and zt_set_hook().

06596 {
06597    int res;
06598    pthread_t threadid;
06599    pthread_attr_t attr;
06600    struct ast_channel *chan;
06601    pthread_attr_init(&attr);
06602    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06603    /* Handle an event on a given channel for the monitor thread. */
06604    switch (event) {
06605    case ZT_EVENT_NONE:
06606    case ZT_EVENT_BITSCHANGED:
06607       break;
06608    case ZT_EVENT_WINKFLASH:
06609    case ZT_EVENT_RINGOFFHOOK:
06610       if (i->inalarm) break;
06611       if (i->radio) break;
06612       /* Got a ring/answer.  What kind of channel are we? */
06613       switch (i->sig) {
06614       case SIG_FXOLS:
06615       case SIG_FXOGS:
06616       case SIG_FXOKS:
06617          res = zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
06618          if (res && (errno == EBUSY))
06619             break;
06620          if (i->cidspill) {
06621             /* Cancel VMWI spill */
06622             free(i->cidspill);
06623             i->cidspill = NULL;
06624          }
06625          if (i->immediate) {
06626             zt_enable_ec(i);
06627             /* The channel is immediately up.  Start right away */
06628             res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
06629             chan = zt_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06630             if (!chan) {
06631                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06632                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06633                if (res < 0)
06634                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06635             }
06636          } else {
06637             /* Check for callerid, digits, etc */
06638             chan = zt_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06639             if (chan) {
06640                if (has_voicemail(i))
06641                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_STUTTER);
06642                else
06643                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
06644                if (res < 0) 
06645                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06646                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06647                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06648                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06649                   if (res < 0)
06650                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06651                   ast_hangup(chan);
06652                }
06653             } else
06654                ast_log(LOG_WARNING, "Unable to create channel\n");
06655          }
06656          break;
06657       case SIG_FXSLS:
06658       case SIG_FXSGS:
06659       case SIG_FXSKS:
06660             i->ringt = i->ringt_base;
06661             /* Fall through */
06662       case SIG_EMWINK:
06663       case SIG_FEATD:
06664       case SIG_FEATDMF:
06665       case SIG_FEATDMF_TA:
06666       case SIG_E911:
06667       case SIG_FGC_CAMA:
06668       case SIG_FGC_CAMAMF:
06669       case SIG_FEATB:
06670       case SIG_EM:
06671       case SIG_EM_E1:
06672       case SIG_SFWINK:
06673       case SIG_SF_FEATD:
06674       case SIG_SF_FEATDMF:
06675       case SIG_SF_FEATB:
06676       case SIG_SF:
06677             /* Check for callerid, digits, etc */
06678             chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06679             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06680                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06681                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06682                if (res < 0)
06683                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06684                ast_hangup(chan);
06685             } else if (!chan) {
06686                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06687             }
06688             break;
06689       default:
06690          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06691          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06692          if (res < 0)
06693                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06694          return -1;
06695       }
06696       break;
06697    case ZT_EVENT_NOALARM:
06698       i->inalarm = 0;
06699       if (!i->unknown_alarm) {
06700          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06701          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06702             "Channel: %d\r\n", i->channel);
06703       } else {
06704          i->unknown_alarm = 0;
06705       }
06706       break;
06707    case ZT_EVENT_ALARM:
06708       i->inalarm = 1;
06709       res = get_alarms(i);
06710       do {
06711          const char *alarm_str = alarm2str(res);
06712 
06713          /* hack alert!  Zaptel 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
06714           * doesn't know what to do with it.  Don't confuse users with log messages. */
06715          if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
06716             i->unknown_alarm = 1;
06717             break;
06718          } else {
06719             i->unknown_alarm = 0;
06720          }
06721 
06722          ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm_str);
06723          manager_event(EVENT_FLAG_SYSTEM, "Alarm",
06724             "Alarm: %s\r\n"
06725             "Channel: %d\r\n",
06726             alarm_str, i->channel);
06727       } while (0);
06728       /* fall thru intentionally */
06729    case ZT_EVENT_ONHOOK:
06730       if (i->radio)
06731          break;
06732       /* Back on hook.  Hang up. */
06733       switch (i->sig) {
06734       case SIG_FXOLS:
06735       case SIG_FXOGS:
06736       case SIG_FEATD:
06737       case SIG_FEATDMF:
06738       case SIG_FEATDMF_TA:
06739       case SIG_E911:
06740       case SIG_FGC_CAMA:
06741       case SIG_FGC_CAMAMF:
06742       case SIG_FEATB:
06743       case SIG_EM:
06744       case SIG_EM_E1:
06745       case SIG_EMWINK:
06746       case SIG_SF_FEATD:
06747       case SIG_SF_FEATDMF:
06748       case SIG_SF_FEATB:
06749       case SIG_SF:
06750       case SIG_SFWINK:
06751       case SIG_FXSLS:
06752       case SIG_FXSGS:
06753       case SIG_FXSKS:
06754       case SIG_GR303FXSKS:
06755          zt_disable_ec(i);
06756          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06757          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
06758          break;
06759       case SIG_GR303FXOKS:
06760       case SIG_FXOKS:
06761          zt_disable_ec(i);
06762          /* Diddle the battery for the zhone */
06763 #ifdef ZHONE_HACK
06764          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
06765          usleep(1);
06766 #endif         
06767          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06768          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
06769          break;
06770       case SIG_PRI:
06771          zt_disable_ec(i);
06772          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06773          break;
06774       default:
06775          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06776          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06777          return -1;
06778       }
06779       break;
06780    case ZT_EVENT_POLARITY:
06781       switch (i->sig) {
06782       case SIG_FXSLS:
06783       case SIG_FXSKS:
06784       case SIG_FXSGS:
06785          /* We have already got a PR before the channel was 
06786             created, but it wasn't handled. We need polarity 
06787             to be REV for remote hangup detection to work. 
06788             At least in Spain */
06789          if (i->hanguponpolarityswitch)
06790             i->polarity = POLARITY_REV;
06791 
06792          if (i->cid_start == CID_START_POLARITY) {
06793             i->polarity = POLARITY_REV;
06794             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
06795                    "CID detection on channel %d\n",
06796                    i->channel);
06797             chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
06798             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06799                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06800             }
06801          }
06802          break;
06803       default:
06804          ast_log(LOG_WARNING, "handle_init_event detected "
06805             "polarity reversal on non-FXO (SIG_FXS) "
06806             "interface %d\n", i->channel);
06807       }
06808       break;
06809    case ZT_EVENT_REMOVED: /* destroy channel */
06810       ast_log(LOG_NOTICE, 
06811             "Got ZT_EVENT_REMOVED. Destroying channel %d\n", 
06812             i->channel);
06813       zap_destroy_channel_bynum(i->channel);
06814       break;
06815    }
06816    pthread_attr_destroy(&attr);
06817    return 0;
06818 }

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

Definition at line 10100 of file chan_zap.c.

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

10101 {
10102    int i, j;
10103    for (i = 0; i < num_cadence; i++) {
10104       char output[1024];
10105       char tmp[16], tmp2[64];
10106       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10107       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10108 
10109       for (j = 0; j < 16; j++) {
10110          if (cadences[i].ringcadence[j] == 0)
10111             break;
10112          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10113          if (cidrings[i] * 2 - 1 == j)
10114             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10115          else
10116             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10117          if (j != 0)
10118             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10119          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10120       }
10121       ast_cli(fd,"%s\n",output);
10122    }
10123    return 0;
10124 }

static int has_voicemail ( struct zt_pvt p  )  [static]

Definition at line 1709 of file chan_zap.c.

References ast_app_has_voicemail(), and zt_pvt::mailbox.

01710 {
01711 
01712    return ast_app_has_voicemail(p->mailbox, NULL);
01713 }

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

Definition at line 1266 of file chan_zap.c.

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

Referenced by conf_del().

01267 {
01268    /* If they're listening to our channel, they're ours */  
01269    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == ZT_CONF_DIGITALMON))
01270       return 1;
01271    /* If they're a talker on our (allocated) conference, they're ours */
01272    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & ZT_CONF_TALKER))
01273       return 1;
01274    return 0;
01275 }

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

Definition at line 1299 of file chan_zap.c.

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

Referenced by update_conf().

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

static int load_module ( void   )  [static]

Definition at line 11394 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, round_robin, setup_zap(), zap_cli, and zap_tech.

11395 {
11396    int res;
11397 
11398 #ifdef HAVE_PRI
11399    int y,i;
11400    memset(pris, 0, sizeof(pris));
11401    for (y = 0; y < NUM_SPANS; y++) {
11402       ast_mutex_init(&pris[y].lock);
11403       pris[y].offset = -1;
11404       pris[y].master = AST_PTHREADT_NULL;
11405       for (i = 0; i < NUM_DCHANS; i++)
11406          pris[y].fds[i] = -1;
11407    }
11408    pri_set_error(zt_pri_error);
11409    pri_set_message(zt_pri_message);
11410    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11411          zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11412 #endif
11413    res = setup_zap(0);
11414    /* Make sure we can register our Zap channel type */
11415    if (res)
11416       return AST_MODULE_LOAD_DECLINE;
11417    if (ast_channel_register(&zap_tech)) {
11418       ast_log(LOG_ERROR, "Unable to register channel class 'Zap'\n");
11419       __unload_module();
11420       return -1;
11421    }
11422 #ifdef HAVE_PRI
11423    ast_string_field_init(&inuse, 16);
11424    ast_string_field_set(&inuse, name, "GR-303InUse");
11425    ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
11426 #endif   
11427    ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
11428    
11429    memset(round_robin, 0, sizeof(round_robin));
11430    ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
11431    ast_manager_register( "ZapHangup", 0, action_transferhangup, "Hangup Zap Channel" );
11432    ast_manager_register( "ZapDialOffhook", 0, action_zapdialoffhook, "Dial over Zap channel while offhook" );
11433    ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
11434    ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
11435    ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
11436    ast_manager_register("ZapRestart", 0, action_zaprestart, "Fully Restart zaptel channels (terminates calls)");
11437 
11438    return res;
11439 }

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

Definition at line 7152 of file chan_zap.c.

References ast_calloc, ast_log(), ast_mutex_init(), ast_strlen_zero(), zt_chan_conf::chan, CHAN_PSEUDO, destroy_zt_pvt(), errno, iflist, LOG_ERROR, MAX_CHANNELS, zt_pvt::next, zt_pvt::prev, zt_pvt::sig, sig2str, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SUB_REAL, and zt_open().

Referenced by build_channels().

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

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

Definition at line 5389 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

05390 {
05391    char c;
05392 
05393    *str = 0; /* start with empty output buffer */
05394    for (;;)
05395    {
05396       /* Wait for the first digit (up to specified ms). */
05397       c = ast_waitfordigit(chan, ms);
05398       /* if timeout, hangup or error, return as such */
05399       if (c < 1)
05400          return c;
05401       *str++ = c;
05402       *str = 0;
05403       if (strchr(term, c))
05404          return 1;
05405    }
05406 }

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

Definition at line 4922 of file chan_zap.c.

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

Referenced by zt_write().

04923 {
04924    int sent=0;
04925    int size;
04926    int res;
04927    int fd;
04928    fd = p->subs[index].zfd;
04929    while (len) {
04930       size = len;
04931       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
04932          size = (linear ? READ_SIZE * 2 : READ_SIZE);
04933       res = write(fd, buf, size);
04934       if (res != size) {
04935          if (option_debug)
04936             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04937          return sent;
04938       }
04939       len -= size;
04940       buf += size;
04941    }
04942    return sent;
04943 }

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

Definition at line 10594 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, 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, zt_pvt::mailbox, MAX_CHANLIST_LEN, zt_pvt::mohinterpret, zt_pvt::mohsuggest, ast_variable::name, ast_variable::next, 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().

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

static int reload ( void   )  [static]

Definition at line 11542 of file chan_zap.c.

References ast_log(), and setup_zap().

11543 {
11544    int res = 0;
11545 
11546    res = setup_zap(1);
11547    if (res) {
11548       ast_log(LOG_WARNING, "Reload of chan_zap.so is unsuccessful!\n");
11549       return -1;
11550    }
11551    return 0;
11552 }

static int reset_conf ( struct zt_pvt p  )  [static]

Definition at line 1343 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().

01344 {
01345    ZT_CONFINFO zi;
01346    memset(&zi, 0, sizeof(zi));
01347    p->confno = -1;
01348    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01349    if (p->subs[SUB_REAL].zfd > -1) {
01350       if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &zi))
01351          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d!\n", p->channel);
01352    }
01353    return 0;
01354 }

static int restart_monitor ( void   )  [static]

Definition at line 7007 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(), and LOG_ERROR.

07008 {
07009    pthread_attr_t attr;
07010    pthread_attr_init(&attr);
07011    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07012    /* If we're supposed to be stopped -- stay stopped */
07013    if (monitor_thread == AST_PTHREADT_STOP)
07014       return 0;
07015    ast_mutex_lock(&monlock);
07016    if (monitor_thread == pthread_self()) {
07017       ast_mutex_unlock(&monlock);
07018       ast_log(LOG_WARNING, "Cannot kill myself\n");
07019       return -1;
07020    }
07021    if (monitor_thread != AST_PTHREADT_NULL) {
07022       /* Wake up the thread */
07023       pthread_kill(monitor_thread, SIGURG);
07024    } else {
07025       /* Start a new monitor */
07026       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07027          ast_mutex_unlock(&monlock);
07028          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07029          pthread_attr_destroy(&attr);
07030          return -1;
07031       }
07032    }
07033    ast_mutex_unlock(&monlock);
07034    pthread_attr_destroy(&attr);
07035    return 0;
07036 }

static int restore_conference ( struct zt_pvt p  )  [static]

Definition at line 1675 of file chan_zap.c.

References ast_log(), errno, 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().

01676 {
01677    int res;
01678    if (p->saveconf.confmode) {
01679       res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &p->saveconf);
01680       p->saveconf.confmode = 0;
01681       if (res) {
01682          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01683          return -1;
01684       }
01685    }
01686    if (option_debug)
01687       ast_log(LOG_DEBUG, "Restored conferencing\n");
01688    return 0;
01689 }

static int restore_gains ( struct zt_pvt p  )  [static]

Definition at line 1602 of file chan_zap.c.

References ast_log(), errno, 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().

01603 {
01604    int res;
01605 
01606    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
01607    if (res) {
01608       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01609       return -1;
01610    }
01611 
01612    return 0;
01613 }

static int save_conference ( struct zt_pvt p  )  [static]

Definition at line 1647 of file chan_zap.c.

References ast_log(), errno, 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().

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

static int send_callerid ( struct zt_pvt p  )  [static]

Definition at line 1715 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, errno, 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().

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

static int send_cwcidspill ( struct zt_pvt p  )  [static]

Definition at line 1693 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().

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

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

Definition at line 1583 of file chan_zap.c.

References set_actual_rxgain(), and set_actual_txgain().

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

01584 {
01585    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01586 }

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

Definition at line 1565 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

01566 {
01567    struct zt_gains g;
01568    int res;
01569 
01570    memset(&g, 0, sizeof(g));
01571    g.chan = chan;
01572    res = ioctl(fd, ZT_GETGAINS, &g);
01573    if (res) {
01574       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01575       return res;
01576    }
01577 
01578    fill_rxgain(&g, gain, law);
01579 
01580    return ioctl(fd, ZT_SETGAINS, &g);
01581 }

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

Definition at line 1546 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

01547 {
01548    struct zt_gains g;
01549    int res;
01550 
01551    memset(&g, 0, sizeof(g));
01552    g.chan = chan;
01553    res = ioctl(fd, ZT_GETGAINS, &g);
01554    if (res) {
01555       if (option_debug)
01556          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01557       return res;
01558    }
01559 
01560    fill_txgain(&g, gain, law);
01561 
01562    return ioctl(fd, ZT_SETGAINS, &g);
01563 }

static int setup_zap ( int  reload  )  [static]

Definition at line 11261 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(), default_jbconf, global_jbconf, ast_variable::lineno, LOG_ERROR, 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().

11262 {
11263    struct ast_config *cfg;
11264    struct ast_variable *v;
11265    struct zt_chan_conf conf = zt_chan_conf_default();
11266    int res;
11267 
11268 #ifdef HAVE_PRI
11269    char *c;
11270    int spanno;
11271    int i, x;
11272    int logicalspan;
11273    int trunkgroup;
11274    int dchannels[NUM_DCHANS];
11275 #endif
11276 
11277    cfg = ast_config_load(config);
11278 
11279    /* Error if we have no config file */
11280    if (!cfg) {
11281       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
11282       return 0;
11283    }
11284 
11285    /* It's a little silly to lock it, but we mind as well just to be sure */
11286    ast_mutex_lock(&iflock);
11287 #ifdef HAVE_PRI
11288    if (!reload) {
11289       /* Process trunkgroups first */
11290       v = ast_variable_browse(cfg, "trunkgroups");
11291       while (v) {
11292          if (!strcasecmp(v->name, "trunkgroup")) {
11293             trunkgroup = atoi(v->value);
11294             if (trunkgroup > 0) {
11295                if ((c = strchr(v->value, ','))) {
11296                   i = 0;
11297                   memset(dchannels, 0, sizeof(dchannels));
11298                   while (c && (i < NUM_DCHANS)) {
11299                      dchannels[i] = atoi(c + 1);
11300                      if (dchannels[i] < 0) {
11301                         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);
11302                      } else
11303                         i++;
11304                      c = strchr(c + 1, ',');
11305                   }
11306                   if (i) {
11307                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11308                         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);
11309                      } else if (option_verbose > 1)
11310                         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");
11311                   } else
11312                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
11313                } else
11314                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
11315             } else
11316                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
11317          } else if (!strcasecmp(v->name, "spanmap")) {
11318             spanno = atoi(v->value);
11319             if (spanno > 0) {
11320                if ((c = strchr(v->value, ','))) {
11321                   trunkgroup = atoi(c + 1);
11322                   if (trunkgroup > 0) {
11323                      if ((c = strchr(c + 1, ','))) 
11324                         logicalspan = atoi(c + 1);
11325                      else
11326                         logicalspan = 0;
11327                      if (logicalspan >= 0) {
11328                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11329                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11330                         } else if (option_verbose > 1) 
11331                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11332                      } else
11333                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
11334                   } else
11335                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
11336                } else
11337                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
11338             } else
11339                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
11340          } else {
11341             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11342          }
11343          v = v->next;
11344       }
11345    }
11346 #endif
11347    
11348    /* Copy the default jb config over global_jbconf */
11349    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11350 
11351    v = ast_variable_browse(cfg, "channels");
11352    res = process_zap(&conf, v, reload, 0);
11353    ast_mutex_unlock(&iflock);
11354    ast_config_destroy(cfg);
11355    if (res)
11356       return res;
11357    cfg = ast_config_load("users.conf");
11358    if (cfg) {
11359       char *cat;
11360       const char *chans;
11361       process_zap(&conf, ast_variable_browse(cfg, "general"), 1, 1);
11362       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11363          if (!strcasecmp(cat, "general"))
11364             continue;
11365          chans = ast_variable_retrieve(cfg, cat, "zapchan");
11366          if (!ast_strlen_zero(chans)) {
11367             /** \todo At this point we should probably 
11368              * duplicate conf, and pass a copy, to prevent 
11369              * one section from affecting another
11370              */
11371             process_zap(&conf, ast_variable_browse(cfg, cat), reload, 0);
11372          }
11373       }
11374       ast_config_destroy(cfg);
11375    }
11376 #ifdef HAVE_PRI
11377    if (!reload) {
11378       for (x = 0; x < NUM_SPANS; x++) {
11379          if (pris[x].pvts[0]) {
11380             if (start_pri(pris + x)) {
11381                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11382                return -1;
11383             } else if (option_verbose > 1)
11384                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11385          }
11386       }
11387    }
11388 #endif
11389    /* And start the monitor for the first time */
11390    restart_monitor();
11391    return 0;
11392 }

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

Definition at line 5426 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_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(), 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, zt_pvt::context, ast_channel::context, ringContextData::contextData, counter, zt_pvt::defcontext, zt_pvt::dnd, zt_pvt::dop, zt_pvt::drings, zt_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, zt_pvt::dtmfrelax, errno, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, zt_pvt::exten, exten, f, 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, 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, zt_pvt::ringt, zt_pvt::ringt_base, 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::smdi_iface, SMDI_MD_WAIT_TIMEOUT, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, timeout, 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, zap_tech, 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().

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

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

Definition at line 844 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().

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

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

Definition at line 970 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().

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

static int unload_module ( void   )  [static]

Definition at line 10491 of file chan_zap.c.

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

10492 {
10493 #ifdef HAVE_PRI      
10494    int y;
10495    for (y = 0; y < NUM_SPANS; y++)
10496       ast_mutex_destroy(&pris[y].lock);
10497 #endif
10498    return __unload_module();
10499 }

static int update_conf ( struct zt_pvt p  )  [static]

Definition at line 1356 of file chan_zap.c.

References conf_add(), conf_del(), zt_subchannel::inthreeway, isslavenative(), zt_pvt::subs, and zt_subchannel::zfd.

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

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

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

Definition at line 784 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().

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

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

Definition at line 9852 of file chan_zap.c.

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

09853 {
09854    int channel;
09855    
09856    if (argc != 4)
09857       return RESULT_SHOWUSAGE;
09858    
09859    channel = atoi(argv[3]);
09860 
09861    return zap_destroy_channel_bynum(channel);
09862 }

static int zap_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 6578 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().

06579 {
06580    struct zt_pvt *tmp = NULL;
06581    struct zt_pvt *prev = NULL;
06582 
06583    tmp = iflist;
06584    while (tmp) {
06585       if (tmp->channel == channel) {
06586          destroy_channel(prev, tmp, 1);
06587          return RESULT_SUCCESS;
06588       }
06589       prev = tmp;
06590       tmp = tmp->next;
06591    }
06592    return RESULT_FAILURE;
06593 }

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

Definition at line 10240 of file chan_zap.c.

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

Referenced by action_transfer(), and action_transferhangup().

10241 {
10242    if (p) {
10243       switch (mode) {
10244          case TRANSFER:
10245             p->fake_event = ZT_EVENT_WINKFLASH;
10246             break;
10247          case HANGUP:
10248             p->fake_event = ZT_EVENT_ONHOOK;
10249             break;
10250          default:
10251             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10252       }
10253    }
10254    return 0;
10255 }

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

Definition at line 814 of file chan_zap.c.

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

Referenced by action_zapdialoffhook().

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

static int zap_restart ( void   )  [static]

Definition at line 9865 of file chan_zap.c.

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

Referenced by action_zaprestart(), and zap_restart_cmd().

09866 {
09867    if (option_verbose > 0)
09868       ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
09869    while (iflist) {
09870       if (option_debug)
09871          ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
09872       /* Also updates iflist: */
09873       destroy_channel(NULL, iflist, 1);
09874    }
09875    if (option_debug)
09876       ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
09877    if (setup_zap(0) != 0) {
09878       ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
09879       return 1;
09880    }
09881    return 0;
09882 }

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

Definition at line 9884 of file chan_zap.c.

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

09885 {
09886    if (argc != 2) {
09887       return RESULT_SHOWUSAGE;
09888    }
09889 
09890    if (zap_restart() != 0)
09891       return RESULT_FAILURE;
09892    return RESULT_SUCCESS;
09893 }

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

Definition at line 9966 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, zt_pvt::master, 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.

09967 {
09968    int channel;
09969    struct zt_pvt *tmp = NULL;
09970    ZT_CONFINFO ci;
09971    ZT_PARAMS ps;
09972    int x;
09973    ast_mutex_t *lock;
09974    struct zt_pvt *start;
09975 #ifdef HAVE_PRI
09976    char *c;
09977    int trunkgroup;
09978    struct zt_pri *pri=NULL;
09979 #endif
09980 
09981    lock = &iflock;
09982    start = iflist;
09983 
09984    if (argc != 4)
09985       return RESULT_SHOWUSAGE;
09986 #ifdef HAVE_PRI
09987    if ((c = strchr(argv[3], ':'))) {
09988       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
09989          return RESULT_SHOWUSAGE;
09990       if ((trunkgroup < 1) || (channel < 1))
09991          return RESULT_SHOWUSAGE;
09992       for (x = 0; x < NUM_SPANS; x++) {
09993          if (pris[x].trunkgroup == trunkgroup) {
09994             pri = pris + x;
09995             break;
09996          }
09997       }
09998       if (pri) {
09999          start = pri->crvs;
10000          lock = &pri->lock;
10001       } else {
10002          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10003          return RESULT_FAILURE;
10004       }
10005    } else
10006 #endif
10007       channel = atoi(argv[3]);
10008 
10009    ast_mutex_lock(lock);
10010    tmp = start;
10011    while (tmp) {
10012       if (tmp->channel == channel) {
10013 #ifdef HAVE_PRI
10014          if (pri) 
10015             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10016          else
10017 #endif         
10018          ast_cli(fd, "Channel: %d\n", tmp->channel);
10019          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
10020          ast_cli(fd, "Span: %d\n", tmp->span);
10021          ast_cli(fd, "Extension: %s\n", tmp->exten);
10022          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10023          ast_cli(fd, "Context: %s\n", tmp->context);
10024          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10025          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10026          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10027          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10028          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10029          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10030          ast_cli(fd, "Radio: %d\n", tmp->radio);
10031          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10032          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)" : "");
10033          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)" : "");
10034          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)" : "");
10035          ast_cli(fd, "Confno: %d\n", tmp->confno);
10036          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10037          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10038          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10039          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10040          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10041          ast_cli(fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
10042          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10043          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10044          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10045          if (tmp->master)
10046             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10047          for (x = 0; x < MAX_SLAVES; x++) {
10048             if (tmp->slaves[x])
10049                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10050          }
10051 #ifdef HAVE_PRI
10052          if (tmp->pri) {
10053             ast_cli(fd, "PRI Flags: ");
10054             if (tmp->resetting)
10055                ast_cli(fd, "Resetting ");
10056             if (tmp->call)
10057                ast_cli(fd, "Call ");
10058             if (tmp->bearer)
10059                ast_cli(fd, "Bearer ");
10060             ast_cli(fd, "\n");
10061             if (tmp->logicalspan) 
10062                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10063             else
10064                ast_cli(fd, "PRI Logical Span: Implicit\n");
10065          }
10066             
10067 #endif
10068          memset(&ci, 0, sizeof(ci));
10069          ps.channo = tmp->channel;
10070          if (tmp->subs[SUB_REAL].zfd > -1) {
10071             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
10072                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10073             }
10074 #ifdef ZT_GETCONFMUTE
10075             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) {
10076                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10077             }
10078 #endif
10079             if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
10080                ast_log(LOG_WARNING, "Failed to get parameters on channel %d\n", tmp->channel);
10081             } else {
10082                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10083             }
10084          }
10085          ast_mutex_unlock(lock);
10086          return RESULT_SUCCESS;
10087       }
10088       tmp = tmp->next;
10089    }
10090    
10091    ast_cli(fd, "Unable to find given channel %d\n", channel);
10092    ast_mutex_unlock(lock);
10093    return RESULT_FAILURE;
10094 }

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

Definition at line 9905 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.

09906 {
09907 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
09908 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
09909    struct zt_pvt *tmp = NULL;
09910    char tmps[20] = "";
09911    ast_mutex_t *lock;
09912    struct zt_pvt *start;
09913 #ifdef HAVE_PRI
09914    int trunkgroup;
09915    struct zt_pri *pri = NULL;
09916    int x;
09917 #endif
09918 
09919    lock = &iflock;
09920    start = iflist;
09921 
09922 #ifdef HAVE_PRI
09923    if (argc == 4) {
09924       if ((trunkgroup = atoi(argv[3])) < 1)
09925          return RESULT_SHOWUSAGE;
09926       for (x = 0; x < NUM_SPANS; x++) {
09927          if (pris[x].trunkgroup == trunkgroup) {
09928             pri = pris + x;
09929             break;
09930          }
09931       }
09932       if (pri) {
09933          start = pri->crvs;
09934          lock = &pri->lock;
09935       } else {
09936          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
09937          return RESULT_FAILURE;
09938       }
09939    } else
09940 #endif
09941    if (argc != 3)
09942       return RESULT_SHOWUSAGE;
09943 
09944    ast_mutex_lock(lock);
09945 #ifdef HAVE_PRI
09946    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
09947 #else
09948    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
09949 #endif   
09950    
09951    tmp = start;
09952    while (tmp) {
09953       if (tmp->channel > 0) {
09954          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
09955       } else
09956          ast_copy_string(tmps, "pseudo", sizeof(tmps));
09957       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
09958       tmp = tmp->next;
09959    }
09960    ast_mutex_unlock(lock);
09961    return RESULT_SUCCESS;
09962 #undef FORMAT
09963 #undef FORMAT2
09964 }

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

Definition at line 10127 of file chan_zap.c.

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

10127                                                            {
10128    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10129    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10130 
10131    int span;
10132    int res;
10133    char alarms[50];
10134 
10135    int ctl;
10136    ZT_SPANINFO s;
10137 
10138    ctl = open("/dev/zap/ctl", O_RDWR);
10139    if (ctl < 0) {
10140       ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10141       ast_cli(fd, "No Zaptel interface found.\n");
10142       return RESULT_FAILURE;
10143    }
10144    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10145 
10146    for (span = 1; span < ZT_MAX_SPANS; ++span) {
10147       s.spanno = span;
10148       res = ioctl(ctl, ZT_SPANSTAT, &s);
10149       if (res) {
10150          continue;
10151       }
10152       alarms[0] = '\0';
10153       if (s.alarms > 0) {
10154          if (s.alarms & ZT_ALARM_BLUE)
10155             strcat(alarms, "BLU/");
10156          if (s.alarms & ZT_ALARM_YELLOW)
10157             strcat(alarms, "YEL/");
10158          if (s.alarms & ZT_ALARM_RED)
10159             strcat(alarms, "RED/");
10160          if (s.alarms & ZT_ALARM_LOOPBACK)
10161             strcat(alarms, "LB/");
10162          if (s.alarms & ZT_ALARM_RECOVER)
10163             strcat(alarms, "REC/");
10164          if (s.alarms & ZT_ALARM_NOTOPEN)
10165             strcat(alarms, "NOP/");
10166          if (!strlen(alarms))
10167             strcat(alarms, "UUU/");
10168          if (strlen(alarms)) {
10169             /* Strip trailing / */
10170             alarms[strlen(alarms) - 1] = '\0';
10171          }
10172       } else {
10173          if (s.numchans)
10174             strcpy(alarms, "OK");
10175          else
10176             strcpy(alarms, "UNCONFIGURED");
10177       }
10178 
10179       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10180    }
10181    close(ctl);
10182 
10183    return RESULT_SUCCESS;
10184 #undef FORMAT
10185 #undef FORMAT2
10186 }

static char* zap_sig2str ( int  sig  )  [static]

Definition at line 1166 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.

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

static int zt_answer ( struct ast_channel ast  )  [static]

Definition at line 2740 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().

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

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 3149 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(), f, ast_channel::fds, zt_subchannel::inthreeway, zt_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, 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().

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

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

Definition at line 1776 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, errno, 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().

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

static int zt_callwait ( struct ast_channel ast  )  [static]

Definition at line 1748 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().

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

static struct zt_chan_conf zt_chan_conf_default ( void   )  [static]

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

Definition at line 600 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().

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

static void zt_close ( int  fd  )  [static]

Definition at line 919 of file chan_zap.c.

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

00920 {
00921    if (fd > 0)
00922       close(fd);
00923 }

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

Definition at line 1631 of file chan_zap.c.

References ast_log(), zt_pvt::channel, errno, 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().

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

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

Definition at line 1006 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().

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

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

Definition at line 1066 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().

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

static void zt_disable_ec ( struct zt_pvt p  )  [static]

Definition at line 1463 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().

01464 {
01465    int x;
01466    int res;
01467    if (p->echocancel) {
01468       x = 0;
01469       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01470       if (res)
01471          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
01472       else if (option_debug)
01473          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01474    }
01475    p->echocanon = 0;
01476 }

static void zt_enable_ec ( struct zt_pvt p  )  [static]

Definition at line 1413 of file chan_zap.c.

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

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

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

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

Definition at line 4625 of file chan_zap.c.

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

04626 {
04627    struct zt_pvt *p = ast->tech_pvt;
04628    struct ast_frame *f;
04629    ast_mutex_lock(&p->lock);
04630    f = __zt_exception(ast);
04631    ast_mutex_unlock(&p->lock);
04632    return f;
04633 }

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

Definition at line 3444 of file chan_zap.c.

References ast_log(), ast_mutex_lock(), zt_pvt::channel, zt_pvt::lock, LOG_DEBUG, zt_subchannel::owner, zt_pvt::owner, zt_pvt::subs, ast_channel::tech_pvt, and zt_unlink().

03445 {
03446    struct zt_pvt *p = newchan->tech_pvt;
03447    int x;
03448    ast_mutex_lock(&p->lock);
03449    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03450    if (p->owner == oldchan) {
03451       p->owner = newchan;
03452    }
03453    for (x = 0; x < 3; x++)
03454       if (p->subs[x].owner == oldchan) {
03455          if (!x)
03456             zt_unlink(NULL, p, 0);
03457          p->subs[x].owner = newchan;
03458       }
03459    if (newchan->_state == AST_STATE_RINGING) 
03460       zt_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03461    update_conf(p);
03462    ast_mutex_unlock(&p->lock);
03463    return 0;
03464 }

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

Definition at line 3010 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.

03011 {
03012    struct zt_pvt *p = chan->tech_pvt;
03013    
03014    if (!strcasecmp(data, "rxgain")) {
03015       ast_mutex_lock(&p->lock);
03016       snprintf(buf, len, "%f", p->rxgain);
03017       ast_mutex_unlock(&p->lock);   
03018    } else if (!strcasecmp(data, "txgain")) {
03019       ast_mutex_lock(&p->lock);
03020       snprintf(buf, len, "%f", p->txgain);
03021       ast_mutex_unlock(&p->lock);   
03022    } else {
03023       ast_copy_string(buf, "", len);
03024    }
03025    return 0;
03026 }

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(), 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 764 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().

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

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

Definition at line 3612 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, f, zt_pvt::faxhandled, ast_frame::frametype, free, LOG_DEBUG, LOG_NOTICE, 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().

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

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

Definition at line 3683 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::callwaitcas, 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::cidrings, zt_pvt::cidspill, zt_pvt::confirmanswer, ast_frame::data, ast_frame::datalen, zt_pvt::dialdest, zt_pvt::dialing, zt_pvt::dop, zt_pvt::echobreak, zt_pvt::echocanon, zt_pvt::echorest, zt_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, zt_subchannel::f, 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, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, zt_pvt::mohsuggest, zt_pvt::msgstate, zt_subchannel::needflash, zt_subchannel::needhold, 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(), zt_pvt::unknown_alarm, 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().

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

static int zt_hangup ( struct ast_channel ast  )  [static]

Definition at line 2412 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().

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

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

Definition at line 5028 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_SRCUPDATE, 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, errno, func, ast_channel::hangupcause, ISTRUNK, zt_pvt::lock, LOG_DEBUG, 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().

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

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

Definition at line 3087 of file chan_zap.c.

References ast_log(), LOG_WARNING, and master.

Referenced by zt_bridge().

03087                                                                  {
03088    int x;
03089    if (!slave || !master) {
03090       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03091       return;
03092    }
03093    for (x = 0; x < MAX_SLAVES; x++) {
03094       if (!master->slaves[x]) {
03095          master->slaves[x] = slave;
03096          break;
03097       }
03098    }
03099    if (x >= MAX_SLAVES) {
03100       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03101       master->slaves[MAX_SLAVES - 1] = slave;
03102    }
03103    if (slave->master) 
03104       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03105    slave->master = master;
03106    
03107    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03108 }

static struct ast_channel * zt_new ( struct zt_pvt ,
int  ,
int  ,
int  ,
int  ,
int   
) [static]

Definition at line 5202 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, zt_pvt::cid_name, 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, 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, zap_tech, zt_subchannel::zfd, zt_confmute(), and zt_setlinear().

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

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

static int zt_open ( char *  fn  )  [static]

Definition at line 872 of file chan_zap.c.

References ast_log(), errno, LOG_WARNING, and READ_SIZE.

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

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

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

Definition at line 4635 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, errno, zt_subchannel::f, 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, 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().

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

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

Definition at line 7782 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(), 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, zt_pvt::next, option_debug, zt_pvt::outgoing, zt_pvt::owner, zt_pvt::prev, restart_monitor(), round_robin, s, zt_pvt::sig, SIG_FXSKS, strsep(), SUB_CALLWAIT, SUB_REAL, zt_pvt::subs, ast_channel::transfercapability, zt_subchannel::zfd, and zt_new().

07783 {
07784    ast_group_t groupmatch = 0;
07785    int channelmatch = -1;
07786    int roundrobin = 0;
07787    int callwait = 0;
07788    int busy = 0;
07789    struct zt_pvt *p;
07790    struct ast_channel *tmp = NULL;
07791    char *dest=NULL;
07792    int x;
07793    char *s;
07794    char opt=0;
07795    int res=0, y=0;
07796    int backwards = 0;
07797 #ifdef HAVE_PRI
07798    int crv;
07799    int bearer = -1;
07800    int trunkgroup;
07801    struct zt_pri *pri=NULL;
07802 #endif   
07803    struct zt_pvt *exit, *start, *end;
07804    ast_mutex_t *lock;
07805    int channelmatched = 0;
07806    int groupmatched = 0;
07807    
07808    /* Assume we're locking the iflock */
07809    lock = &iflock;
07810    start = iflist;
07811    end = ifend;
07812    if (data) {
07813       dest = ast_strdupa((char *)data);
07814    } else {
07815       ast_log(LOG_WARNING, "Channel requested with no data\n");
07816       return NULL;
07817    }
07818    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
07819       /* Retrieve the group number */
07820       char *stringp=NULL;
07821       stringp=dest + 1;
07822       s = strsep(&stringp, "/");
07823       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
07824          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
07825          return NULL;
07826       }
07827       groupmatch = ((ast_group_t) 1 << x);
07828       if (toupper(dest[0]) == 'G') {
07829          if (dest[0] == 'G') {
07830             backwards = 1;
07831             p = ifend;
07832          } else
07833             p = iflist;
07834       } else {
07835          if (dest[0] == 'R') {
07836             backwards = 1;
07837             p = round_robin[x]?round_robin[x]->prev:ifend;
07838             if (!p)
07839                p = ifend;
07840          } else {
07841             p = round_robin[x]?round_robin[x]->next:iflist;
07842             if (!p)
07843                p = iflist;
07844          }
07845          roundrobin = 1;
07846       }
07847    } else {
07848       char *stringp=NULL;
07849       stringp=dest;
07850       s = strsep(&stringp, "/");
07851       p = iflist;
07852       if (!strcasecmp(s, "pseudo")) {
07853          /* Special case for pseudo */
07854          x = CHAN_PSEUDO;
07855          channelmatch = x;
07856       } 
07857 #ifdef HAVE_PRI
07858       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
07859          if ((trunkgroup < 1) || (crv < 1)) {
07860             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
07861             return NULL;
07862          }
07863          res--;
07864          for (x = 0; x < NUM_SPANS; x++) {
07865             if (pris[x].trunkgroup == trunkgroup) {
07866                pri = pris + x;
07867                lock = &pri->lock;
07868                start = pri->crvs;
07869                end = pri->crvend;
07870                break;
07871             }
07872          }
07873          if (!pri) {
07874             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
07875             return NULL;
07876          }
07877          channelmatch = crv;
07878          p = pris[x].crvs;
07879       }
07880 #endif   
07881       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
07882          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
07883          return NULL;
07884       } else {
07885          channelmatch = x;
07886       }
07887    }
07888    /* Search for an unowned channel */
07889    ast_mutex_lock(lock);
07890    exit = p;
07891    while (p && !tmp) {
07892       if (roundrobin)
07893          round_robin[x] = p;
07894 #if 0
07895       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
07896 #endif
07897 
07898       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
07899          if (option_debug)
07900             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
07901             if (p->inalarm) 
07902                goto next;
07903 
07904          callwait = (p->owner != NULL);
07905 #ifdef HAVE_PRI
07906          if (pri && (p->subs[SUB_REAL].zfd < 0)) {
07907             if (p->sig != SIG_FXSKS) {
07908                /* Gotta find an actual channel to use for this
07909                   CRV if this isn't a callwait */
07910                bearer = pri_find_empty_chan(pri, 0);
07911                if (bearer < 0) {
07912                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
07913                   p = NULL;
07914                   break;
07915                }
07916                pri_assign_bearer(p, pri, pri->pvts[bearer]);
07917             } else {
07918                if (alloc_sub(p, 0)) {
07919                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
07920                   p = NULL;
07921                   break;
07922                } else
07923                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
07924                p->pri = pri;
07925             }
07926          }
07927 #endif         
07928          if (p->channel == CHAN_PSEUDO) {
07929             p = chandup(p);
07930             if (!p) {
07931                break;
07932             }
07933          }
07934          if (p->owner) {
07935             if (alloc_sub(p, SUB_CALLWAIT)) {
07936                p = NULL;
07937                break;
07938             }
07939          }
07940          p->outgoing = 1;
07941          tmp = zt_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
07942 #ifdef HAVE_PRI
07943          if (p->bearer) {
07944             /* Log owner to bearer channel, too */
07945             p->bearer->owner = tmp;
07946          }
07947 #endif         
07948          /* Make special notes */
07949          if (res > 1) {
07950             if (opt == 'c') {
07951                /* Confirm answer */
07952                p->confirmanswer = 1;
07953             } else if (opt == 'r') {
07954                /* Distinctive ring */
07955                if (res < 3)
07956                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
07957                else
07958                   p->distinctivering = y;
07959             } else if (opt == 'd') {
07960                /* If this is an ISDN call, make it digital */
07961                p->digital = 1;
07962                if (tmp)
07963                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
07964             } else {
07965                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
07966             }
07967          }
07968          /* Note if the call is a call waiting call */
07969          if (tmp && callwait)
07970             tmp->cdrflags |= AST_CDR_CALLWAIT;
07971          break;
07972       }
07973 next:
07974       if (backwards) {
07975          p = p->prev;
07976          if (!p)
07977             p = end;
07978       } else {
07979          p = p->next;
07980          if (!p)
07981             p = start;
07982       }
07983       /* stop when you roll to the one that we started from */
07984       if (p == exit)
07985          break;
07986    }
07987    ast_mutex_unlock(lock);
07988    restart_monitor();
07989    if (callwait)
07990       *cause = AST_CAUSE_BUSY;
07991    else if (!tmp) {
07992       if (channelmatched) {
07993          if (busy)
07994             *cause = AST_CAUSE_BUSY;
07995       } else if (groupmatched) {
07996          *cause = AST_CAUSE_CONGESTION;
07997       }
07998    }
07999       
08000    return tmp;
08001 }

static int zt_ring_phone ( struct zt_pvt p  )  [static]

Definition at line 3466 of file chan_zap.c.

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

Referenced by __zt_exception(), and zt_handle_event().

03467 {
03468    int x;
03469    int res;
03470    /* Make sure our transmit state is on hook */
03471    x = 0;
03472    x = ZT_ONHOOK;
03473    res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03474    do {
03475       x = ZT_RING;
03476       res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03477       if (res) {
03478          switch (errno) {
03479          case EBUSY:
03480          case EINTR:
03481             /* Wait just in case */
03482             usleep(10000);
03483             continue;
03484          case EINPROGRESS:
03485             res = 0;
03486             break;
03487          default:
03488             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03489             res = 0;
03490          }
03491       }
03492    } while (res);
03493    return res;
03494 }

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

Definition at line 11441 of file chan_zap.c.

References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, zt_pvt::channel, END_SILENCE_LEN, errno, pollfd::events, pollfd::fd, free, HEADER_LEN, HEADER_MS, LOG_ERROR, 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().

11442 {
11443 #define  END_SILENCE_LEN 400
11444 #define  HEADER_MS 50
11445 #define  TRAILER_MS 5
11446 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11447 #define  ASCII_BYTES_PER_CHAR 80
11448 
11449    unsigned char *buf,*mybuf;
11450    struct zt_pvt *p = c->tech_pvt;
11451    struct pollfd fds[1];
11452    int size,res,fd,len,x;
11453    int bytes=0;
11454    /* Initial carrier (imaginary) */
11455    float cr = 1.0;
11456    float ci = 0.0;
11457    float scont = 0.0;
11458    int index;
11459 
11460    index = zt_get_index(c, p, 0);
11461    if (index < 0) {
11462       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
11463       return -1;
11464    }
11465    if (!text[0]) return(0); /* if nothing to send, dont */
11466    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
11467    if (p->mate) 
11468       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11469    else
11470       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11471    if (!buf)
11472       return -1;
11473    mybuf = buf;
11474    if (p->mate) {
11475       int codec = AST_LAW(p);
11476       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
11477          PUT_CLID_MARKMS;
11478       }
11479       /* Put actual message */
11480       for (x = 0; text[x]; x++) {
11481          PUT_CLID(text[x]);
11482       }
11483       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
11484          PUT_CLID_MARKMS;
11485       }
11486       len = bytes;
11487       buf = mybuf;
11488    } else {
11489       len = tdd_generate(p->tdd, buf, text);
11490       if (len < 1) {
11491          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11492          free(mybuf);
11493          return -1;
11494       }
11495    }
11496    memset(buf + len, 0x7f, END_SILENCE_LEN);
11497    len += END_SILENCE_LEN;
11498    fd = p->subs[index].zfd;
11499    while (len) {
11500       if (ast_check_hangup(c)) {
11501          free(mybuf);
11502          return -1;
11503       }
11504       size = len;
11505       if (size > READ_SIZE)
11506          size = READ_SIZE;
11507       fds[0].fd = fd;
11508       fds[0].events = POLLOUT | POLLPRI;
11509       fds[0].revents = 0;
11510       res = poll(fds, 1, -1);
11511       if (!res) {
11512          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11513          continue;
11514       }
11515         /* if got exception */
11516       if (fds[0].revents & POLLPRI) {
11517          ast_free(mybuf);
11518          return -1;
11519       }
11520       if (!(fds[0].revents & POLLOUT)) {
11521          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11522          continue;
11523       }
11524       res = write(fd, buf, size);
11525       if (res != size) {
11526          if (res == -1) {
11527             free(mybuf);
11528             return -1;
11529          }
11530          if (option_debug)
11531             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11532          break;
11533       }
11534       len -= size;
11535       buf += size;
11536    }
11537    free(mybuf);
11538    return(0);
11539 }

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

Definition at line 1615 of file chan_zap.c.

References ast_log(), errno, and LOG_WARNING.

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

01616 {
01617    int x, res;
01618 
01619    x = hs;
01620    res = ioctl(fd, ZT_HOOK, &x);
01621 
01622    if (res < 0) {
01623       if (errno == EINPROGRESS)
01624          return 0;
01625       ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
01626    }
01627 
01628    return res;
01629 }

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

Definition at line 925 of file chan_zap.c.

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

00926 {
00927    int res;
00928    res = ioctl(zfd, ZT_SETLINEAR, &linear);
00929    if (res)
00930       return res;
00931    return 0;
00932 }

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

Definition at line 2825 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, errno, 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().

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

static void zt_train_ec ( struct zt_pvt p  )  [static]

Definition at line 1447 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().

01448 {
01449    int x;
01450    int res;
01451    if (p && p->echocancel && p->echotraining) {
01452       x = p->echotraining;
01453       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
01454       if (res)
01455          ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
01456       else {
01457          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01458       }
01459    } else
01460       ast_log(LOG_DEBUG, "No echo training requested\n");
01461 }

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

Definition at line 3029 of file chan_zap.c.

References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), conf_del(), zt_pvt::lock, LOG_DEBUG, master, and SUB_REAL.

Referenced by zt_bridge(), and zt_fixup().

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

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 5408 of file chan_zap.c.

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

Referenced by ss_thread().

05409 {
05410    int j;
05411    zt_set_hook(p->subs[index].zfd, ZT_WINK);
05412    for (;;)
05413    {
05414          /* set bits of interest */
05415       j = ZT_IOMUX_SIGEVENT;
05416           /* wait for some happening */
05417       if (ioctl(p->subs[index].zfd,ZT_IOMUX,&j) == -1) return(-1);
05418          /* exit loop if we have it */
05419       if (j & ZT_IOMUX_SIGEVENT) break;
05420    }
05421      /* get the event info */
05422    if (ioctl(p->subs[index].zfd,ZT_GETEVENT,&j) == -1) return(-1);
05423    return 0;
05424 }

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

Definition at line 4945 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, errno, ast_frame::frametype, zt_subchannel::linear, zt_pvt::lock, LOG_DEBUG, 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().

04946 {
04947    struct zt_pvt *p = ast->tech_pvt;
04948    int res;
04949    int index;
04950    index = zt_get_index(ast, p, 0);
04951    if (index < 0) {
04952       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
04953       return -1;
04954    }
04955 
04956 #if 0
04957 #ifdef HAVE_PRI
04958    ast_mutex_lock(&p->lock);
04959    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
04960       if (p->pri->pri) {      
04961          if (!pri_grab(p, p->pri)) {
04962                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
04963                pri_rel(p->pri);
04964          } else
04965                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04966       }
04967       p->proceeding=1;
04968    }
04969    ast_mutex_unlock(&p->lock);
04970 #endif
04971 #endif
04972    /* Write a frame of (presumably voice) data */
04973    if (frame->frametype != AST_FRAME_VOICE) {
04974       if (frame->frametype != AST_FRAME_IMAGE)
04975          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
04976       return 0;
04977    }
04978    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
04979        (frame->subclass != AST_FORMAT_ULAW) &&
04980        (frame->subclass != AST_FORMAT_ALAW)) {
04981       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
04982       return -1;
04983    }
04984    if (p->dialing) {
04985       if (option_debug)
04986          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
04987       return 0;
04988    }
04989    if (!p->owner) {
04990       if (option_debug)
04991          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
04992       return 0;
04993    }
04994    if (p->cidspill) {
04995       if (option_debug)
04996          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
04997       return 0;
04998    }
04999    /* Return if it's not valid data */
05000    if (!frame->data || !frame->datalen)
05001       return 0;
05002 
05003    if (frame->subclass == AST_FORMAT_SLINEAR) {
05004       if (!p->subs[index].linear) {
05005          p->subs[index].linear = 1;
05006          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
05007          if (res)
05008             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05009       }
05010       res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05011    } else {
05012       /* x-law already */
05013       if (p->subs[index].linear) {
05014          p->subs[index].linear = 0;
05015          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
05016          if (res)
05017             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05018       }
05019       res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05020    }
05021    if (res < 0) {
05022       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05023       return -1;
05024    } 
05025    return 0;
05026 }


Variable Documentation

int alarm

Definition at line 1125 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 740 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 751 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 10200 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 process_zap().

char* events[] [static]

Definition at line 1102 of file chan_zap.c.

Referenced by authenticate(), and geteventbyname().

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 1126 of file chan_zap.c.

int num_cadence = 4 [static]

Definition at line 737 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 714 of file chan_zap.c.

Referenced by load_module(), and zt_request().

char show_channel_usage[] [static]

Initial value:

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

Definition at line 10192 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 10188 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 738 of file chan_zap.c.

struct ast_cli_entry zap_cli[] [static]

Definition at line 10211 of file chan_zap.c.

Referenced by __unload_module(), and load_module().

char zap_restart_usage[] [static]

Definition at line 10204 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 10096 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 10196 of file chan_zap.c.

struct ast_channel_tech zap_tech [static]

Definition at line 687 of file chan_zap.c.

Referenced by __unload_module(), load_module(), ss_thread(), and zt_new().


Generated on Mon Mar 31 07:39:46 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1