Tue Nov 4 13:20:34 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"

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, const 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 pri_active_dchan_fd (struct zt_pri *pri)
static int pri_assign_bearer (struct zt_pvt *crv, struct zt_pri *pri, struct zt_pvt *bearer)
static int pri_find_dchan (struct zt_pri *pri)
static int pri_is_up (struct zt_pri *pri)
static int process_zap (struct zt_chan_conf *confp, struct ast_variable *v, int reload, int skipchannels)
static char * redirectingreason2str (int redirectingreason)
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_setlaw (int zfd, int law)
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 155 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)

10,000 ms

Definition at line 284 of file chan_zap.c.

Referenced by zt_callwait().

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

300 ms

Definition at line 283 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 783 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 784 of file chan_zap.c.

Referenced by zt_handle_event(), and zt_new().

#define CHAN_PSEUDO   -2

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

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

500 ms

Definition at line 285 of file chan_zap.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 407 of file chan_zap.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 408 of file chan_zap.c.

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 203 of file chan_zap.c.

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 200 of file chan_zap.c.

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 199 of file chan_zap.c.

#define DCHAN_UP   (1 << 2)

Definition at line 201 of file chan_zap.c.

#define DEFAULT_CIDRINGS   1

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

Definition at line 151 of file chan_zap.c.

Referenced by zt_chan_conf_default().

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

8,000 ms

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

#define HANGUP   1

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

Referenced by ss_thread(), zap_show_channel(), and zt_indicate().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 280 of file chan_zap.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_zap().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 195 of file chan_zap.c.

Referenced by mkintf().

#define MAX_SLAVES   4

Definition at line 410 of file chan_zap.c.

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

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

Referenced by ss_thread(), and zt_new().

#define NUM_CADENCE_MAX   25

Definition at line 758 of file chan_zap.c.

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 194 of file chan_zap.c.

#define NUM_SPANS   32

Definition at line 193 of file chan_zap.c.

#define POLARITY_IDLE   0

Definition at line 365 of file chan_zap.c.

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

#define POLARITY_REV   1

Definition at line 366 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 278 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 1244 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 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_EM   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_EM_E1   ZT_SIG_EM_E1

