Fri Aug 24 02:23:52 2007

Asterisk developer's documentation


chan_zap.c File Reference

Zaptel Pseudo TDM interface. More...

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

Include dependency graph for chan_zap.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

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

Variables

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


Detailed Description

Zaptel Pseudo TDM interface.

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

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

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

Definition in file chan_zap.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by zt_sendtext().

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

Definition at line 153 of file chan_zap.c.

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

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

300 ms

Definition at line 282 of file chan_zap.c.

Referenced by zt_callwait().

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

300 ms

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

Referenced by zt_handle_event(), and zt_new().

#define CHAN_PSEUDO   -2

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

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

500 ms

Definition at line 283 of file chan_zap.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 405 of file chan_zap.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 406 of file chan_zap.c.

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 201 of file chan_zap.c.

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 198 of file chan_zap.c.

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 197 of file chan_zap.c.

#define DCHAN_UP   (1 << 2)

Definition at line 199 of file chan_zap.c.

#define DEFAULT_CIDRINGS   1

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

Definition at line 149 of file chan_zap.c.

Referenced by zt_chan_conf_default().

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

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

#define HANGUP   1

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

Referenced by ss_thread(), and zt_indicate().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 278 of file chan_zap.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_zap().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 193 of file chan_zap.c.

Referenced by mkintf().

#define MAX_SLAVES   4

Definition at line 408 of file chan_zap.c.

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

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

Referenced by ss_thread(), and zt_new().

#define NUM_CADENCE_MAX   25

Definition at line 734 of file chan_zap.c.

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 192 of file chan_zap.c.

#define NUM_SPANS   32

Definition at line 191 of file chan_zap.c.

#define POLARITY_IDLE   0

Definition at line 363 of file chan_zap.c.

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

#define POLARITY_REV   1

Definition at line 364 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 276 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 1218 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 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_EM   ZT_SIG_EM

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

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

#define SIG_EMWINK   (0x0100000 | ZT_SIG_EM)

Definition at line 167 of file chan_zap.c.

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

#define SIG_FEATB   (0x0800000 | 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_FEATD   (0x0200000 | 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_FEATDMF   (0x0400000 | ZT_SIG_EM)

Definition at line 169 of file chan_zap.c.

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

#define SIG_FEATDMF_TA   (0x2000000 | 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_FGC_CAMA   (0x4000000 | ZT_SIG_EM)

Definition at line 173 of file chan_zap.c.

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

#define SIG_FGC_CAMAMF   (0x8000000 | 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_FXOGS   ZT_SIG_FXOGS

Definition at line 179 of file chan_zap.c.

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

#define SIG_FXOKS   ZT_SIG_FXOKS

Definition at line 180 of file chan_zap.c.

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

#define SIG_FXOLS   ZT_SIG_FXOLS

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

#define SIG_FXSGS   ZT_SIG_FXSGS

Definition at line 176 of file chan_zap.c.

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

#define SIG_FXSKS   ZT_SIG_FXSKS

Definition at line 177 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 175 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 188 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 189 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 181 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 182 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 186 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 184 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 185 of file chan_zap.c.

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

#define SIG_SFWINK   (0x0100000 | ZT_SIG_SF)

Definition at line 183 of file chan_zap.c.

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

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 105 of file chan_zap.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 359 of file chan_zap.c.

#define SUB_REAL   0

Active call

Definition at line 358 of file chan_zap.c.

#define SUB_THREEWAY   2

Three-way call

Definition at line 360 of file chan_zap.c.

#define tdesc   "Zapata Telephony"

Definition at line 11444 of file chan_zap.c.

Referenced by load_module().

#define TRAILER_MS   5

Referenced by zt_sendtext().

#define TRANSFER   0

Definition at line 10122 of file chan_zap.c.

Referenced by action_transfer(), and zap_fake_event().

#define ZT_EVENT_DTMFDOWN   0

Definition at line 123 of file chan_zap.c.