Definition at line 189 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 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_FEATB   (0x0800000 | 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_FEATD   (0x0200000 | 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   (0x0400000 | 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_FEATDMF_TA   (0x2000000 | 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_CAMA   (0x4000000 | 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_FGC_CAMAMF   (0x8000000 | ZT_SIG_EM)

Definition at line 176 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 181 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 182 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 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_FXSGS   ZT_SIG_FXSGS

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

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

#define SIG_FXSLS   ZT_SIG_FXSLS

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_GR303FXOKS   (0x0100000 | ZT_SIG_FXOKS)

Definition at line 190 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 191 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 183 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 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 SIG_SF_FEATB   (0x0800000 | ZT_SIG_SF)

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_SF_FEATD   (0x0200000 | 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_SF_FEATDMF   (0x0400000 | ZT_SIG_SF)

Definition at line 187 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 185 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 107 of file chan_zap.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 361 of file chan_zap.c.

#define SUB_REAL   0

Active call

Definition at line 360 of file chan_zap.c.

#define SUB_THREEWAY   2

Three-way call

Definition at line 362 of file chan_zap.c.

#define tdesc   "Zapata Telephony"

Definition at line 11631 of file chan_zap.c.

#define TRAILER_MS   5

Referenced by zt_sendtext().

#define TRANSFER   0

Definition at line 10298 of file chan_zap.c.

Referenced by action_transfer(), and zap_fake_event().

#define ZT_EVENT_DTMFDOWN   0

Definition at line 125 of file chan_zap.c.

Referenced by zt_handle_event().

#define ZT_EVENT_DTMFUP   0

Definition at line 126 of file chan_zap.c.

Referenced by zt_handle_event().


Function Documentation

static int __unload_module ( void   )  [static]

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

10481 {
10482    int x;
10483    struct zt_pvt *p, *pl;
10484 
10485 #ifdef HAVE_PRI
10486    int i;
10487    for (i = 0; i < NUM_SPANS; i++) {
10488       if (pris[i].master != AST_PTHREADT_NULL) 
10489          pthread_cancel(pris[i].master);
10490    }
10491    ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
10492    ast_unregister_application(zap_send_keypad_facility_app);
10493 #endif
10494    ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
10495    ast_manager_unregister( "ZapDialOffhook" );
10496    ast_manager_unregister( "ZapHangup" );
10497    ast_manager_unregister( "ZapTransfer" );
10498    ast_manager_unregister( "ZapDNDoff" );
10499    ast_manager_unregister( "ZapDNDon" );
10500    ast_manager_unregister("ZapShowChannels");
10501    ast_manager_unregister("ZapRestart");
10502    ast_channel_unregister(&zap_tech);
10503    ast_mutex_lock(&iflock);
10504    /* Hangup all interfaces if they have an owner */
10505    p = iflist;
10506    while (p) {
10507       if (p->owner)
10508          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10509       p = p->next;
10510    }
10511    ast_mutex_unlock(&iflock);
10512    ast_mutex_lock(&monlock);
10513    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10514       pthread_cancel(monitor_thread);
10515       pthread_kill(monitor_thread, SIGURG);
10516       pthread_join(monitor_thread, NULL);
10517    }
10518    monitor_thread = AST_PTHREADT_STOP;
10519    ast_mutex_unlock(&monlock);
10520 
10521    ast_mutex_lock(&iflock);
10522    /* Destroy all the interfaces and free their memory */
10523    p = iflist;
10524    while (p) {
10525       /* Free any callerid */
10526       if (p->cidspill)
10527          free(p->cidspill);
10528       /* Close the zapata thingy */
10529       if (p->subs[SUB_REAL].zfd > -1)
10530          zt_close(p->subs[SUB_REAL].zfd);
10531       pl = p;
10532       p = p->next;
10533       x = pl->channel;
10534       /* Free associated memory */
10535       if (pl)
10536          destroy_zt_pvt(&pl);
10537       ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10538    }
10539    iflist = NULL;
10540    ifcount = 0;
10541    ast_mutex_unlock(&iflock);
10542 #ifdef HAVE_PRI      
10543    for (i = 0; i < NUM_SPANS; i++) {
10544       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10545          pthread_join(pris[i].master, NULL);
10546       zt_close(pris[i].fds[i]);
10547    }
10548 #endif
10549    return 0;
10550 }

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

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

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

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

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

10368 {
10369    struct zt_pvt *p = NULL;
10370    const char *channel = astman_get_header(m, "ZapChannel");
10371 
10372    if (ast_strlen_zero(channel)) {
10373       astman_send_error(s, m, "No channel specified");
10374       return 0;
10375    }
10376    p = find_channel(atoi(channel));
10377    if (!p) {
10378       astman_send_error(s, m, "No such channel");
10379       return 0;
10380    }
10381    zap_fake_event(p,TRANSFER);
10382    astman_send_ack(s, m, "ZapTransfer");
10383    return 0;
10384 }

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

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

10387 {
10388    struct zt_pvt *p = NULL;
10389    const char *channel = astman_get_header(m, "ZapChannel");
10390 
10391    if (ast_strlen_zero(channel)) {
10392       astman_send_error(s, m, "No channel specified");
10393       return 0;
10394    }
10395    p = find_channel(atoi(channel));
10396    if (!p) {
10397       astman_send_error(s, m, "No such channel");
10398       return 0;
10399    }
10400    zap_fake_event(p,HANGUP);
10401    astman_send_ack(s, m, "ZapHangup");
10402    return 0;
10403 }

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

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

10406 {
10407    struct zt_pvt *p = NULL;
10408    const char *channel = astman_get_header(m, "ZapChannel");
10409    const char *number = astman_get_header(m, "Number");
10410    int i;
10411 
10412    if (ast_strlen_zero(channel)) {
10413       astman_send_error(s, m, "No channel specified");
10414       return 0;
10415    }
10416    if (ast_strlen_zero(number)) {
10417       astman_send_error(s, m, "No number specified");
10418       return 0;
10419    }
10420    p = find_channel(atoi(channel));
10421    if (!p) {
10422       astman_send_error(s, m, "No such channel");
10423       return 0;
10424    }
10425    if (!p->owner) {
10426       astman_send_error(s, m, "Channel does not have it's owner");
10427       return 0;
10428    }
10429    for (i = 0; i < strlen(number); i++) {
10430       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10431       zap_queue_frame(p, &f, NULL); 
10432    }
10433    astman_send_ack(s, m, "ZapDialOffhook");
10434    return 0;
10435 }

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

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

10349 {
10350    struct zt_pvt *p = NULL;
10351    const char *channel = astman_get_header(m, "ZapChannel");
10352 
10353    if (ast_strlen_zero(channel)) {
10354       astman_send_error(s, m, "No channel specified");
10355       return 0;
10356    }
10357    p = find_channel(atoi(channel));
10358    if (!p) {
10359       astman_send_error(s, m, "No such channel");
10360       return 0;
10361    }
10362    p->dnd = 0;
10363    astman_send_ack(s, m, "DND Disabled");
10364    return 0;
10365 }

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

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

10330 {
10331    struct zt_pvt *p = NULL;
10332    const char *channel = astman_get_header(m, "ZapChannel");
10333 
10334    if (ast_strlen_zero(channel)) {
10335       astman_send_error(s, m, "No channel specified");
10336       return 0;
10337    }
10338    p = find_channel(atoi(channel));
10339    if (!p) {
10340       astman_send_error(s, m, "No such channel");
10341       return 0;
10342    }
10343    p->dnd = 1;
10344    astman_send_ack(s, m, "DND Enabled");
10345    return 0;
10346 }

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

Definition at line 9937 of file chan_zap.c.

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

Referenced by load_module().

09938 {
09939    if (zap_restart() != 0) {
09940       astman_send_error(s, m, "Failed rereading zaptel configuration");
09941       return 1;
09942    }
09943    astman_send_ack(s, m, "ZapRestart: Success");
09944    return 0;
09945 }

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

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

10438 {
10439    struct zt_pvt *tmp = NULL;
10440    const char *id = astman_get_header(m, "ActionID");
10441    char idText[256] = "";
10442 
10443    astman_send_ack(s, m, "Zapata channel status will follow");
10444    if (!ast_strlen_zero(id))
10445       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10446 
10447    ast_mutex_lock(&iflock);
10448    
10449    tmp = iflist;
10450    while (tmp) {
10451       if (tmp->channel > 0) {
10452          int alarm = get_alarms(tmp);
10453          astman_append(s,
10454             "Event: ZapShowChannels\r\n"
10455             "Channel: %d\r\n"
10456             "Signalling: %s\r\n"
10457             "Context: %s\r\n"
10458             "DND: %s\r\n"
10459             "Alarm: %s\r\n"
10460             "%s"
10461             "\r\n",
10462             tmp->channel, sig2str(tmp->sig), tmp->context, 
10463             tmp->dnd ? "Enabled" : "Disabled",
10464             alarm2str(alarm), idText);
10465       } 
10466 
10467       tmp = tmp->next;
10468    }
10469 
10470    ast_mutex_unlock(&iflock);
10471    
10472    astman_append(s, 
10473       "Event: ZapShowChannelsComplete\r\n"
10474       "%s"
10475       "\r\n", 
10476       idText);
10477    return 0;
10478 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1155 of file chan_zap.c.

References alarms, and name.

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

01156 {
01157    int x;
01158    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01159       if (alarms[x].alarm & alarm)
01160          return alarms[x].name;
01161    }
01162    return alarm ? "Unknown Alarm" : "No Alarm";
01163 }

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

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

00954 {
00955    ZT_BUFFERINFO bi;
00956    int res;
00957    if (p->subs[x].zfd < 0) {
00958       p->subs[x].zfd = zt_open("/dev/zap/pseudo");
00959       if (p->subs[x].zfd > -1) {
00960          res = ioctl(p->subs[x].zfd, ZT_GET_BUFINFO, &bi);
00961          if (!res) {
00962             bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
00963             bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
00964             bi.numbufs = numbufs;
00965             res = ioctl(p->subs[x].zfd, ZT_SET_BUFINFO, &bi);
00966             if (res < 0) {
00967                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", x);
00968             }
00969          } else 
00970             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", x);
00971          if (ioctl(p->subs[x].zfd, ZT_CHANNO, &p->subs[x].chan) == 1) {
00972             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d\n", p->subs[x].zfd);
00973             zt_close(p->subs[x].zfd);
00974             p->subs[x].zfd = -1;
00975             return -1;
00976          }
00977          if (option_debug)
00978             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
00979          return 0;
00980       } else
00981          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
00982       return -1;
00983    }
00984    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
00985    return -1;
00986 }

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 3513 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.

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

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

Definition at line 7645 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, LOG_DEBUG, zt_pvt::oprmode, zt_pvt::outgoing, 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, and zt_pvt::subs.

Referenced by zt_request().

07646 {
07647    int res;
07648    ZT_PARAMS par;
07649 
07650    /* First, check group matching */
07651    if (groupmatch) {
07652       if ((p->group & groupmatch) != groupmatch)
07653          return 0;
07654       *groupmatched = 1;
07655    }
07656    /* Check to see if we have a channel match */
07657    if (channelmatch != -1) {
07658       if (p->channel != channelmatch)
07659          return 0;
07660       *channelmatched = 1;
07661    }
07662    /* We're at least busy at this point */
07663    if (busy) {
07664       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07665          *busy = 1;
07666    }
07667    /* If do not disturb, definitely not */
07668    if (p->dnd)
07669       return 0;
07670    /* If guard time, definitely not */
07671    if (p->guardtime && (time(NULL) < p->guardtime)) 
07672       return 0;
07673       
07674    /* If no owner definitely available */
07675    if (!p->owner) {
07676 #ifdef HAVE_PRI
07677       /* Trust PRI */
07678       if (p->pri) {
07679          if (p->resetting || p->call)
07680             return 0;
07681          else
07682             return 1;
07683       }
07684 #endif
07685       if (!(p->radio || (p->oprmode < 0)))
07686       {
07687          if (!p->sig || (p->sig == SIG_FXSLS))
07688             return 1;
07689          /* Check hook state */
07690          if (p->subs[SUB_REAL].zfd > -1)
07691             res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
07692          else {
07693             /* Assume not off hook on CVRS */
07694             res = 0;
07695             par.rxisoffhook = 0;
07696          }
07697          if (res) {
07698             ast_log(LOG_WARNING, "Unable to check hook state on channel %d\n", p->channel);
07699          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07700             /* When "onhook" that means no battery on the line, and thus
07701               it is out of service..., if it's on a TDM card... If it's a channel
07702               bank, there is no telling... */
07703             if (par.rxbits > -1)
07704                return 1;
07705             if (par.rxisoffhook)
07706                return 1;
07707             else
07708 #ifdef ZAP_CHECK_HOOKSTATE
07709                return 0;
07710 #else
07711                return 1;
07712 #endif
07713          } else if (par.rxisoffhook) {
07714             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07715             /* Not available when the other end is off hook */
07716             return 0;
07717          }
07718       }
07719       return 1;
07720    }
07721 
07722    /* If it's not an FXO, forget about call wait */
07723    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
07724       return 0;
07725 
07726    if (!p->callwaiting) {
07727       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
07728       return 0;
07729    }
07730 
07731    if (p->subs[SUB_CALLWAIT].zfd > -1) {
07732       /* If there is already a call waiting call, then we can't take a second one */
07733       return 0;
07734    }
07735    
07736    if ((p->owner->_state != AST_STATE_UP) &&
07737        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07738       /* If the current call is not up, then don't allow the call */
07739       return 0;
07740    }
07741    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07742       /* Can't take a call wait when the three way calling hasn't been merged yet. */
07743       return 0;
07744    }
07745    /* We're cool */
07746    return 1;
07747 }

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 10562 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().

10563 {
10564    char *c, *chan;
10565    int x, start, finish;
10566    struct zt_pvt *tmp;
10567 #ifdef HAVE_PRI
10568    struct zt_pri *pri;
10569    int trunkgroup, y;
10570 #endif
10571    
10572    if ((reload == 0) && (conf->chan.sig < 0)) {
10573       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10574       return -1;
10575    }
10576 
10577    c = ast_strdupa(value);
10578 
10579 #ifdef HAVE_PRI
10580    pri = NULL;
10581    if (iscrv) {
10582       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10583          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10584          return -1;
10585       }
10586       if (trunkgroup < 1) {
10587          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10588          return -1;
10589       }
10590       c += y;
10591       for (y = 0; y < NUM_SPANS; y++) {
10592          if (pris[y].trunkgroup == trunkgroup) {
10593             pri = pris + y;
10594             break;
10595          }
10596       }
10597       if (!pri) {
10598          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10599          return -1;
10600       }
10601    }
10602 #endif         
10603 
10604    while ((chan = strsep(&c, ","))) {
10605       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10606          /* Range */
10607       } else if (sscanf(chan, "%d", &start)) {
10608          /* Just one */
10609          finish = start;
10610       } else if (!strcasecmp(chan, "pseudo")) {
10611          finish = start = CHAN_PSEUDO;
10612          if (found_pseudo)
10613             *found_pseudo = 1;
10614       } else {
10615          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10616          return -1;
10617       }
10618       if (finish < start) {
10619          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10620          x = finish;
10621          finish = start;
10622          start = x;
10623       }
10624 
10625       for (x = start; x <= finish; x++) {
10626 #ifdef HAVE_PRI
10627          tmp = mkintf(x, conf, pri, reload);
10628 #else       
10629          tmp = mkintf(x, conf, NULL, reload);
10630 #endif         
10631 
10632          if (tmp) {
10633             if (option_verbose > 2) {
10634 #ifdef HAVE_PRI
10635                if (pri)
10636                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10637                else
10638 #endif
10639                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10640             }
10641          } else {
10642             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10643                (reload == 1) ? "reconfigure" : "register", value);
10644             return -1;
10645          }
10646       }
10647    }
10648 
10649    return 0;
10650 }

static int bump_gains ( struct zt_pvt p  )  [static]

Definition at line 1606 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, and zt_pvt::txgain.

Referenced by ss_thread().

01607 {
01608    int res;
01609 
01610    /* Bump receive gain by 5.0db */
01611    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01612    if (res) {
01613       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01614       return -1;
01615    }
01616 
01617    return 0;
01618 }

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

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

07750 {
07751    struct zt_pvt *p;
07752    ZT_BUFFERINFO bi;
07753    int res;
07754    
07755    if ((p = ast_malloc(sizeof(*p)))) {
07756       memcpy(p, src, sizeof(struct zt_pvt));
07757       ast_mutex_init(&p->lock);
07758       p->subs[SUB_REAL].zfd = zt_open("/dev/zap/pseudo");
07759       /* Allocate a zapata structure */
07760       if (p->subs[SUB_REAL].zfd < 0) {
07761          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
07762          destroy_zt_pvt(&p);
07763          return NULL;
07764       }
07765       res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
07766       if (!res) {
07767          bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
07768          bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
07769          bi.numbufs = numbufs;
07770          res = ioctl(p->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
07771          if (res < 0) {
07772             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel\n");
07773          }
07774       } else
07775          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel\n");
07776    }
07777    p->destroy = 1;
07778    p->next = iflist;
07779    p->prev = NULL;
07780    iflist = p;
07781    if (iflist->next)
07782       iflist->next->prev = p;
07783    return p;
07784 }

static int check_for_conference ( struct zt_pvt p  )  [static]

Definition at line 3589 of file chan_zap.c.

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

Referenced by zt_handle_event().

03590 {
03591    ZT_CONFINFO ci;
03592    /* Fine if we already have a master, etc */
03593    if (p->master || (p->confno > -1))
03594       return 0;
03595    memset(&ci, 0, sizeof(ci));
03596    if (ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
03597       ast_log(LOG_WARNING, "Failed to get conference info on channel %d\n", p->channel);
03598       return 0;
03599    }
03600    /* If we have no master and don't have a confno, then 
03601       if we're in a conference, it's probably a MeetMe room or
03602       some such, so don't let us 3-way out! */
03603    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03604       if (option_verbose > 2) 
03605          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03606       return 1;
03607    }
03608    return 0;
03609 }

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

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

01247 {
01248    /* If the conference already exists, and we're already in it
01249       don't bother doing anything */
01250    ZT_CONFINFO zi;
01251    
01252    memset(&zi, 0, sizeof(zi));
01253    zi.chan = 0;
01254 
01255    if (slavechannel > 0) {
01256       /* If we have only one slave, do a digital mon */
01257       zi.confmode = ZT_CONF_DIGITALMON;
01258       zi.confno = slavechannel;
01259    } else {
01260       if (!index) {
01261          /* Real-side and pseudo-side both participate in conference */
01262          zi.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER |
01263             ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
01264       } else
01265          zi.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
01266       zi.confno = p->confno;
01267    }
01268    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01269       return 0;
01270    if (c->zfd < 0)
01271       return 0;
01272    if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
01273       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d\n", c->zfd, zi.confmode, zi.confno);
01274       return -1;
01275    }
01276    if (slavechannel < 1) {
01277       p->confno = zi.confno;
01278    }
01279    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01280    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01281    return 0;
01282 }

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

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

01296 {
01297    ZT_CONFINFO zi;
01298    if (/* Can't delete if there's no zfd */
01299       (c->zfd < 0) ||
01300       /* Don't delete from the conference if it's not our conference */
01301       !isourconf(p, c)
01302       /* Don't delete if we don't think it's conferenced at all (implied) */
01303       ) return 0;
01304    memset(&zi, 0, sizeof(zi));
01305    zi.chan = 0;
01306    zi.confno = 0;
01307    zi.confmode = 0;
01308    if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
01309       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01310       return -1;
01311    }
01312    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01313    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01314    return 0;
01315 }

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

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

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

02248 {
02249    int owned = 0;
02250    int i = 0;
02251 
02252    if (!now) {
02253       if (cur->owner) {
02254          owned = 1;
02255       }
02256 
02257       for (i = 0; i < 3; i++) {
02258          if (cur->subs[i].owner) {
02259             owned = 1;
02260          }
02261       }
02262       if (!owned) {
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    } else {
02282       if (prev) {
02283          prev->next = cur->next;
02284          if (prev->next)
02285             prev->next->prev = prev;
02286          else
02287             ifend = prev;
02288       } else {
02289          iflist = cur->next;
02290          if (iflist)
02291             iflist->prev = NULL;
02292          else
02293             ifend = NULL;
02294       }
02295       if (cur->subs[SUB_REAL].zfd > -1) {
02296          zt_close(cur->subs[SUB_REAL].zfd);
02297       }
02298       destroy_zt_pvt(&cur);
02299    }
02300    return 0;
02301 }

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

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

02233 {
02234    struct zt_pvt *p = *pvt;
02235    /* Remove channel from the list */
02236    if (p->prev)
02237       p->prev->next = p->next;
02238    if (p->next)
02239       p->next->prev = p->prev;
02240    if (p->use_smdi)
02241       ast_smdi_interface_unref(p->smdi_iface);
02242    ast_mutex_destroy(&p->lock);
02243    free(p);
02244    *pvt = NULL;
02245 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1008 of file chan_zap.c.

Referenced by zt_digit_begin().

01009 {
01010    if (isdigit(digit))
01011       return ZT_TONE_DTMF_BASE + (digit - '0');
01012    else if (digit >= 'A' && digit <= 'D')
01013       return ZT_TONE_DTMF_A + (digit - 'A');
01014    else if (digit >= 'a' && digit <= 'd')
01015       return ZT_TONE_DTMF_A + (digit - 'a');
01016    else if (digit == '*')
01017       return ZT_TONE_DTMF_s;
01018    else if (digit == '#')
01019       return ZT_TONE_DTMF_p;
01020    else
01021       return -1;
01022 }

static void disable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3127 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, and zt_pvt::subs.

Referenced by zt_bridge().

03128 {
03129 #ifdef ZT_TONEDETECT
03130    int val;
03131 #endif
03132 
03133    p->ignoredtmf = 1;
03134 
03135 #ifdef ZT_TONEDETECT
03136    val = 0;
03137    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03138 #endif      
03139    if (!p->hardwaredtmf && p->dsp) {
03140       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03141       ast_dsp_set_features(p->dsp, p->dsp_features);
03142    }
03143 }

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

Definition at line 6837 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_pvt::owner, POLLIN, POLLPRI, zt_pvt::radio, pollfd::revents, zt_pvt::sig, SUB_REAL, and zt_pvt::subs.

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

static void enable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3145 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, and zt_pvt::subs.

Referenced by zt_bridge().

03146 {
03147 #ifdef ZT_TONEDETECT
03148    int val;
03149 #endif
03150 
03151    if (p->channel == CHAN_PSEUDO)
03152       return;
03153 
03154    p->ignoredtmf = 0;
03155 
03156 #ifdef ZT_TONEDETECT
03157    val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
03158    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03159 #endif      
03160    if (!p->hardwaredtmf && p->dsp) {
03161       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03162       ast_dsp_set_features(p->dsp, p->dsp_features);
03163    }
03164 }

static char* event2str ( int  event  )  [static]

Definition at line 1165 of file chan_zap.c.

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

01166 {
01167    static char buf[256];
01168    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01169       return events[event];
01170    sprintf(buf, "Event %d", event); /* safe */
01171    return buf;
01172 }

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

Definition at line 1530 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

01531 {
01532    int j;
01533    int k;
01534    float linear_gain = pow(10.0, gain / 20.0);
01535 
01536    switch (law) {
01537    case ZT_LAW_ALAW:
01538       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01539          if (gain) {
01540             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01541             if (k > 32767) k = 32767;
01542             if (k < -32767) k = -32767;
01543             g->rxgain[j] = AST_LIN2A(k);
01544          } else {
01545             g->rxgain[j] = j;
01546          }
01547       }
01548       break;
01549    case ZT_LAW_MULAW:
01550       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01551          if (gain) {
01552             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01553             if (k > 32767) k = 32767;
01554             if (k < -32767) k = -32767;
01555             g->rxgain[j] = AST_LIN2MU(k);
01556          } else {
01557             g->rxgain[j] = j;
01558          }
01559       }
01560       break;
01561    }
01562 }

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

Definition at line 1496 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

01497 {
01498    int j;
01499    int k;
01500    float linear_gain = pow(10.0, gain / 20.0);
01501 
01502    switch (law) {
01503    case ZT_LAW_ALAW:
01504       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01505          if (gain) {
01506             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01507             if (k > 32767) k = 32767;
01508             if (k < -32767) k = -32767;
01509             g->txgain[j] = AST_LIN2A(k);
01510          } else {
01511             g->txgain[j] = j;
01512          }
01513       }
01514       break;
01515    case ZT_LAW_MULAW:
01516       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01517          if (gain) {
01518             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01519             if (k > 32767) k = 32767;
01520             if (k < -32767) k = -32767;
01521             g->txgain[j] = AST_LIN2MU(k);
01522          } else {
01523             g->txgain[j] = j;
01524          }
01525       }
01526       break;
01527    }
01528 }

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

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

10318 {
10319    struct zt_pvt *p = iflist;
10320    while (p) {
10321       if (p->channel == channel) {
10322          break;
10323       }
10324       p = p->next;
10325    }
10326    return p;
10327 }

static int get_alarms ( struct zt_pvt p  )  [static]

Definition at line 3611 of file chan_zap.c.

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

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

03612 {
03613    int res;
03614    ZT_SPANINFO zi;
03615    memset(&zi, 0, sizeof(zi));
03616    zi.spanno = p->span;
03617    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SPANSTAT, &zi);
03618    if (res < 0) {
03619       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03620       return 0;
03621    }
03622    return zi.alarms;
03623 }

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

Definition at line 6612 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_disable_ec(), zt_enable_ec(), zt_new(), and zt_set_hook().

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

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

Definition at line 10161 of file chan_zap.c.

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

10162 {
10163    int i, j;
10164    for (i = 0; i < num_cadence; i++) {
10165       char output[1024];
10166       char tmp[16], tmp2[64];
10167       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10168       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10169 
10170       for (j = 0; j < 16; j++) {
10171          if (cadences[i].ringcadence[j] == 0)
10172             break;
10173          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10174          if (cidrings[i] * 2 - 1 == j)
10175             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10176          else
10177             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10178          if (j != 0)
10179             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10180          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10181       }
10182       ast_cli(fd,"%s\n",output);
10183    }
10184    return 0;
10185 }

static int has_voicemail ( struct zt_pvt p  )  [static]

Definition at line 1725 of file chan_zap.c.

References ast_app_has_voicemail(), and zt_pvt::mailbox.

01726 {
01727 
01728    return ast_app_has_voicemail(p->mailbox, NULL);
01729 }

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

Definition at line 1284 of file chan_zap.c.

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

Referenced by conf_del().

01285 {
01286    /* If they're listening to our channel, they're ours */  
01287    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == ZT_CONF_DIGITALMON))
01288       return 1;
01289    /* If they're a talker on our (allocated) conference, they're ours */
01290    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & ZT_CONF_TALKER))
01291       return 1;
01292    return 0;
01293 }

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

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

01318 {
01319    int x;
01320    int useslavenative;
01321    struct zt_pvt *slave = NULL;
01322    /* Start out optimistic */
01323    useslavenative = 1;
01324    /* Update conference state in a stateless fashion */
01325    for (x = 0; x < 3; x++) {
01326       /* Any three-way calling makes slave native mode *definitely* out
01327          of the question */
01328       if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway)
01329          useslavenative = 0;
01330    }
01331    /* If we don't have any 3-way calls, check to see if we have
01332       precisely one slave */
01333    if (useslavenative) {
01334       for (x = 0; x < MAX_SLAVES; x++) {
01335          if (p->slaves[x]) {
01336             if (slave) {
01337                /* Whoops already have a slave!  No 
01338                   slave native and stop right away */
01339                slave = NULL;
01340                useslavenative = 0;
01341                break;
01342             } else {
01343                /* We have one slave so far */
01344                slave = p->slaves[x];
01345             }
01346          }
01347       }
01348    }
01349    /* If no slave, slave native definitely out */
01350    if (!slave)
01351       useslavenative = 0;
01352    else if (slave->law != p->law) {
01353       useslavenative = 0;
01354       slave = NULL;
01355    }
01356    if (out)
01357       *out = slave;
01358    return useslavenative;
01359 }