Referenced by zt_handle_event().

#define ZT_EVENT_DTMFUP   0

Definition at line 124 of file chan_zap.c.

Referenced by zt_handle_event().


Function Documentation

static int __unload_module ( void   )  [static]

Definition at line 10304 of file chan_zap.c.

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

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

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

Definition at line 4485 of file chan_zap.c.

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

Referenced by zt_exception(), and zt_read().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 9780 of file chan_zap.c.

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

Referenced by load_module().

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

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

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

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

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1129 of file chan_zap.c.

References alarms, and name.

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

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

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

Definition at line 927 of file chan_zap.c.

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

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

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

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

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

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

Definition at line 7548 of file chan_zap.c.

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

Referenced by zt_request().

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

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

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

Referenced by process_zap().

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

static int bump_gains ( struct zt_pvt p  )  [static]

Definition at line 1580 of file chan_zap.c.

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

Referenced by ss_thread().

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

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

Definition at line 7652 of file chan_zap.c.

References ast_log(), ast_malloc, ast_mutex_init(), destroy_zt_pvt(), iflist, LOG_ERROR, SUB_REAL, and zt_open().

Referenced by zt_request().

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

static int check_for_conference ( struct zt_pvt p  )  [static]

Definition at line 3558 of file chan_zap.c.

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

Referenced by zt_handle_event().

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

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

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

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

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

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

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

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

Definition at line 2219 of file chan_zap.c.

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

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

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

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

Definition at line 2204 of file chan_zap.c.

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

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

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

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 982 of file chan_zap.c.

Referenced by zt_digit_begin().

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

static void disable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3101 of file chan_zap.c.

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

Referenced by zt_bridge().

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

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

Definition at line 6757 of file chan_zap.c.

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

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

static void enable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3119 of file chan_zap.c.

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

Referenced by zt_bridge().

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

static char* event2str ( int  event  )  [static]

Definition at line 1139 of file chan_zap.c.

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

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

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

Definition at line 1504 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

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

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

Definition at line 1470 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

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

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

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

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

static int get_alarms ( struct zt_pvt p  )  [static]

Definition at line 3580 of file chan_zap.c.

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

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

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

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

Definition at line 6556 of file chan_zap.c.

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

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

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

Definition at line 9985 of file chan_zap.c.

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

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

static int has_voicemail ( struct zt_pvt p  )  [static]

Definition at line 1701 of file chan_zap.c.

References ast_app_has_voicemail(), and zt_pvt::mailbox.

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

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

Definition at line 1258 of file chan_zap.c.

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

Referenced by conf_del().

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

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

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

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

static int load_module ( void   )  [static]

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

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

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

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

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

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

Definition at line 5358 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

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

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

Definition at line 4889 of file chan_zap.c.

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

Referenced by zt_write().

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

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

Definition at line 10479 of file chan_zap.c.

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

Referenced by setup_zap().

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

static int reload ( void   )  [static]

Definition at line 11425 of file chan_zap.c.

References ast_log(), and setup_zap().

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

static int reset_conf ( struct zt_pvt p  )  [static]

Definition at line 1335 of file chan_zap.c.

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

Referenced by zt_hangup().

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

static int restart_monitor ( void   )  [static]

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

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

static int restore_conference ( struct zt_pvt p  )  [static]

Definition at line 1667 of file chan_zap.c.

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

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

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

static int restore_gains ( struct zt_pvt p  )  [static]

Definition at line 1594 of file chan_zap.c.

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

Referenced by ss_thread(), and zt_hangup().

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

static int save_conference ( struct zt_pvt p  )  [static]

Definition at line 1639 of file chan_zap.c.

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

Referenced by zt_callwait(), and zt_handle_event().

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

static int send_callerid ( struct zt_pvt p  )  [static]

Definition at line 1707 of file chan_zap.c.

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

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

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

static int send_cwcidspill ( struct zt_pvt p  )  [static]

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

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

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