static int load_module ( void   )  [static]

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

11465 {
11466    int res;
11467 
11468 #ifdef HAVE_PRI
11469    int y,i;
11470    memset(pris, 0, sizeof(pris));
11471    for (y = 0; y < NUM_SPANS; y++) {
11472       ast_mutex_init(&pris[y].lock);
11473       pris[y].offset = -1;
11474       pris[y].master = AST_PTHREADT_NULL;
11475       for (i = 0; i < NUM_DCHANS; i++)
11476          pris[y].fds[i] = -1;
11477    }
11478    pri_set_error(zt_pri_error);
11479    pri_set_message(zt_pri_message);
11480    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11481          zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11482 #endif
11483    res = setup_zap(0);
11484    /* Make sure we can register our Zap channel type */
11485    if (res)
11486       return AST_MODULE_LOAD_DECLINE;
11487    if (ast_channel_register(&zap_tech)) {
11488       ast_log(LOG_ERROR, "Unable to register channel class 'Zap'\n");
11489       __unload_module();
11490       return -1;
11491    }
11492 #ifdef HAVE_PRI
11493    ast_string_field_init(&inuse, 16);
11494    ast_string_field_set(&inuse, name, "GR-303InUse");
11495    ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
11496 #endif   
11497    ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
11498    
11499    memset(round_robin, 0, sizeof(round_robin));
11500    ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
11501    ast_manager_register( "ZapHangup", 0, action_transferhangup, "Hangup Zap Channel" );
11502    ast_manager_register( "ZapDialOffhook", 0, action_zapdialoffhook, "Dial over Zap channel while offhook" );
11503    ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
11504    ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
11505    ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
11506    ast_manager_register("ZapRestart", 0, action_zaprestart, "Fully Restart zaptel channels (terminates calls)");
11507 
11508    return res;
11509 }

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

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

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

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

Definition at line 5409 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

05410 {
05411    char c;
05412 
05413    *str = 0; /* start with empty output buffer */
05414    for (;;)
05415    {
05416       /* Wait for the first digit (up to specified ms). */
05417       c = ast_waitfordigit(chan, ms);
05418       /* if timeout, hangup or error, return as such */
05419       if (c < 1)
05420          return c;
05421       *str++ = c;
05422       *str = 0;
05423       if (strchr(term, c))
05424          return 1;
05425    }
05426 }

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

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

04938 {
04939    int sent=0;
04940    int size;
04941    int res;
04942    int fd;
04943    fd = p->subs[index].zfd;
04944    while (len) {
04945       size = len;
04946       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
04947          size = (linear ? READ_SIZE * 2 : READ_SIZE);
04948       res = write(fd, buf, size);
04949       if (res != size) {
04950          if (option_debug)
04951             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04952          return sent;
04953       }
04954       len -= size;
04955       buf += size;
04956    }
04957    return sent;
04958 }

static int pri_active_dchan_fd ( struct zt_pri *  pri  )  [inline, static]

static int pri_assign_bearer ( struct zt_pvt crv,
struct zt_pri *  pri,
struct zt_pvt bearer 
) [inline, static]

Referenced by zt_request().

static int pri_find_dchan ( struct zt_pri *  pri  )  [static]

static int pri_is_up ( struct zt_pri *  pri  )  [inline, static]

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

Definition at line 10655 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::busycompare, zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::busyfuzziness, zt_pvt::busyquietlength, zt_pvt::busytonelength, 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_pvt::silencethreshold, 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().

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

static char* redirectingreason2str ( int  redirectingreason  )  [static]

static int reload ( void   )  [static]

Definition at line 11612 of file chan_zap.c.

References ast_log(), and setup_zap().

11613 {
11614    int res = 0;
11615 
11616    res = setup_zap(1);
11617    if (res) {
11618       ast_log(LOG_WARNING, "Reload of chan_zap.so is unsuccessful!\n");
11619       return -1;
11620    }
11621    return 0;
11622 }

static int reset_conf ( struct zt_pvt p  )  [static]

Definition at line 1361 of file chan_zap.c.

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

Referenced by zt_hangup().

01362 {
01363    ZT_CONFINFO zi;
01364    memset(&zi, 0, sizeof(zi));
01365    p->confno = -1;
01366    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01367    if (p->subs[SUB_REAL].zfd > -1) {
01368       if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &zi))
01369          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d!\n", p->channel);
01370    }
01371    return 0;
01372 }

static int restart_monitor ( void   )  [static]

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

07025 {
07026    pthread_attr_t attr;
07027    pthread_attr_init(&attr);
07028    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07029    /* If we're supposed to be stopped -- stay stopped */
07030    if (monitor_thread == AST_PTHREADT_STOP)
07031       return 0;
07032    ast_mutex_lock(&monlock);
07033    if (monitor_thread == pthread_self()) {
07034       ast_mutex_unlock(&monlock);
07035       ast_log(LOG_WARNING, "Cannot kill myself\n");
07036       return -1;
07037    }
07038    if (monitor_thread != AST_PTHREADT_NULL) {
07039       /* Wake up the thread */
07040       pthread_kill(monitor_thread, SIGURG);
07041    } else {
07042       /* Start a new monitor */
07043       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07044          ast_mutex_unlock(&monlock);
07045          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07046          pthread_attr_destroy(&attr);
07047          return -1;
07048       }
07049    }
07050    ast_mutex_unlock(&monlock);
07051    pthread_attr_destroy(&attr);
07052    return 0;
07053 }

static int restore_conference ( struct zt_pvt p  )  [static]

Definition at line 1693 of file chan_zap.c.

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

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

01694 {
01695    int res;
01696    if (p->saveconf.confmode) {
01697       res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &p->saveconf);
01698       p->saveconf.confmode = 0;
01699       if (res) {
01700          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01701          return -1;
01702       }
01703    }
01704    if (option_debug)
01705       ast_log(LOG_DEBUG, "Restored conferencing\n");
01706    return 0;
01707 }

static int restore_gains ( struct zt_pvt p  )  [static]

Definition at line 1620 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, and zt_pvt::txgain.

Referenced by ss_thread(), and zt_hangup().

01621 {
01622    int res;
01623 
01624    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
01625    if (res) {
01626       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01627       return -1;
01628    }
01629 
01630    return 0;
01631 }

static int save_conference ( struct zt_pvt p  )  [static]

Definition at line 1665 of file chan_zap.c.

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

Referenced by zt_callwait(), and zt_handle_event().

01666 {
01667    struct zt_confinfo c;
01668    int res;
01669    if (p->saveconf.confmode) {
01670       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01671       return -1;
01672    }
01673    p->saveconf.chan = 0;
01674    res = ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &p->saveconf);
01675    if (res) {
01676       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01677       p->saveconf.confmode = 0;
01678       return -1;
01679    }
01680    c.chan = 0;
01681    c.confno = 0;
01682    c.confmode = ZT_CONF_NORMAL;
01683    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &c);
01684    if (res) {
01685       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01686       return -1;
01687    }
01688    if (option_debug)
01689       ast_log(LOG_DEBUG, "Disabled conferencing\n");
01690    return 0;
01691 }

static int send_callerid ( struct zt_pvt p  )  [static]

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

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

01732 {
01733    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
01734    int res;
01735    /* Take out of linear mode if necessary */
01736    if (p->subs[SUB_REAL].linear) {
01737       p->subs[SUB_REAL].linear = 0;
01738       zt_setlinear(p->subs[SUB_REAL].zfd, 0);
01739    }
01740    while (p->cidpos < p->cidlen) {
01741       res = write(p->subs[SUB_REAL].zfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01742       if (res < 0) {
01743          if (errno == EAGAIN)
01744             return 0;
01745          else {
01746             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01747             return -1;
01748          }
01749       }
01750       if (!res)
01751          return 0;
01752       p->cidpos += res;
01753    }
01754    free(p->cidspill);
01755    p->cidspill = NULL;
01756    if (p->callwaitcas) {
01757       /* Wait for CID/CW to expire */
01758       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01759    } else
01760       restore_conference(p);
01761    return 0;
01762 }

static int send_cwcidspill ( struct zt_pvt p  )  [static]

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

01710 {
01711    p->callwaitcas = 0;
01712    p->cidcwexpire = 0;
01713    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01714       return -1;
01715    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01716    /* Make sure we account for the end */
01717    p->cidlen += READ_SIZE * 4;
01718    p->cidpos = 0;
01719    send_callerid(p);
01720    if (option_verbose > 2)
01721       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01722    return 0;
01723 }

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

Definition at line 1601 of file chan_zap.c.

References set_actual_rxgain(), and set_actual_txgain().

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

01602 {
01603    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01604 }

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

Definition at line 1583 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

01584 {
01585    struct zt_gains g;
01586    int res;
01587 
01588    memset(&g, 0, sizeof(g));
01589    g.chan = chan;
01590    res = ioctl(fd, ZT_GETGAINS, &g);
01591    if (res) {
01592       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01593       return res;
01594    }
01595 
01596    fill_rxgain(&g, gain, law);
01597 
01598    return ioctl(fd, ZT_SETGAINS, &g);
01599 }

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

Definition at line 1564 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

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

static int setup_zap ( int  reload  )  [static]

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

11333 {
11334    struct ast_config *cfg;
11335    struct ast_variable *v;
11336    struct zt_chan_conf conf = zt_chan_conf_default();
11337    int res;
11338 
11339 #ifdef HAVE_PRI
11340    char *c;
11341    int spanno;
11342    int i, x;
11343    int logicalspan;
11344    int trunkgroup;
11345    int dchannels[NUM_DCHANS];
11346 #endif
11347 
11348    cfg = ast_config_load(config);
11349 
11350    /* Error if we have no config file */
11351    if (!cfg) {
11352       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
11353       return 0;
11354    }
11355 
11356    /* It's a little silly to lock it, but we mind as well just to be sure */
11357    ast_mutex_lock(&iflock);
11358 #ifdef HAVE_PRI
11359    if (!reload) {
11360       /* Process trunkgroups first */
11361       v = ast_variable_browse(cfg, "trunkgroups");
11362       while (v) {
11363          if (!strcasecmp(v->name, "trunkgroup")) {
11364             trunkgroup = atoi(v->value);
11365             if (trunkgroup > 0) {
11366                if ((c = strchr(v->value, ','))) {
11367                   i = 0;
11368                   memset(dchannels, 0, sizeof(dchannels));
11369                   while (c && (i < NUM_DCHANS)) {
11370                      dchannels[i] = atoi(c + 1);
11371                      if (dchannels[i] < 0) {
11372                         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);
11373                      } else
11374                         i++;
11375                      c = strchr(c + 1, ',');
11376                   }
11377                   if (i) {
11378                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11379                         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);
11380                      } else if (option_verbose > 1)
11381                         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");
11382                   } else
11383                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
11384                } else
11385                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
11386             } else
11387                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
11388          } else if (!strcasecmp(v->name, "spanmap")) {
11389             spanno = atoi(v->value);
11390             if (spanno > 0) {
11391                if ((c = strchr(v->value, ','))) {
11392                   trunkgroup = atoi(c + 1);
11393                   if (trunkgroup > 0) {
11394                      if ((c = strchr(c + 1, ','))) 
11395                         logicalspan = atoi(c + 1);
11396                      else
11397                         logicalspan = 0;
11398                      if (logicalspan >= 0) {
11399                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11400                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11401                         } else if (option_verbose > 1) 
11402                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11403                      } else
11404                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
11405                   } else
11406                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
11407                } else
11408                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
11409             } else
11410                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
11411          } else {
11412             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11413          }
11414          v = v->next;
11415       }
11416    }
11417 #endif
11418    
11419    /* Copy the default jb config over global_jbconf */
11420    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11421 
11422    v = ast_variable_browse(cfg, "channels");
11423    res = process_zap(&conf, v, reload, 0);
11424    ast_mutex_unlock(&iflock);
11425    ast_config_destroy(cfg);
11426    if (res)
11427       return res;
11428    cfg = ast_config_load("users.conf");
11429    if (cfg) {
11430       char *cat;
11431       const char *chans;
11432       process_zap(&conf, ast_variable_browse(cfg, "general"), 1, 1);
11433       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11434          if (!strcasecmp(cat, "general"))
11435             continue;
11436          chans = ast_variable_retrieve(cfg, cat, "zapchan");
11437          if (!ast_strlen_zero(chans)) {
11438             struct zt_chan_conf sect_conf;
11439             memcpy(&sect_conf, &conf, sizeof(sect_conf));
11440 
11441             process_zap(&sect_conf, ast_variable_browse(cfg, cat), reload, 0);
11442          }
11443       }
11444       ast_config_destroy(cfg);
11445    }
11446 #ifdef HAVE_PRI
11447    if (!reload) {
11448       for (x = 0; x < NUM_SPANS; x++) {
11449          if (pris[x].pvts[0]) {
11450             if (start_pri(pris + x)) {
11451                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11452                return -1;
11453             } else if (option_verbose > 1)
11454                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11455          }
11456       }
11457    }
11458 #endif
11459    /* And start the monitor for the first time */
11460    restart_monitor();
11461    return 0;
11462 }

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

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

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

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

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

00863 {
00864    int tchan;
00865    int tinthreeway;
00866    struct ast_channel *towner;
00867 
00868    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
00869 
00870    tchan = p->subs[a].chan;
00871    towner = p->subs[a].owner;
00872    tinthreeway = p->subs[a].inthreeway;
00873 
00874    p->subs[a].chan = p->subs[b].chan;
00875    p->subs[a].owner = p->subs[b].owner;
00876    p->subs[a].inthreeway = p->subs[b].inthreeway;
00877 
00878    p->subs[b].chan = tchan;
00879    p->subs[b].owner = towner;
00880    p->subs[b].inthreeway = tinthreeway;
00881 
00882    if (p->subs[a].owner) 
00883       p->subs[a].owner->fds[0] = p->subs[a].zfd;
00884    if (p->subs[b].owner) 
00885       p->subs[b].owner->fds[0] = p->subs[b].zfd;
00886    wakeup_sub(p, a, NULL);
00887    wakeup_sub(p, b, NULL);
00888 }

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

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

00989 {
00990    if (!x) {
00991       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
00992       return -1;
00993    }
00994    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
00995    if (p->subs[x].zfd > -1) {
00996       zt_close(p->subs[x].zfd);
00997    }
00998    p->subs[x].zfd = -1;
00999    p->subs[x].linear = 0;
01000    p->subs[x].chan = 0;
01001    p->subs[x].owner = NULL;
01002    p->subs[x].inthreeway = 0;
01003    p->polarity = POLARITY_IDLE;
01004    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01005    return 0;
01006 }

static int unload_module ( void   )  [static]

Definition at line 10552 of file chan_zap.c.

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

10553 {
10554 #ifdef HAVE_PRI      
10555    int y;
10556    for (y = 0; y < NUM_SPANS; y++)
10557       ast_mutex_destroy(&pris[y].lock);
10558 #endif
10559    return __unload_module();
10560 }

static int update_conf ( struct zt_pvt p  )  [static]

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

01375 {
01376    int needconf = 0;
01377    int x;
01378    int useslavenative;
01379    struct zt_pvt *slave = NULL;
01380 
01381    useslavenative = isslavenative(p, &slave);
01382    /* Start with the obvious, general stuff */
01383    for (x = 0; x < 3; x++) {
01384       /* Look for three way calls */
01385       if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway) {
01386          conf_add(p, &p->subs[x], x, 0);
01387          needconf++;
01388       } else {
01389          conf_del(p, &p->subs[x], x);
01390       }
01391    }
01392    /* If we have a slave, add him to our conference now. or DAX
01393       if this is slave native */
01394    for (x = 0; x < MAX_SLAVES; x++) {
01395       if (p->slaves[x]) {
01396          if (useslavenative)
01397             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01398          else {
01399             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01400             needconf++;
01401          }
01402       }
01403    }
01404    /* If we're supposed to be in there, do so now */
01405    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01406       if (useslavenative)
01407          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01408       else {
01409          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01410          needconf++;
01411       }
01412    }
01413    /* If we have a master, add ourselves to his conference */
01414    if (p->master) {
01415       if (isslavenative(p->master, NULL)) {
01416          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01417       } else {
01418          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01419       }
01420    }
01421    if (!needconf) {
01422       /* Nobody is left (or should be left) in our conference.
01423          Kill it. */
01424       p->confno = -1;
01425    }
01426    if (option_debug)
01427       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01428    return 0;
01429 }

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

Definition at line 806 of file chan_zap.c.

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

Referenced by swap_subs().

00808 {
00809 #ifdef HAVE_PRI
00810    if (pri)
00811       ast_mutex_unlock(&pri->lock);
00812 #endif         
00813    for (;;) {
00814       if (p->subs[a].owner) {
00815          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00816             DEADLOCK_AVOIDANCE(&p->lock);
00817          } else {
00818             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
00819             ast_mutex_unlock(&p->subs[a].owner->lock);
00820             break;
00821          }
00822       } else
00823          break;
00824    }
00825 #ifdef HAVE_PRI
00826    if (pri)
00827       ast_mutex_lock(&pri->lock);
00828 #endif         
00829 }

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

Definition at line 9894 of file chan_zap.c.

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

09895 {
09896    int channel;
09897    
09898    if (argc != 4)
09899       return RESULT_SHOWUSAGE;
09900    
09901    channel = atoi(argv[3]);
09902 
09903    return zap_destroy_channel_bynum(channel);
09904 }

static int zap_destroy_channel_bynum ( int  channel  )  [static]

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

06596 {
06597    struct zt_pvt *tmp = NULL;
06598    struct zt_pvt *prev = NULL;
06599 
06600    tmp = iflist;
06601    while (tmp) {
06602       if (tmp->channel == channel) {
06603          destroy_channel(prev, tmp, 1);
06604          return RESULT_SUCCESS;
06605       }
06606       prev = tmp;
06607       tmp = tmp->next;
06608    }
06609    return RESULT_FAILURE;
06610 }

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

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

10302 {
10303    if (p) {
10304       switch (mode) {
10305          case TRANSFER:
10306             p->fake_event = ZT_EVENT_WINKFLASH;
10307             break;
10308          case HANGUP:
10309             p->fake_event = ZT_EVENT_ONHOOK;
10310             break;
10311          default:
10312             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10313       }
10314    }
10315    return 0;
10316 }

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

Definition at line 834 of file chan_zap.c.

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

Referenced by action_zapdialoffhook().

00836 {
00837    /* We must unlock the PRI to avoid the possibility of a deadlock */
00838 #ifdef HAVE_PRI
00839    if (pri)
00840       ast_mutex_unlock(&pri->lock);
00841 #endif      
00842    for (;;) {
00843       if (p->owner) {
00844          if (ast_mutex_trylock(&p->owner->lock)) {
00845             DEADLOCK_AVOIDANCE(&p->lock);
00846          } else {
00847             ast_queue_frame(p->owner, f);
00848             ast_mutex_unlock(&p->owner->lock);
00849             break;
00850          }
00851       } else
00852          break;
00853    }
00854 #ifdef HAVE_PRI
00855    if (pri)
00856       ast_mutex_lock(&pri->lock);
00857 #endif      
00858 }

static int zap_restart ( void   )  [static]

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