Definition at line 1575 of file chan_zap.c.

References set_actual_rxgain(), and set_actual_txgain().

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

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

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

Definition at line 1557 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

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

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

Definition at line 1538 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

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

static int setup_zap ( int  reload  )  [static]

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

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

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

Definition at line 5395 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, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, zt_pvt::exten, exten, f, free, func, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, zt_pvt::hardwaredtmf, zt_pvt::hidecallerid, zt_pvt::immediate, ISTRUNK, zt_pvt::lastcid_num, len, zt_subchannel::linear, LOG_DEBUG, LOG_NOTICE, manager_event(), my_getsigstr(), name, NEED_MFDETECT, option_debug, option_verbose, zt_pvt::owner, zt_subchannel::owner, pbx_builtin_setvar_helper(), restore_gains(), distRingData::ring, zt_distRings::ringContext, zt_distRings::ringnum, zt_pvt::ringt, zt_pvt::ringt_base, zt_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, zt_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, zt_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, timeout, zt_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), zt_pvt::use_callerid, zt_pvt::use_smdi, zt_pvt::usedistinctiveringdetection, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, zap_tech, zt_subchannel::zfd, zt_enable_ec(), zt_get_event(), zt_get_index(), zt_set_hook(), zt_setlinear(), zt_wait_event(), and zt_wink().

Referenced by handle_init_event(), and zt_handle_event().

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

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 10376 of file chan_zap.c.

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

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

static int update_conf ( struct zt_pvt p  )  [static]

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

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

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

Definition at line 782 of file chan_zap.c.

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

Referenced by swap_subs().

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

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

Definition at line 9737 of file chan_zap.c.

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

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

static int zap_destroy_channel_bynum ( int  channel  )  [static]

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

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

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

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

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

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

Definition at line 812 of file chan_zap.c.

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

Referenced by action_zapdialoffhook().

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

static int zap_restart ( void   )  [static]

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

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

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

Definition at line 9769 of file chan_zap.c.

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

09770 {
09771    if (argc != 2) {
09772       return RESULT_SHOWUSAGE;
09773    }
09774 
09775    if (zap_restart() != 0)
09776       return RESULT_FAILURE;
09777    return RESULT_SUCCESS;
09778 }

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

Definition at line 9851 of file chan_zap.c.

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

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

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

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

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

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

Definition at line 10012 of file chan_zap.c.

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

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

static char* zap_sig2str ( int  sig  )  [static]

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

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

static int zt_answer ( struct ast_channel ast  )  [static]

Definition at line 2731 of file chan_zap.c.

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

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

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

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

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

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

Definition at line 1768 of file chan_zap.c.

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

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

static int zt_callwait ( struct ast_channel ast  )  [static]

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

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

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

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

static void zt_close ( int  fd  )  [static]

Definition at line 911 of file chan_zap.c.

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

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

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

Definition at line 1623 of file chan_zap.c.

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

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

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

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

Definition at line 998 of file chan_zap.c.

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

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

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

Definition at line 1058 of file chan_zap.c.

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

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

static void zt_disable_ec ( struct zt_pvt p  )  [static]

Definition at line 1455 of file chan_zap.c.

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

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

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

static void zt_enable_ec ( struct zt_pvt p  )  [static]

Definition at line 1405 of file chan_zap.c.

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

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

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

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

Definition at line 4592 of file chan_zap.c.

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

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

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

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

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

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

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

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

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

Avoid the silly zt_getevent which ignores a bunch of events.

Definition at line 255 of file chan_zap.c.

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

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

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

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

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

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

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

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

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

Definition at line 3665 of file chan_zap.c.

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

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

static int zt_hangup ( struct ast_channel ast  )  [static]

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

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

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

Definition at line 5000 of file chan_zap.c.

References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, zt_pvt::digital, zt_pvt::dop, func, ast_channel::hangupcause, ISTRUNK, zt_pvt::lock, LOG_DEBUG, 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().

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

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