09908 {
09909    if (option_verbose > 0)
09910       ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
09911    while (iflist) {
09912       if (option_debug)
09913          ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
09914       /* Also updates iflist: */
09915       destroy_channel(NULL, iflist, 1);
09916    }
09917    if (option_debug)
09918       ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
09919    if (setup_zap(0) != 0) {
09920       ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
09921       return 1;
09922    }
09923    return 0;
09924 }

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

Definition at line 9926 of file chan_zap.c.

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

09927 {
09928    if (argc != 2) {
09929       return RESULT_SHOWUSAGE;
09930    }
09931 
09932    if (zap_restart() != 0)
09933       return RESULT_FAILURE;
09934    return RESULT_SUCCESS;
09935 }

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

Definition at line 10008 of file chan_zap.c.

References ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::busyfuzziness, zt_pvt::busyquietlength, zt_pvt::busytonelength, zt_pvt::callprogress, 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, ISTRUNK, zt_pvt::law, zt_subchannel::linear, lock, zt_pvt::master, zt_pvt::next, 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, and zt_pvt::subs.

10009 {
10010    int channel;
10011    struct zt_pvt *tmp = NULL;
10012    ZT_CONFINFO ci;
10013    ZT_PARAMS ps;
10014    int x;
10015    ast_mutex_t *lock;
10016    struct zt_pvt *start;
10017 #ifdef HAVE_PRI
10018    char *c;
10019    int trunkgroup;
10020    struct zt_pri *pri=NULL;
10021 #endif
10022 
10023    lock = &iflock;
10024    start = iflist;
10025 
10026    if (argc != 4)
10027       return RESULT_SHOWUSAGE;
10028 #ifdef HAVE_PRI
10029    if ((c = strchr(argv[3], ':'))) {
10030       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10031          return RESULT_SHOWUSAGE;
10032       if ((trunkgroup < 1) || (channel < 1))
10033          return RESULT_SHOWUSAGE;
10034       for (x = 0; x < NUM_SPANS; x++) {
10035          if (pris[x].trunkgroup == trunkgroup) {
10036             pri = pris + x;
10037             break;
10038          }
10039       }
10040       if (pri) {
10041          start = pri->crvs;
10042          lock = &pri->lock;
10043       } else {
10044          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10045          return RESULT_FAILURE;
10046       }
10047    } else
10048 #endif
10049       channel = atoi(argv[3]);
10050 
10051    ast_mutex_lock(lock);
10052    tmp = start;
10053    while (tmp) {
10054       if (tmp->channel == channel) {
10055 #ifdef HAVE_PRI
10056          if (pri) 
10057             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10058          else
10059 #endif         
10060          ast_cli(fd, "Channel: %d\n", tmp->channel);
10061          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
10062          ast_cli(fd, "Span: %d\n", tmp->span);
10063          ast_cli(fd, "Extension: %s\n", tmp->exten);
10064          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10065          ast_cli(fd, "Context: %s\n", tmp->context);
10066          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10067          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10068          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10069          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10070          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10071          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10072          ast_cli(fd, "Radio: %d\n", tmp->radio);
10073          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10074          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)" : "");
10075          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)" : "");
10076          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)" : "");
10077          ast_cli(fd, "Confno: %d\n", tmp->confno);
10078          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10079          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10080          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10081          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10082          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10083          ast_cli(fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
10084          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10085          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10086          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10087          if (tmp->master)
10088             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10089          for (x = 0; x < MAX_SLAVES; x++) {
10090             if (tmp->slaves[x])
10091                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10092          }
10093 #ifdef HAVE_PRI
10094          if (tmp->pri) {
10095             ast_cli(fd, "PRI Flags: ");
10096             if (tmp->resetting)
10097                ast_cli(fd, "Resetting ");
10098             if (tmp->call)
10099                ast_cli(fd, "Call ");
10100             if (tmp->bearer)
10101                ast_cli(fd, "Bearer ");
10102             ast_cli(fd, "\n");
10103             if (tmp->logicalspan) 
10104                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10105             else
10106                ast_cli(fd, "PRI Logical Span: Implicit\n");
10107          }
10108             
10109 #endif
10110          memset(&ci, 0, sizeof(ci));
10111          ps.channo = tmp->channel;
10112          if (tmp->subs[SUB_REAL].zfd > -1) {
10113             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
10114                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10115             }
10116 #ifdef ZT_GETCONFMUTE
10117             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) {
10118                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10119             }
10120 #endif
10121             if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
10122                ast_log(LOG_WARNING, "Failed to get parameters on channel %d\n", tmp->channel);
10123             } else {
10124                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10125             }
10126          }
10127          if (ISTRUNK(tmp)) {
10128             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
10129             if (!ast_strlen_zero(progzone))
10130                ast_cli(fd, "Progress Zone: %s\n", progzone);
10131             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
10132             if(tmp->busydetect) {
10133                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10134                if(tmp->busytonelength > 0) {
10135                   ast_cli(fd, "Busy Pattern:\n");
10136                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10137                   if (tmp->busyquietlength > 0) 
10138                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10139                   else 
10140                      ast_cli(fd, " -- Detect Tone Only\n");
10141                   if(tmp->busyfuzziness > 0)
10142                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10143                }
10144             }
10145          }
10146          ast_mutex_unlock(lock);
10147          return RESULT_SUCCESS;
10148       }
10149       tmp = tmp->next;
10150    }
10151    
10152    ast_cli(fd, "Unable to find given channel %d\n", channel);
10153    ast_mutex_unlock(lock);
10154    return RESULT_FAILURE;
10155 }

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

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

09948 {
09949 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
09950 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
09951    struct zt_pvt *tmp = NULL;
09952    char tmps[20] = "";
09953    ast_mutex_t *lock;
09954    struct zt_pvt *start;
09955 #ifdef HAVE_PRI
09956    int trunkgroup;
09957    struct zt_pri *pri = NULL;
09958    int x;
09959 #endif
09960 
09961    lock = &iflock;
09962    start = iflist;
09963 
09964 #ifdef HAVE_PRI
09965    if (argc == 4) {
09966       if ((trunkgroup = atoi(argv[3])) < 1)
09967          return RESULT_SHOWUSAGE;
09968       for (x = 0; x < NUM_SPANS; x++) {
09969          if (pris[x].trunkgroup == trunkgroup) {
09970             pri = pris + x;
09971             break;
09972          }
09973       }
09974       if (pri) {
09975          start = pri->crvs;
09976          lock = &pri->lock;
09977       } else {
09978          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
09979          return RESULT_FAILURE;
09980       }
09981    } else
09982 #endif
09983    if (argc != 3)
09984       return RESULT_SHOWUSAGE;
09985 
09986    ast_mutex_lock(lock);
09987 #ifdef HAVE_PRI
09988    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
09989 #else
09990    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
09991 #endif   
09992    
09993    tmp = start;
09994    while (tmp) {
09995       if (tmp->channel > 0) {
09996          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
09997       } else
09998          ast_copy_string(tmps, "pseudo", sizeof(tmps));
09999       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10000       tmp = tmp->next;
10001    }
10002    ast_mutex_unlock(lock);
10003    return RESULT_SUCCESS;
10004 #undef FORMAT
10005 #undef FORMAT2
10006 }

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

Definition at line 10188 of file chan_zap.c.

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

10188                                                            {
10189    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10190    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10191 
10192    int span;
10193    int res;
10194    char alarms[50];
10195 
10196    int ctl;
10197    ZT_SPANINFO s;
10198 
10199    ctl = open("/dev/zap/ctl", O_RDWR);
10200    if (ctl < 0) {
10201       ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10202       ast_cli(fd, "No Zaptel interface found.\n");
10203       return RESULT_FAILURE;
10204    }
10205    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10206 
10207    for (span = 1; span < ZT_MAX_SPANS; ++span) {
10208       s.spanno = span;
10209       res = ioctl(ctl, ZT_SPANSTAT, &s);
10210       if (res) {
10211          continue;
10212       }
10213       alarms[0] = '\0';
10214       if (s.alarms > 0) {
10215          if (s.alarms & ZT_ALARM_BLUE)
10216             strcat(alarms, "BLU/");
10217          if (s.alarms & ZT_ALARM_YELLOW)
10218             strcat(alarms, "YEL/");
10219          if (s.alarms & ZT_ALARM_RED)
10220             strcat(alarms, "RED/");
10221          if (s.alarms & ZT_ALARM_LOOPBACK)
10222             strcat(alarms, "LB/");
10223          if (s.alarms & ZT_ALARM_RECOVER)
10224             strcat(alarms, "REC/");
10225          if (s.alarms & ZT_ALARM_NOTOPEN)
10226             strcat(alarms, "NOP/");
10227          if (!strlen(alarms))
10228             strcat(alarms, "UUU/");
10229          if (strlen(alarms)) {
10230             /* Strip trailing / */
10231             alarms[strlen(alarms) - 1] = '\0';
10232          }
10233       } else {
10234          if (s.numchans)
10235             strcpy(alarms, "OK");
10236          else
10237             strcpy(alarms, "UNCONFIGURED");
10238       }
10239 
10240       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10241    }
10242    close(ctl);
10243 
10244    return RESULT_SUCCESS;
10245 #undef FORMAT
10246 #undef FORMAT2
10247 }

static char* zap_sig2str ( int  sig  )  [static]

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