Definition at line 3078 of file chan_zap.c.

References ast_log(), LOG_WARNING, and master.

Referenced by zt_bridge().

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

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

Definition at line 5171 of file chan_zap.c.

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

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

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

static int zt_open ( char *  fn  )  [static]

Definition at line 870 of file chan_zap.c.

References ast_log(), LOG_WARNING, and READ_SIZE.

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

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

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

Definition at line 4602 of file chan_zap.c.

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

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

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

Definition at line 7714 of file chan_zap.c.

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

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

static int zt_ring_phone ( struct zt_pvt p  )  [static]

Definition at line 3448 of file chan_zap.c.

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

Referenced by __zt_exception(), and zt_handle_event().

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

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

Definition at line 11326 of file chan_zap.c.

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

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

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

Definition at line 1607 of file chan_zap.c.

References ast_log(), and LOG_WARNING.

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

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

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

Definition at line 917 of file chan_zap.c.

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

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

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

Definition at line 2816 of file chan_zap.c.

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

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

static void zt_train_ec ( struct zt_pvt p  )  [static]

Definition at line 1439 of file chan_zap.c.

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

Referenced by zt_answer(), and zt_handle_event().

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

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

Definition at line 3020 of file chan_zap.c.

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

Referenced by zt_bridge(), and zt_fixup().

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

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

Avoid the silly zt_waitevent which ignores a bunch of events.

Definition at line 264 of file chan_zap.c.

Referenced by flash_exec(), and ss_thread().

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

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

Definition at line 5377 of file chan_zap.c.

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

Referenced by ss_thread().

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

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

Definition at line 4912 of file chan_zap.c.

References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), zt_pvt::channel, zt_pvt::cidspill, ast_frame::data, ast_frame::datalen, zt_pvt::dialing, zt_pvt::digital, ast_frame::frametype, zt_subchannel::linear, zt_pvt::lock, LOG_DEBUG, 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().

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


Variable Documentation

int alarm

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

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

Definition at line 164 of file chan_zap.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 108 of file chan_zap.c.

char defaultcic[64] = "" [static]

Definition at line 203 of file chan_zap.c.

char defaultozz[64] = "" [static]

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

int distinctiveringaftercid = 0 [static]

Definition at line 208 of file chan_zap.c.

struct zt_distRings drings [static]

Definition at line 367 of file chan_zap.c.

Referenced by process_zap().

char* events[] [static]

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

int gendigittimeout = 8000 [static]

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

Definition at line 225 of file chan_zap.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 115 of file chan_zap.c.

int ifcount = 0 [static]

Definition at line 234 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 228 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 246 of file chan_zap.c.

char* name

Definition at line 1118 of file chan_zap.c.

int num_cadence = 4 [static]

Definition at line 735 of file chan_zap.c.

int numbufs = 4 [static]

Definition at line 210 of file chan_zap.c.

char progzone[10] = "" [static]

Definition at line 206 of file chan_zap.c.

int ringt_base = DEFAULT_RINGT [static]

Definition at line 289 of file chan_zap.c.

struct zt_pvt* round_robin[32]

Definition at line 712 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 10077 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 10073 of file chan_zap.c.

char* subnames[] [static]

Initial value:

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

Definition at line 380 of file chan_zap.c.

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

Definition at line 158 of file chan_zap.c.

int user_has_defined_cadences = 0 [static]

Definition at line 736 of file chan_zap.c.

struct ast_cli_entry zap_cli[] [static]

Definition at line 10096 of file chan_zap.c.

Referenced by __unload_module(), and load_module().

char zap_restart_usage[] [static]

Definition at line 10089 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 9981 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 10081 of file chan_zap.c.

struct ast_channel_tech zap_tech [static]

Definition at line 685 of file chan_zap.c.

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


Generated on Fri Aug 24 02:23:53 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1