01185 {
01186    static char buf[256];
01187    switch (sig) {
01188    case SIG_EM:
01189       return "E & M Immediate";
01190    case SIG_EMWINK:
01191       return "E & M Wink";
01192    case SIG_EM_E1:
01193       return "E & M E1";
01194    case SIG_FEATD:
01195       return "Feature Group D (DTMF)";
01196    case SIG_FEATDMF:
01197       return "Feature Group D (MF)";
01198    case SIG_FEATDMF_TA:
01199       return "Feature Groud D (MF) Tandem Access";
01200    case SIG_FEATB:
01201       return "Feature Group B (MF)";
01202    case SIG_E911:
01203       return "E911 (MF)";
01204    case SIG_FGC_CAMA:
01205       return "FGC/CAMA (Dialpulse)";
01206    case SIG_FGC_CAMAMF:
01207       return "FGC/CAMA (MF)";
01208    case SIG_FXSLS:
01209       return "FXS Loopstart";
01210    case SIG_FXSGS:
01211       return "FXS Groundstart";
01212    case SIG_FXSKS:
01213       return "FXS Kewlstart";
01214    case SIG_FXOLS:
01215       return "FXO Loopstart";
01216    case SIG_FXOGS:
01217       return "FXO Groundstart";
01218    case SIG_FXOKS:
01219       return "FXO Kewlstart";
01220    case SIG_PRI:
01221       return "ISDN PRI";
01222    case SIG_SF:
01223       return "SF (Tone) Immediate";
01224    case SIG_SFWINK:
01225       return "SF (Tone) Wink";
01226    case SIG_SF_FEATD:
01227       return "SF (Tone) with Feature Group D (DTMF)";
01228    case SIG_SF_FEATDMF:
01229       return "SF (Tone) with Feature Group D (MF)";
01230    case SIG_SF_FEATB:
01231       return "SF (Tone) with Feature Group B (MF)";
01232    case SIG_GR303FXOKS:
01233       return "GR-303 with FXOKS";
01234    case SIG_GR303FXSKS:
01235       return "GR-303 with FXSKS";
01236    case 0:
01237       return "Pseudo";
01238    default:
01239       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01240       return buf;
01241    }
01242 }

static int zt_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

static int zt_callwait ( struct ast_channel ast  )  [static]

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

01765 {
01766    struct zt_pvt *p = ast->tech_pvt;
01767    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01768    if (p->cidspill) {
01769       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01770       free(p->cidspill);
01771    }
01772    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01773       return -1;
01774    save_conference(p);
01775    /* Silence */
01776    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01777    if (!p->callwaitrings && p->callwaitingcallerid) {
01778       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01779       p->callwaitcas = 1;
01780       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01781    } else {
01782       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01783       p->callwaitcas = 0;
01784       p->cidlen = 2400 + READ_SIZE * 4;
01785    }
01786    p->cidpos = 0;
01787    send_callerid(p);
01788    
01789    return 0;
01790 }

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 604 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().

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

static void zt_close ( int  fd  )  [static]

Definition at line 937 of file chan_zap.c.

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

00938 {
00939    if (fd > 0)
00940       close(fd);
00941 }

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

Definition at line 1649 of file chan_zap.c.

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

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

01650 {
01651    int x, y, res;
01652    x = muted;
01653    if (p->sig == SIG_PRI) {
01654       y = 1;
01655       res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
01656       if (res)
01657          ast_log(LOG_WARNING, "Unable to set audio mode on '%d'\n", p->channel);
01658    }
01659    res = ioctl(p->subs[SUB_REAL].zfd, ZT_CONFMUTE, &x);
01660    if (res < 0)
01661       ast_log(LOG_WARNING, "zt confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01662    return res;
01663 }

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

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

01025 {
01026    struct zt_pvt *pvt;
01027    int index;
01028    int dtmf = -1;
01029    
01030    pvt = chan->tech_pvt;
01031 
01032    ast_mutex_lock(&pvt->lock);
01033 
01034    index = zt_get_index(chan, pvt, 0);
01035 
01036    if ((index != SUB_REAL) || !pvt->owner)
01037       goto out;
01038 
01039 #ifdef HAVE_PRI
01040    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01041       if (pvt->setup_ack) {
01042          if (!pri_grab(pvt, pvt->pri)) {
01043             pri_information(pvt->pri->pri, pvt->call, digit);
01044             pri_rel(pvt->pri);
01045          } else
01046             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01047       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01048          int res;
01049          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01050          res = strlen(pvt->dialdest);
01051          pvt->dialdest[res++] = digit;
01052          pvt->dialdest[res] = '\0';
01053       }
01054       goto out;
01055    }
01056 #endif
01057    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01058       goto out;
01059 
01060    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &dtmf)) {
01061       int res;
01062       ZT_DIAL_OPERATION zo = {
01063          .op = ZT_DIAL_OP_APPEND,
01064          .dialstr[0] = 'T',
01065          .dialstr[1] = digit,
01066          .dialstr[2] = 0,
01067       };
01068       if ((res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_DIAL, &zo)))
01069          ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
01070       else
01071          pvt->dialing = 1;
01072    } else {
01073       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01074       pvt->dialing = 1;
01075       pvt->begindigit = digit;
01076    }
01077 
01078 out:
01079    ast_mutex_unlock(&pvt->lock);
01080 
01081    return 0;
01082 }

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

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

01085 {
01086    struct zt_pvt *pvt;
01087    int res = 0;
01088    int index;
01089    int x;
01090    
01091    pvt = chan->tech_pvt;
01092 
01093    ast_mutex_lock(&pvt->lock);
01094    
01095    index = zt_get_index(chan, pvt, 0);
01096 
01097    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01098       goto out;
01099 
01100 #ifdef HAVE_PRI
01101    /* This means that the digit was already sent via PRI signalling */
01102    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01103       goto out;
01104 #endif
01105 
01106    if (pvt->begindigit) {
01107       x = -1;
01108       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01109       res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &x);
01110       pvt->dialing = 0;
01111       pvt->begindigit = 0;
01112    }
01113 
01114 out:
01115    ast_mutex_unlock(&pvt->lock);
01116 
01117    return res;
01118 }

static void zt_disable_ec ( struct zt_pvt p  )  [static]

Definition at line 1481 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, and zt_pvt::subs.

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

01482 {
01483    int x;
01484    int res;
01485    if (p->echocancel) {
01486       x = 0;
01487       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01488       if (res)
01489          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
01490       else if (option_debug)
01491          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01492    }
01493    p->echocanon = 0;
01494 }

static void zt_enable_ec ( struct zt_pvt p  )  [static]

Definition at line 1431 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, and zt_pvt::subs.

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

01432 {
01433    int x;
01434    int res;
01435    if (!p)
01436       return;
01437    if (p->echocanon) {
01438       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01439       return;
01440    }
01441    if (p->digital) {
01442       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01443       return;
01444    }
01445    if (p->echocancel) {
01446       if (p->sig == SIG_PRI) {
01447          x = 1;
01448          res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x);
01449          if (res)
01450             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01451       }
01452       x = p->echocancel;
01453       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01454       if (res) 
01455          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01456       else {
01457          p->echocanon = 1;
01458          if (option_debug)
01459             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01460       }
01461    } else if (option_debug)
01462       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01463 }

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

Definition at line 4638 of file chan_zap.c.

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

04639 {
04640    struct zt_pvt *p = ast->tech_pvt;
04641    struct ast_frame *f;
04642    ast_mutex_lock(&p->lock);
04643    f = __zt_exception(ast);
04644    ast_mutex_unlock(&p->lock);
04645    return f;
04646 }

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

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

03458 {
03459    struct zt_pvt *p = newchan->tech_pvt;
03460    int x;
03461    ast_mutex_lock(&p->lock);
03462    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03463    if (p->owner == oldchan) {
03464       p->owner = newchan;
03465    }
03466    for (x = 0; x < 3; x++)
03467       if (p->subs[x].owner == oldchan) {
03468          if (!x)
03469             zt_unlink(NULL, p, 0);
03470          p->subs[x].owner = newchan;
03471       }
03472    if (newchan->_state == AST_STATE_RINGING) 
03473       zt_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03474    update_conf(p);
03475    ast_mutex_unlock(&p->lock);
03476    return 0;
03477 }

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

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

03030 {
03031    struct zt_pvt *p = chan->tech_pvt;
03032    
03033    if (!strcasecmp(data, "rxgain")) {
03034       ast_mutex_lock(&p->lock);
03035       snprintf(buf, len, "%f", p->rxgain);
03036       ast_mutex_unlock(&p->lock);   
03037    } else if (!strcasecmp(data, "txgain")) {
03038       ast_mutex_lock(&p->lock);
03039       snprintf(buf, len, "%f", p->txgain);
03040       ast_mutex_unlock(&p->lock);   
03041    } else {
03042       ast_copy_string(buf, "", len);
03043    }
03044    return 0;
03045 }

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

Avoid the silly zt_getevent which ignores a bunch of events.

Definition at line 257 of file chan_zap.c.

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

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

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

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

00787 {
00788    int res;
00789    if (p->subs[0].owner == ast)
00790       res = 0;
00791    else if (p->subs[1].owner == ast)
00792       res = 1;
00793    else if (p->subs[2].owner == ast)
00794       res = 2;
00795    else {
00796       res = -1;
00797       if (!nullok)
00798          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
00799    }
00800    return res;
00801 }

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

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

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

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

Definition at line 3696 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, DEADLOCK_AVOIDANCE, 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, ast_channel::lock, zt_pvt::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().

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

static int zt_hangup ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

Definition at line 3104 of file chan_zap.c.

References ast_log(), LOG_WARNING, and master.

Referenced by zt_bridge().

03104                                                                  {
03105    int x;
03106    if (!slave || !master) {
03107       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03108       return;
03109    }
03110    for (x = 0; x < MAX_SLAVES; x++) {
03111       if (!master->slaves[x]) {
03112          master->slaves[x] = slave;
03113          break;
03114       }
03115    }
03116    if (x >= MAX_SLAVES) {
03117       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03118       master->slaves[MAX_SLAVES - 1] = slave;
03119    }
03120    if (slave->master) 
03121       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03122    slave->master = master;
03123    
03124    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03125 }

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

Definition at line 5217 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_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), 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::busycompare, zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::busyfuzziness, zt_pvt::busyquietlength, zt_pvt::busytonelength, 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, zt_pvt::silencethreshold, 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().

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

static int zt_open ( char *  fn  )  [static]

Definition at line 890 of file chan_zap.c.

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

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

00891 {
00892    int fd;
00893    int isnum;
00894    int chan = 0;
00895    int bs;
00896    int x;
00897    isnum = 1;
00898    for (x = 0; x < strlen(fn); x++) {
00899       if (!isdigit(fn[x])) {
00900          isnum = 0;
00901          break;
00902       }
00903    }
00904    if (isnum) {
00905       chan = atoi(fn);
00906       if (chan < 1) {
00907          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
00908          return -1;
00909       }
00910       fn = "/dev/zap/channel";
00911    }
00912    fd = open(fn, O_RDWR | O_NONBLOCK);
00913    if (fd < 0) {
00914       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
00915       return -1;
00916    }
00917    if (chan) {
00918       if (ioctl(fd, ZT_SPECIFY, &chan)) {
00919          x = errno;
00920          close(fd);
00921          errno = x;
00922          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
00923          return -1;
00924       }
00925    }
00926    bs = READ_SIZE;
00927    if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) {
00928       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
00929       x = errno;
00930       close(fd);
00931       errno = x;
00932       return -1;
00933    }
00934    return fd;
00935 }

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

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

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

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

Definition at line 7814 of file chan_zap.c.

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

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

static int zt_ring_phone ( struct zt_pvt p  )  [static]

Definition at line 3479 of file chan_zap.c.

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

Referenced by __zt_exception(), and zt_handle_event().

03480 {
03481    int x;
03482    int res;
03483    /* Make sure our transmit state is on hook */
03484    x = 0;
03485    x = ZT_ONHOOK;
03486    res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03487    do {
03488       x = ZT_RING;
03489       res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03490       if (res) {
03491          switch (errno) {
03492          case EBUSY:
03493          case EINTR:
03494             /* Wait just in case */
03495             usleep(10000);
03496             continue;
03497          case EINPROGRESS:
03498             res = 0;
03499             break;
03500          default:
03501             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03502             res = 0;
03503          }
03504       }
03505    } while (res);
03506    return res;
03507 }

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

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

11512 {
11513 #define  END_SILENCE_LEN 400
11514 #define  HEADER_MS 50
11515 #define  TRAILER_MS 5
11516 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11517 #define  ASCII_BYTES_PER_CHAR 80
11518 
11519    unsigned char *buf,*mybuf;
11520    struct zt_pvt *p = c->tech_pvt;
11521    struct pollfd fds[1];
11522    int size,res,fd,len,x;
11523    int bytes=0;
11524    /* Initial carrier (imaginary) */
11525    float cr = 1.0;
11526    float ci = 0.0;
11527    float scont = 0.0;
11528    int index;
11529 
11530    index = zt_get_index(c, p, 0);
11531    if (index < 0) {
11532       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
11533       return -1;
11534    }
11535    if (!text[0]) return(0); /* if nothing to send, dont */
11536    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
11537    if (p->mate) 
11538       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11539    else
11540       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11541    if (!buf)
11542       return -1;
11543    mybuf = buf;
11544    if (p->mate) {
11545       int codec = AST_LAW(p);
11546       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
11547          PUT_CLID_MARKMS;
11548       }
11549       /* Put actual message */
11550       for (x = 0; text[x]; x++) {
11551          PUT_CLID(text[x]);
11552       }
11553       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
11554          PUT_CLID_MARKMS;
11555       }
11556       len = bytes;
11557       buf = mybuf;
11558    } else {
11559       len = tdd_generate(p->tdd, buf, text);
11560       if (len < 1) {
11561          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11562          free(mybuf);
11563          return -1;
11564       }
11565    }
11566    memset(buf + len, 0x7f, END_SILENCE_LEN);
11567    len += END_SILENCE_LEN;
11568    fd = p->subs[index].zfd;
11569    while (len) {
11570       if (ast_check_hangup(c)) {
11571          free(mybuf);
11572          return -1;
11573       }
11574       size = len;
11575       if (size > READ_SIZE)
11576          size = READ_SIZE;
11577       fds[0].fd = fd;
11578       fds[0].events = POLLOUT | POLLPRI;
11579       fds[0].revents = 0;
11580       res = poll(fds, 1, -1);
11581       if (!res) {
11582          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11583          continue;
11584       }
11585         /* if got exception */
11586       if (fds[0].revents & POLLPRI) {
11587          ast_free(mybuf);
11588          return -1;
11589       }
11590       if (!(fds[0].revents & POLLOUT)) {
11591          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11592          continue;
11593       }
11594       res = write(fd, buf, size);
11595       if (res != size) {
11596          if (res == -1) {
11597             free(mybuf);
11598             return -1;
11599          }
11600          if (option_debug)
11601             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11602          break;
11603       }
11604       len -= size;
11605       buf += size;
11606    }
11607    free(mybuf);
11608    return(0);
11609 }

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

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

01634 {
01635    int x, res;
01636 
01637    x = hs;
01638    res = ioctl(fd, ZT_HOOK, &x);
01639 
01640    if (res < 0) {
01641       if (errno == EINPROGRESS)
01642          return 0;
01643       ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
01644    }
01645 
01646    return res;
01647 }

static int zt_setlaw ( int  zfd,
int  law 
) [static]

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

Definition at line 943 of file chan_zap.c.

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

00944 {
00945    int res;
00946    res = ioctl(zfd, ZT_SETLINEAR, &linear);
00947    if (res)
00948       return res;
00949    return 0;
00950 }

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

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

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

static void zt_train_ec ( struct zt_pvt p  )  [static]

Definition at line 1465 of file chan_zap.c.

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

Referenced by zt_answer(), and zt_handle_event().

01466 {
01467    int x;
01468    int res;
01469    if (p && p->echocancel && p->echotraining) {
01470       x = p->echotraining;
01471       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
01472       if (res)
01473          ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
01474       else {
01475          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01476       }
01477    } else
01478       ast_log(LOG_DEBUG, "No echo training requested\n");
01479 }

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

Definition at line 3048 of file chan_zap.c.

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

Referenced by zt_bridge(), and zt_fixup().

03049 {
03050    /* Unlink a specific slave or all slaves/masters from a given master */
03051    int x;
03052    int hasslaves;
03053    if (!master)
03054       return;
03055    if (needlock) {
03056       ast_mutex_lock(&master->lock);
03057       if (slave) {
03058          while (ast_mutex_trylock(&slave->lock)) {
03059             DEADLOCK_AVOIDANCE(&master->lock);
03060          }
03061       }
03062    }
03063    hasslaves = 0;
03064    for (x = 0; x < MAX_SLAVES; x++) {
03065       if (master->slaves[x]) {
03066          if (!slave || (master->slaves[x] == slave)) {
03067             /* Take slave out of the conference */
03068             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03069             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03070             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03071             master->slaves[x]->master = NULL;
03072             master->slaves[x] = NULL;
03073          } else
03074             hasslaves = 1;
03075       }
03076       if (!hasslaves)
03077          master->inconference = 0;
03078    }
03079    if (!slave) {
03080       if (master->master) {
03081          /* Take master out of the conference */
03082          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03083          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03084          hasslaves = 0;
03085          for (x = 0; x < MAX_SLAVES; x++) {
03086             if (master->master->slaves[x] == master)
03087                master->master->slaves[x] = NULL;
03088             else if (master->master->slaves[x])
03089                hasslaves = 1;
03090          }
03091          if (!hasslaves)
03092             master->master->inconference = 0;
03093       }
03094       master->master = NULL;
03095    }
03096    update_conf(master);
03097    if (needlock) {
03098       if (slave)
03099          ast_mutex_unlock(&slave->lock);
03100       ast_mutex_unlock(&master->lock);
03101    }
03102 }

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

Avoid the silly zt_waitevent which ignores a bunch of events.

Definition at line 266 of file chan_zap.c.

Referenced by flash_exec(), and ss_thread().

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

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

Definition at line 5428 of file chan_zap.c.

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

Referenced by ss_thread().

05429 {
05430    int j;
05431    zt_set_hook(p->subs[index].zfd, ZT_WINK);
05432    for (;;)
05433    {
05434          /* set bits of interest */
05435       j = ZT_IOMUX_SIGEVENT;
05436           /* wait for some happening */
05437       if (ioctl(p->subs[index].zfd,ZT_IOMUX,&j) == -1) return(-1);
05438          /* exit loop if we have it */
05439       if (j & ZT_IOMUX_SIGEVENT) break;
05440    }
05441      /* get the event info */
05442    if (ioctl(p->subs[index].zfd,ZT_GETEVENT,&j) == -1) return(-1);
05443    return 0;
05444 }

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

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

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


Variable Documentation

int alarm

Definition at line 1143 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 762 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 773 of file chan_zap.c.

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

Definition at line 166 of file chan_zap.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 110 of file chan_zap.c.

char defaultcic[64] = "" [static]

Definition at line 205 of file chan_zap.c.

char defaultozz[64] = "" [static]

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

int distinctiveringaftercid = 0 [static]

Definition at line 210 of file chan_zap.c.

struct zt_distRings drings [static]

Definition at line 369 of file chan_zap.c.

Referenced by process_zap().

char* events[] [static]

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

int gendigittimeout = 8000 [static]

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

Definition at line 227 of file chan_zap.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 117 of file chan_zap.c.

int ifcount = 0 [static]

Definition at line 236 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 230 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 248 of file chan_zap.c.

char* name

Definition at line 1144 of file chan_zap.c.

int num_cadence = 4 [static]

Definition at line 759 of file chan_zap.c.

int numbufs = 4 [static]

Definition at line 212 of file chan_zap.c.

char progzone[10] = "" [static]

Definition at line 208 of file chan_zap.c.

int ringt_base = DEFAULT_RINGT [static]

Definition at line 291 of file chan_zap.c.

struct zt_pvt* round_robin[32]

Definition at line 739 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 10253 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 10249 of file chan_zap.c.

char* subnames[] [static]

Initial value:

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

Definition at line 382 of file chan_zap.c.

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

Definition at line 160 of file chan_zap.c.

int user_has_defined_cadences = 0 [static]

Definition at line 760 of file chan_zap.c.

struct ast_cli_entry zap_cli[] [static]

Definition at line 10272 of file chan_zap.c.

Referenced by __unload_module(), and load_module().

char zap_restart_usage[] [static]

Definition at line 10265 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 10157 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 10257 of file chan_zap.c.

struct ast_channel_tech zap_tech [static]

Definition at line 712 of file chan_zap.c.

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


Generated on Tue Nov 4 13:20:35 2008 for Asterisk - the Open Source PBX by  doxygen 1.4.7