Mon May 14 04:46:28 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 usedistinctiveringdetection = 0
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 283 of file chan_zap.c.

Referenced by zt_callwait().

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

300 ms

Definition at line 282 of file chan_zap.c.

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

Definition at line 760 of file chan_zap.c.

Referenced by zt_new().

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

Definition at line 761 of file chan_zap.c.

Referenced by zt_handle_event(), and zt_new().

#define CHAN_PSEUDO   -2

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

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 406 of file chan_zap.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 407 of file chan_zap.c.

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

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

#define END_SILENCE_LEN   400

Referenced by zt_sendtext().

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

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

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

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

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

Definition at line 710 of file chan_zap.c.

#define HANGUP   1

Definition at line 10086 of file chan_zap.c.

Referenced by action_transferhangup(), and zap_fake_event().

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

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

#define HEADER_MS   50

Referenced by zt_sendtext().

#define ISTRUNK (  ) 

Value:

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

Definition at line 757 of file chan_zap.c.

Referenced by ss_thread(), and zt_indicate().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 279 of file chan_zap.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 280 of file chan_zap.c.

#define MAX_CHANLIST_LEN   80

The length of the parameters list of 'zapchan'.

Todo:
Move definition of MAX_CHANLIST_LEN to a proper place.

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

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

Definition at line 285 of file chan_zap.c.

Referenced by zt_handle_event().

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

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

Definition at line 156 of file chan_zap.c.

Referenced by ss_thread(), and zt_new().

#define NUM_CADENCE_MAX   25

Definition at line 735 of file chan_zap.c.

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

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

#define POLARITY_REV   1

Definition at line 365 of file chan_zap.c.

Referenced by handle_init_event(), and zt_handle_event().

#define READ_SIZE   160

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

Definition at line 277 of file chan_zap.c.

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

#define sig2str   zap_sig2str

Definition at line 1219 of file chan_zap.c.

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

#define SUB_REAL   0

Active call

Definition at line 359 of file chan_zap.c.

#define SUB_THREEWAY   2

Three-way call

Definition at line 361 of file chan_zap.c.

#define tdesc   "Zapata Telephony"

Definition at line 11405 of file chan_zap.c.

Referenced by load_module().

#define TRAILER_MS   5

Referenced by zt_sendtext().

#define TRANSFER   0

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

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

10268 {
10269    int x = 0;
10270    struct zt_pvt *p, *pl;
10271 #ifdef HAVE_PRI
10272    int i;
10273    for (i = 0; i < NUM_SPANS; i++) {
10274       if (pris[i].master != AST_PTHREADT_NULL) 
10275          pthread_cancel(pris[i].master);
10276    }
10277    ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
10278    ast_unregister_application(zap_send_keypad_facility_app);
10279 #endif
10280    ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
10281    ast_manager_unregister( "ZapDialOffhook" );
10282    ast_manager_unregister( "ZapHangup" );
10283    ast_manager_unregister( "ZapTransfer" );
10284    ast_manager_unregister( "ZapDNDoff" );
10285    ast_manager_unregister( "ZapDNDon" );
10286    ast_manager_unregister("ZapShowChannels");
10287    ast_manager_unregister("ZapRestart");
10288    ast_channel_unregister(&zap_tech);
10289    ast_mutex_lock(&iflock);
10290    /* Hangup all interfaces if they have an owner */
10291    p = iflist;
10292    while (p) {
10293       if (p->owner)
10294          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10295       p = p->next;
10296    }
10297    ast_mutex_unlock(&iflock);
10298    ast_mutex_lock(&monlock);
10299    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10300       pthread_cancel(monitor_thread);
10301       pthread_kill(monitor_thread, SIGURG);
10302       pthread_join(monitor_thread, NULL);
10303    }
10304    monitor_thread = AST_PTHREADT_STOP;
10305    ast_mutex_unlock(&monlock);
10306 
10307    ast_mutex_lock(&iflock);
10308    /* Destroy all the interfaces and free their memory */
10309    p = iflist;
10310    while (p) {
10311       /* Free any callerid */
10312       if (p->cidspill)
10313          free(p->cidspill);
10314       /* Close the zapata thingy */
10315       if (p->subs[SUB_REAL].zfd > -1)
10316          zt_close(p->subs[SUB_REAL].zfd);
10317       pl = p;
10318       p = p->next;
10319       x++;
10320       /* Free associated memory */
10321       if (pl)
10322          destroy_zt_pvt(&pl);
10323       ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10324    }
10325    iflist = NULL;
10326    ifcount = 0;
10327    ast_mutex_unlock(&iflock);
10328 #ifdef HAVE_PRI      
10329    for (i = 0; i < NUM_SPANS; i++) {
10330       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10331          pthread_join(pris[i].master, NULL);
10332       zt_close(pris[i].fds[i]);
10333    }
10334 #endif
10335    return 0;
10336 }

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

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

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

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

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

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

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

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

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

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

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

10193 {
10194    struct zt_pvt *p = NULL;
10195    const char *channel = astman_get_header(m, "ZapChannel");
10196    const char *number = astman_get_header(m, "Number");
10197    int i;
10198 
10199    if (ast_strlen_zero(channel)) {
10200       astman_send_error(s, m, "No channel specified");
10201       return 0;
10202    }
10203    if (ast_strlen_zero(number)) {
10204       astman_send_error(s, m, "No number specified");
10205       return 0;
10206    }
10207    p = find_channel(atoi(channel));
10208    if (!p) {
10209       astman_send_error(s, m, "No such channel");
10210       return 0;
10211    }
10212    if (!p->owner) {
10213       astman_send_error(s, m, "Channel does not have it's owner");
10214       return 0;
10215    }
10216    for (i = 0; i < strlen(number); i++) {
10217       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10218       zap_queue_frame(p, &f, NULL); 
10219    }
10220    astman_send_ack(s, m, "ZapDialOffhook");
10221    return 0;
10222 }

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

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

10136 {
10137    struct zt_pvt *p = NULL;
10138    const char *channel = astman_get_header(m, "ZapChannel");
10139 
10140    if (ast_strlen_zero(channel)) {
10141       astman_send_error(s, m, "No channel specified");
10142       return 0;
10143    }
10144    p = find_channel(atoi(channel));
10145    if (!p) {
10146       astman_send_error(s, m, "No such channel");
10147       return 0;
10148    }
10149    p->dnd = 0;
10150    astman_send_ack(s, m, "DND Disabled");
10151    return 0;
10152 }

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

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

10117 {
10118    struct zt_pvt *p = NULL;
10119    const char *channel = astman_get_header(m, "ZapChannel");
10120 
10121    if (ast_strlen_zero(channel)) {
10122       astman_send_error(s, m, "No channel specified");
10123       return 0;
10124    }
10125    p = find_channel(atoi(channel));
10126    if (!p) {
10127       astman_send_error(s, m, "No such channel");
10128       return 0;
10129    }
10130    p->dnd = 1;
10131    astman_send_ack(s, m, "DND Enabled");
10132    return 0;
10133 }

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

Definition at line 9743 of file chan_zap.c.

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

Referenced by load_module().

09744 {
09745    if (zap_restart() != 0) {
09746       astman_send_error(s, m, "Failed rereading zaptel configuration");
09747       return 1;
09748    }
09749    astman_send_ack(s, m, "ZapRestart: Success");
09750    return 0;
09751 }

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

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

10225 {
10226    struct zt_pvt *tmp = NULL;
10227    const char *id = astman_get_header(m, "ActionID");
10228    char idText[256] = "";
10229 
10230    astman_send_ack(s, m, "Zapata channel status will follow");
10231    if (!ast_strlen_zero(id))
10232       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10233 
10234    ast_mutex_lock(&iflock);
10235    
10236    tmp = iflist;
10237    while (tmp) {
10238       if (tmp->channel > 0) {
10239          int alarm = get_alarms(tmp);
10240          astman_append(s,
10241             "Event: ZapShowChannels\r\n"
10242             "Channel: %d\r\n"
10243             "Signalling: %s\r\n"
10244             "Context: %s\r\n"
10245             "DND: %s\r\n"
10246             "Alarm: %s\r\n"
10247             "%s"
10248             "\r\n",
10249             tmp->channel, sig2str(tmp->sig), tmp->context, 
10250             tmp->dnd ? "Enabled" : "Disabled",
10251             alarm2str(alarm), idText);
10252       } 
10253 
10254       tmp = tmp->next;
10255    }
10256 
10257    ast_mutex_unlock(&iflock);
10258    
10259    astman_append(s, 
10260       "Event: ZapShowChannelsComplete\r\n"
10261       "%s"
10262       "\r\n", 
10263       idText);
10264    return 0;
10265 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1130 of file chan_zap.c.

References alarms, and name.

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

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

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

Definition at line 928 of file chan_zap.c.

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

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

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

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

AST_MUTEX_DEFINE_STATIC ( monlock   ) 

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

AST_MUTEX_DEFINE_STATIC ( iflock   ) 

Protect the interface list (of zt_pvt's).

static int attempt_transfer ( struct zt_pvt p  )  [static]

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

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

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

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

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

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

10349 {
10350    char *c, *chan;
10351    int x, start, finish;
10352    struct zt_pvt *tmp;
10353 #ifdef HAVE_PRI
10354    struct zt_pri *pri;
10355    int trunkgroup, y;
10356 #endif
10357    
10358    if ((reload == 0) && (conf.chan.sig < 0)) {
10359       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10360       return -1;
10361    }
10362 
10363    c = ast_strdupa(value);
10364 
10365 #ifdef HAVE_PRI
10366    pri = NULL;
10367    if (iscrv) {
10368       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10369          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10370          return -1;
10371       }
10372       if (trunkgroup < 1) {
10373          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10374          return -1;
10375       }
10376       c += y;
10377       for (y = 0; y < NUM_SPANS; y++) {
10378          if (pris[y].trunkgroup == trunkgroup) {
10379             pri = pris + y;
10380             break;
10381          }
10382       }
10383       if (!pri) {
10384          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10385          return -1;
10386       }
10387    }
10388 #endif         
10389 
10390    while ((chan = strsep(&c, ","))) {
10391       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10392          /* Range */
10393       } else if (sscanf(chan, "%d", &start)) {
10394          /* Just one */
10395          finish = start;
10396       } else if (!strcasecmp(chan, "pseudo")) {
10397          finish = start = CHAN_PSEUDO;
10398          if (found_pseudo)
10399             *found_pseudo = 1;
10400       } else {
10401          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10402          return -1;
10403       }
10404       if (finish < start) {
10405          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10406          x = finish;
10407          finish = start;
10408          start = x;
10409       }
10410 
10411       for (x = start; x <= finish; x++) {
10412 #ifdef HAVE_PRI
10413          tmp = mkintf(x, conf, pri, reload);
10414 #else       
10415          tmp = mkintf(x, conf, NULL, reload);
10416 #endif         
10417 
10418          if (tmp) {
10419             if (option_verbose > 2) {
10420 #ifdef HAVE_PRI
10421                if (pri)
10422                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10423                else
10424 #endif
10425                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10426             }
10427          } else {
10428             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10429                (reload == 1) ? "reconfigure" : "register", value);
10430             return -1;
10431          }
10432       }
10433    }
10434 
10435    return 0;
10436 }

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

07639 {
07640    struct zt_pvt *p;
07641    ZT_BUFFERINFO bi;
07642    int res;
07643    
07644    if ((p = ast_malloc(sizeof(*p)))) {
07645       memcpy(p, src, sizeof(struct zt_pvt));
07646       ast_mutex_init(&p->lock);
07647       p->subs[SUB_REAL].zfd = zt_open("/dev/zap/pseudo");
07648       /* Allocate a zapata structure */
07649       if (p->subs[SUB_REAL].zfd < 0) {
07650          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
07651          destroy_zt_pvt(&p);
07652          return NULL;
07653       }
07654       res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
07655       if (!res) {
07656          bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
07657          bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
07658          bi.numbufs = numbufs;
07659          res = ioctl(p->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
07660          if (res < 0) {
07661             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel\n");
07662          }
07663       } else
07664          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel\n");
07665    }
07666    p->destroy = 1;
07667    p->next = iflist;
07668    iflist = p;
07669    return p;
07670 }

static int check_for_conference ( struct zt_pvt p  )  [static]

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

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

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

Definition at line 1221 of file chan_zap.c.

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

Referenced by update_conf().

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

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

Definition at line 1270 of file chan_zap.c.

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

Referenced by update_conf(), and zt_unlink().

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

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

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

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

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

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

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

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 983 of file chan_zap.c.

Referenced by zt_digit_begin().

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

static void disable_dtmf_detect ( struct zt_pvt p  )  [static]

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

03095 {
03096 #ifdef ZT_TONEDETECT
03097    int val;
03098 #endif
03099 
03100    p->ignoredtmf = 1;
03101 
03102 #ifdef ZT_TONEDETECT
03103    val = 0;
03104    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03105 #endif      
03106    if (!p->hardwaredtmf && p->dsp) {
03107       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03108       ast_dsp_set_features(p->dsp, p->dsp_features);
03109    }
03110 }

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

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

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

static void enable_dtmf_detect ( struct zt_pvt p  )  [static]

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

03113 {
03114 #ifdef ZT_TONEDETECT
03115    int val;
03116 #endif
03117 
03118    if (p->channel == CHAN_PSEUDO)
03119       return;
03120 
03121    p->ignoredtmf = 0;
03122 
03123 #ifdef ZT_TONEDETECT
03124    val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
03125    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03126 #endif      
03127    if (!p->hardwaredtmf && p->dsp) {
03128       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03129       ast_dsp_set_features(p->dsp, p->dsp_features);
03130    }
03131 }

static char* event2str ( int  event  )  [static]

Definition at line 1140 of file chan_zap.c.

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

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

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

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

10105 {
10106    struct zt_pvt *p = iflist;
10107    while (p) {
10108       if (p->channel == channel) {
10109          break;
10110       }
10111       p = p->next;
10112    }
10113    return p;
10114 }

static int get_alarms ( struct zt_pvt p  )  [static]

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

03574 {
03575    int res;
03576    ZT_SPANINFO zi;
03577    memset(&zi, 0, sizeof(zi));
03578    zi.spanno = p->span;
03579    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SPANSTAT, &zi);
03580    if (res < 0) {
03581       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03582       return 0;
03583    }
03584    return zi.alarms;
03585 }

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

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

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

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

Definition at line 9948 of file chan_zap.c.

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

09949 {
09950    int i, j;
09951    for (i = 0; i < num_cadence; i++) {
09952       char output[1024];
09953       char tmp[16], tmp2[64];
09954       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
09955       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
09956 
09957       for (j = 0; j < 16; j++) {
09958          if (cadences[i].ringcadence[j] == 0)
09959             break;
09960          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
09961          if (cidrings[i] * 2 - 1 == j)
09962             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
09963          else
09964             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
09965          if (j != 0)
09966             strncat(output, ",", sizeof(output) - strlen(output) - 1);
09967          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
09968       }
09969       ast_cli(fd,"%s\n",output);
09970    }
09971    return 0;
09972 }

static int has_voicemail ( struct zt_pvt p  )  [static]

Definition at line 1698 of file chan_zap.c.

References ast_app_has_voicemail(), and zt_pvt::mailbox.

01699 {
01700 
01701    return ast_app_has_voicemail(p->mailbox, NULL);
01702 }

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

Definition at line 1259 of file chan_zap.c.

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

Referenced by conf_del().

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

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

Definition at line 1292 of file chan_zap.c.

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

Referenced by update_conf().

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

static int load_module ( void   )  [static]

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

11241 {
11242    int res;
11243 
11244 #ifdef HAVE_PRI
11245    int y,i;
11246    memset(pris, 0, sizeof(pris));
11247    for (y = 0; y < NUM_SPANS; y++) {
11248       ast_mutex_init(&pris[y].lock);
11249       pris[y].offset = -1;
11250       pris[y].master = AST_PTHREADT_NULL;
11251       for (i = 0; i < NUM_DCHANS; i++)
11252          pris[y].fds[i] = -1;
11253    }
11254    pri_set_error(zt_pri_error);
11255    pri_set_message(zt_pri_message);
11256    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11257          zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11258 #endif
11259    res = setup_zap(0);
11260    /* Make sure we can register our Zap channel type */
11261    if (res)
11262       return AST_MODULE_LOAD_DECLINE;
11263    if (ast_channel_register(&zap_tech)) {
11264       ast_log(LOG_ERROR, "Unable to register channel class 'Zap'\n");
11265       __unload_module();
11266       return -1;
11267    }
11268 #ifdef HAVE_PRI
11269    ast_string_field_init(&inuse, 16);
11270    ast_string_field_set(&inuse, name, "GR-303InUse");
11271    ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
11272 #endif   
11273    ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
11274    
11275    memset(round_robin, 0, sizeof(round_robin));
11276    ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
11277    ast_manager_register( "ZapHangup", 0, action_transferhangup, "Hangup Zap Channel" );
11278    ast_manager_register( "ZapDialOffhook", 0, action_zapdialoffhook, "Dial over Zap channel while offhook" );
11279    ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
11280    ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
11281    ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
11282    ast_manager_register("ZapRestart", 0, action_zaprestart, "Fully Restart zaptel channels (terminates calls)");
11283 
11284    return res;
11285 }

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

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

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

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

Definition at line 5346 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

05347 {
05348    char c;
05349 
05350    *str = 0; /* start with empty output buffer */
05351    for (;;)
05352    {
05353       /* Wait for the first digit (up to specified ms). */
05354       c = ast_waitfordigit(chan, ms);
05355       /* if timeout, hangup or error, return as such */
05356       if (c < 1)
05357          return c;
05358       *str++ = c;
05359       *str = 0;
05360       if (strchr(term, c))
05361          return 1;
05362    }
05363 }

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

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

04875 {
04876    int sent=0;
04877    int size;
04878    int res;
04879    int fd;
04880    fd = p->subs[index].zfd;
04881    while (len) {
04882       size = len;
04883       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
04884          size = (linear ? READ_SIZE * 2 : READ_SIZE);
04885       res = write(fd, buf, size);
04886       if (res != size) {
04887          if (option_debug)
04888             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04889          return sent;
04890       }
04891       len -= size;
04892       buf += size;
04893    }
04894    return sent;
04895 }

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

Definition at line 10441 of file chan_zap.c.

References zt_pvt::accountcode, zt_pvt::adsi, zt_pvt::amaflags, 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, zt_pvt::drings, DSP_DIGITMODE_RELAXDTMF, zt_pvt::dtmfrelax, zt_pvt::echocanbridged, zt_pvt::echocancel, zt_pvt::echotraining, global_jbconf, zt_pvt::group, 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::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::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().

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

static int reload ( void   )  [static]

Definition at line 11386 of file chan_zap.c.

References ast_log(), and setup_zap().

11387 {
11388    int res = 0;
11389 
11390    res = setup_zap(1);
11391    if (res) {
11392       ast_log(LOG_WARNING, "Reload of chan_zap.so is unsuccessful!\n");
11393       return -1;
11394    }
11395    return 0;
11396 }

static int reset_conf ( struct zt_pvt p  )  [static]

Definition at line 1336 of file chan_zap.c.

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

Referenced by zt_hangup().

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

static int restart_monitor ( void   )  [static]

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

06935 {
06936    pthread_attr_t attr;
06937    pthread_attr_init(&attr);
06938    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06939    /* If we're supposed to be stopped -- stay stopped */
06940    if (monitor_thread == AST_PTHREADT_STOP)
06941       return 0;
06942    ast_mutex_lock(&monlock);
06943    if (monitor_thread == pthread_self()) {
06944       ast_mutex_unlock(&monlock);
06945       ast_log(LOG_WARNING, "Cannot kill myself\n");
06946       return -1;
06947    }
06948    if (monitor_thread != AST_PTHREADT_NULL) {
06949       /* Wake up the thread */
06950       pthread_kill(monitor_thread, SIGURG);
06951    } else {
06952       /* Start a new monitor */
06953       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
06954          ast_mutex_unlock(&monlock);
06955          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
06956          pthread_attr_destroy(&attr);
06957          return -1;
06958       }
06959    }
06960    ast_mutex_unlock(&monlock);
06961    pthread_attr_destroy(&attr);
06962    return 0;
06963 }

static int restore_conference ( struct zt_pvt p  )  [static]

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

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

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

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

static int send_callerid ( struct zt_pvt p  )  [static]

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

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

static int send_cwcidspill ( struct zt_pvt p  )  [static]

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

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

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

11108 {
11109    struct ast_config *cfg;
11110    struct ast_variable *v;
11111    struct zt_chan_conf conf = zt_chan_conf_default();
11112    int res;
11113 
11114 #ifdef HAVE_PRI
11115    char *c;
11116    int spanno;
11117    int i, x;
11118    int logicalspan;
11119    int trunkgroup;
11120    int dchannels[NUM_DCHANS];
11121 #endif
11122 
11123    cfg = ast_config_load(config);
11124 
11125    /* Error if we have no config file */
11126    if (!cfg) {
11127       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
11128       return 0;
11129    }
11130 
11131    /* It's a little silly to lock it, but we mind as well just to be sure */
11132    ast_mutex_lock(&iflock);
11133 #ifdef HAVE_PRI
11134    if (!reload) {
11135       /* Process trunkgroups first */
11136       v = ast_variable_browse(cfg, "trunkgroups");
11137       while (v) {
11138          if (!strcasecmp(v->name, "trunkgroup")) {
11139             trunkgroup = atoi(v->value);
11140             if (trunkgroup > 0) {
11141                if ((c = strchr(v->value, ','))) {
11142                   i = 0;
11143                   memset(dchannels, 0, sizeof(dchannels));
11144                   while (c && (i < NUM_DCHANS)) {
11145                      dchannels[i] = atoi(c + 1);
11146                      if (dchannels[i] < 0) {
11147                         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);
11148                      } else
11149                         i++;
11150                      c = strchr(c + 1, ',');
11151                   }
11152                   if (i) {
11153                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11154                         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);
11155                      } else if (option_verbose > 1)
11156                         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");
11157                   } else
11158                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
11159                } else
11160                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
11161             } else
11162                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
11163          } else if (!strcasecmp(v->name, "spanmap")) {
11164             spanno = atoi(v->value);
11165             if (spanno > 0) {
11166                if ((c = strchr(v->value, ','))) {
11167                   trunkgroup = atoi(c + 1);
11168                   if (trunkgroup > 0) {
11169                      if ((c = strchr(c + 1, ','))) 
11170                         logicalspan = atoi(c + 1);
11171                      else
11172                         logicalspan = 0;
11173                      if (logicalspan >= 0) {
11174                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11175                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11176                         } else if (option_verbose > 1) 
11177                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11178                      } else
11179                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
11180                   } else
11181                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
11182                } else
11183                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
11184             } else
11185                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
11186          } else {
11187             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11188          }
11189          v = v->next;
11190       }
11191    }
11192 #endif
11193    
11194    /* Copy the default jb config over global_jbconf */
11195    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11196 
11197    v = ast_variable_browse(cfg, "channels");
11198    res = process_zap(&conf, v, reload, 0);
11199    ast_mutex_unlock(&iflock);
11200    ast_config_destroy(cfg);
11201    if (res)
11202       return res;
11203    cfg = ast_config_load("users.conf");
11204    if (cfg) {
11205       char *cat;
11206       const char *chans;
11207       process_zap(&conf, ast_variable_browse(cfg, "general"), 1, 1);
11208       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11209          if (!strcasecmp(cat, "general"))
11210             continue;
11211          chans = ast_variable_retrieve(cfg, cat, "zapchan");
11212          if (!ast_strlen_zero(chans)) {
11213             /** \todo At this point we should probably 
11214              * duplicate conf, and pass a copy, to prevent 
11215              * one section from affecting another
11216              */
11217             process_zap(&conf, ast_variable_browse(cfg, cat), reload, 0);
11218          }
11219       }
11220       ast_config_destroy(cfg);
11221    }
11222 #ifdef HAVE_PRI
11223    if (!reload) {
11224       for (x = 0; x < NUM_SPANS; x++) {
11225          if (pris[x].pvts[0]) {
11226             if (start_pri(pris + x)) {
11227                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11228                return -1;
11229             } else if (option_verbose > 1)
11230                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11231          }
11232       }
11233    }
11234 #endif
11235    /* And start the monitor for the first time */
11236    restart_monitor();
11237    return 0;
11238 }

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

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

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

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

Definition at line 843 of file chan_zap.c.

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

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

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

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

Definition at line 963 of file chan_zap.c.

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

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

static int unload_module ( void   )  [static]

Definition at line 10338 of file chan_zap.c.

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

10339 {
10340 #ifdef HAVE_PRI      
10341    int y;
10342    for (y = 0; y < NUM_SPANS; y++)
10343       ast_mutex_destroy(&pris[y].lock);
10344 #endif
10345    return __unload_module();
10346 }

static int update_conf ( struct zt_pvt p  )  [static]

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

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

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

Definition at line 783 of file chan_zap.c.

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

Referenced by swap_subs().

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

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

Definition at line 9700 of file chan_zap.c.

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

09701 {
09702    int channel;
09703    
09704    if (argc != 4)
09705       return RESULT_SHOWUSAGE;
09706    
09707    channel = atoi(argv[3]);
09708 
09709    return zap_destroy_channel_bynum(channel);
09710 }

static int zap_destroy_channel_bynum ( int  channel  )  [static]

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

06526 {
06527    struct zt_pvt *tmp = NULL;
06528    struct zt_pvt *prev = NULL;
06529 
06530    tmp = iflist;
06531    while (tmp) {
06532       if (tmp->channel == channel) {
06533          destroy_channel(prev, tmp, 1);
06534          return RESULT_SUCCESS;
06535       }
06536       prev = tmp;
06537       tmp = tmp->next;
06538    }
06539    return RESULT_FAILURE;
06540 }

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

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

10089 {
10090    if (p) {
10091       switch (mode) {
10092          case TRANSFER:
10093             p->fake_event = ZT_EVENT_WINKFLASH;
10094             break;
10095          case HANGUP:
10096             p->fake_event = ZT_EVENT_ONHOOK;
10097             break;
10098          default:
10099             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10100       }
10101    }
10102    return 0;
10103 }

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

Definition at line 813 of file chan_zap.c.

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

Referenced by action_zapdialoffhook().

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

static int zap_restart ( void   )  [static]

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

09714 {
09715    if (option_verbose > 0)
09716       ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
09717    while (iflist) {
09718       if (option_debug)
09719          ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
09720       /* Also updates iflist: */
09721       destroy_channel(NULL, iflist, 1);
09722    }
09723    if (option_debug)
09724       ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
09725    if (setup_zap(0) != 0) {
09726       ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
09727       return 1;
09728    }
09729    return 0;
09730 }

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

Definition at line 9732 of file chan_zap.c.

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

09733 {
09734    if (argc != 2) {
09735       return RESULT_SHOWUSAGE;
09736    }
09737 
09738    if (zap_restart() != 0)
09739       return RESULT_FAILURE;
09740    return RESULT_SUCCESS;
09741 }

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

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

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

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

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

09754 {
09755 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
09756 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
09757    struct zt_pvt *tmp = NULL;
09758    char tmps[20] = "";
09759    ast_mutex_t *lock;
09760    struct zt_pvt *start;
09761 #ifdef HAVE_PRI
09762    int trunkgroup;
09763    struct zt_pri *pri = NULL;
09764    int x;
09765 #endif
09766 
09767    lock = &iflock;
09768    start = iflist;
09769 
09770 #ifdef HAVE_PRI
09771    if (argc == 4) {
09772       if ((trunkgroup = atoi(argv[3])) < 1)
09773          return RESULT_SHOWUSAGE;
09774       for (x = 0; x < NUM_SPANS; x++) {
09775          if (pris[x].trunkgroup == trunkgroup) {
09776             pri = pris + x;
09777             break;
09778          }
09779       }
09780       if (pri) {
09781          start = pri->crvs;
09782          lock = &pri->lock;
09783       } else {
09784          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
09785          return RESULT_FAILURE;
09786       }
09787    } else
09788 #endif
09789    if (argc != 3)
09790       return RESULT_SHOWUSAGE;
09791 
09792    ast_mutex_lock(lock);
09793 #ifdef HAVE_PRI
09794    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
09795 #else
09796    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
09797 #endif   
09798    
09799    tmp = start;
09800    while (tmp) {
09801       if (tmp->channel > 0) {
09802          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
09803       } else
09804          ast_copy_string(tmps, "pseudo", sizeof(tmps));
09805       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
09806       tmp = tmp->next;
09807    }
09808    ast_mutex_unlock(lock);
09809    return RESULT_SUCCESS;
09810 #undef FORMAT
09811 #undef FORMAT2
09812 }

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

Definition at line 9975 of file chan_zap.c.

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

09975                                                            {
09976    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
09977    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
09978 
09979    int span;
09980    int res;
09981    char alarms[50];
09982 
09983    int ctl;
09984    ZT_SPANINFO s;
09985 
09986    ctl = open("/dev/zap/ctl", O_RDWR);
09987    if (ctl < 0) {
09988       ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
09989       ast_cli(fd, "No Zaptel interface found.\n");
09990       return RESULT_FAILURE;
09991    }
09992    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
09993 
09994    for (span = 1; span < ZT_MAX_SPANS; ++span) {
09995       s.spanno = span;
09996       res = ioctl(ctl, ZT_SPANSTAT, &s);
09997       if (res) {
09998          continue;
09999       }
10000       alarms[0] = '\0';
10001       if (s.alarms > 0) {
10002          if (s.alarms & ZT_ALARM_BLUE)
10003             strcat(alarms, "BLU/");
10004          if (s.alarms & ZT_ALARM_YELLOW)
10005             strcat(alarms, "YEL/");
10006          if (s.alarms & ZT_ALARM_RED)
10007             strcat(alarms, "RED/");
10008          if (s.alarms & ZT_ALARM_LOOPBACK)
10009             strcat(alarms, "LB/");
10010          if (s.alarms & ZT_ALARM_RECOVER)
10011             strcat(alarms, "REC/");
10012          if (s.alarms & ZT_ALARM_NOTOPEN)
10013             strcat(alarms, "NOP/");
10014          if (!strlen(alarms))
10015             strcat(alarms, "UUU/");
10016          if (strlen(alarms)) {
10017             /* Strip trailing / */
10018             alarms[strlen(alarms) - 1] = '\0';
10019          }
10020       } else {
10021          if (s.numchans)
10022             strcpy(alarms, "OK");
10023          else
10024             strcpy(alarms, "UNCONFIGURED");
10025       }
10026 
10027       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10028    }
10029    close(ctl);
10030 
10031    return RESULT_SUCCESS;
10032 #undef FORMAT
10033 #undef FORMAT2
10034 }

static char* zap_sig2str ( int  sig  )  [static]

Definition at line 1159 of file chan_zap.c.

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

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

static int zt_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

static int zt_callwait ( struct ast_channel ast  )  [static]

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

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

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

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

Referenced by setup_zap().

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

static void zt_close ( int  fd  )  [static]

Definition at line 912 of file chan_zap.c.

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

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

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

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

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

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

Definition at line 999 of file chan_zap.c.

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

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

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

Definition at line 1059 of file chan_zap.c.

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

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

static void zt_disable_ec ( struct zt_pvt p  )  [static]

Definition at line 1455 of file chan_zap.c.

References ast_log(), zt_pvt::channel, zt_pvt::echocancel, zt_pvt::echocanon, LOG_DEBUG, LOG_WARNING, 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
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 1406 of file chan_zap.c.

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

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

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

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

04578 {
04579    struct zt_pvt *p = ast->tech_pvt;
04580    struct ast_frame *f;
04581    ast_mutex_lock(&p->lock);
04582    f = __zt_exception(ast);
04583    ast_mutex_unlock(&p->lock);
04584    return f;
04585 }

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

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

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

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

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

02995 {
02996    struct zt_pvt *p = chan->tech_pvt;
02997    
02998    if (!strcasecmp(data, "rxgain")) {
02999       ast_mutex_lock(&p->lock);
03000       snprintf(buf, len, "%f", p->rxgain);
03001       ast_mutex_unlock(&p->lock);   
03002    } else if (!strcasecmp(data, "txgain")) {
03003       ast_mutex_lock(&p->lock);
03004       snprintf(buf, len, "%f", p->txgain);
03005       ast_mutex_unlock(&p->lock);   
03006    } else {
03007       ast_copy_string(buf, "", len);
03008    }
03009    return 0;
03010 }

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

Avoid the silly zt_getevent which ignores a bunch of events.

Definition at line 256 of file chan_zap.c.

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

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

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

Definition at line 763 of file chan_zap.c.

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

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

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

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

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

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

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

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

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

static int zt_hangup ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

Definition at line 3071 of file chan_zap.c.

References ast_log(), LOG_WARNING, and master.

Referenced by zt_bridge().

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

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

Definition at line 5155 of file chan_zap.c.

References accountcode, zt_pvt::accountcode, zt_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, zt_pvt::amaflags, asprintf, 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_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), zt_pvt::busy_quietlength, zt_pvt::busy_tonelength, zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::call_forward, zt_pvt::callgroup, ast_channel::callgroup, zt_pvt::callingpres, zt_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, zt_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, zt_pvt::cid_name, ast_callerid::cid_num, zt_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, zt_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, zt_pvt::context, zt_pvt::digital, zt_pvt::dnid, zt_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, zt_pvt::dsp_features, DSP_PROGRESS_TALK, zt_pvt::dtmfrelax, ast_channel::exten, zt_pvt::exten, zt_pvt::fake_event, ast_channel::fds, free, global_jbconf, zt_pvt::hardwaredtmf, language, zt_pvt::language, zt_subchannel::linear, LOG_DEBUG, 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().

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

static int zt_open ( char *  fn  )  [static]

Definition at line 871 of file chan_zap.c.

References ast_log(), LOG_WARNING, and READ_SIZE.

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

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

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

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

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

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

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

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

static int zt_ring_phone ( struct zt_pvt p  )  [static]

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

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

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

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

11288 {
11289 #define  END_SILENCE_LEN 400
11290 #define  HEADER_MS 50
11291 #define  TRAILER_MS 5
11292 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11293 #define  ASCII_BYTES_PER_CHAR 80
11294 
11295    unsigned char *buf,*mybuf;
11296    struct zt_pvt *p = c->tech_pvt;
11297    struct pollfd fds[1];
11298    int size,res,fd,len,x;
11299    int bytes=0;
11300    /* Initial carrier (imaginary) */
11301    float cr = 1.0;
11302    float ci = 0.0;
11303    float scont = 0.0;
11304    int index;
11305 
11306    index = zt_get_index(c, p, 0);
11307    if (index < 0) {
11308       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
11309       return -1;
11310    }
11311    if (!text[0]) return(0); /* if nothing to send, dont */
11312    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
11313    if (p->mate) 
11314       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11315    else
11316       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11317    if (!buf)
11318       return -1;
11319    mybuf = buf;
11320    if (p->mate) {
11321       int codec = AST_LAW(p);
11322       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
11323          PUT_CLID_MARKMS;
11324       }
11325       /* Put actual message */
11326       for (x = 0; text[x]; x++) {
11327          PUT_CLID(text[x]);
11328       }
11329       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
11330          PUT_CLID_MARKMS;
11331       }
11332       len = bytes;
11333       buf = mybuf;
11334    } else {
11335       len = tdd_generate(p->tdd, buf, text);
11336       if (len < 1) {
11337          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11338          free(mybuf);
11339          return -1;
11340       }
11341    }
11342    memset(buf + len, 0x7f, END_SILENCE_LEN);
11343    len += END_SILENCE_LEN;
11344    fd = p->subs[index].zfd;
11345    while (len) {
11346       if (ast_check_hangup(c)) {
11347          free(mybuf);
11348          return -1;
11349       }
11350       size = len;
11351       if (size > READ_SIZE)
11352          size = READ_SIZE;
11353       fds[0].fd = fd;
11354       fds[0].events = POLLOUT | POLLPRI;
11355       fds[0].revents = 0;
11356       res = poll(fds, 1, -1);
11357       if (!res) {
11358          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11359          continue;
11360       }
11361         /* if got exception */
11362       if (fds[0].revents & POLLPRI)
11363          return -1;
11364       if (!(fds[0].revents & POLLOUT)) {
11365          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11366          continue;
11367       }
11368       res = write(fd, buf, size);
11369       if (res != size) {
11370          if (res == -1) {
11371             free(mybuf);
11372             return -1;
11373          }
11374          if (option_debug)
11375             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11376          break;
11377       }
11378       len -= size;
11379       buf += size;
11380    }
11381    free(mybuf);
11382    return(0);
11383 }

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    x = hs;
01611    res = ioctl(fd, ZT_HOOK, &x);
01612    if (res < 0) 
01613    {
01614       if (errno == EINPROGRESS) return 0;
01615       ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
01616    }
01617    return res;
01618 }

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

Definition at line 918 of file chan_zap.c.

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

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

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

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

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

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

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

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

Avoid the silly zt_waitevent which ignores a bunch of events.

Definition at line 265 of file chan_zap.c.

Referenced by flash_exec(), and ss_thread().

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

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

Definition at line 5365 of file chan_zap.c.

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

Referenced by ss_thread().

05366 {
05367    int j;
05368    zt_set_hook(p->subs[index].zfd, ZT_WINK);
05369    for (;;)
05370    {
05371          /* set bits of interest */
05372       j = ZT_IOMUX_SIGEVENT;
05373           /* wait for some happening */
05374       if (ioctl(p->subs[index].zfd,ZT_IOMUX,&j) == -1) return(-1);
05375          /* exit loop if we have it */
05376       if (j & ZT_IOMUX_SIGEVENT) break;
05377    }
05378      /* get the event info */
05379    if (ioctl(p->subs[index].zfd,ZT_GETEVENT,&j) == -1) return(-1);
05380    return 0;
05381 }

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

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

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


Variable Documentation

int alarm

Definition at line 1118 of file chan_zap.c.

Referenced by action_zapshowchannels().

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

Referenced by alarm2str(), and zap_show_status().

struct zt_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 739 of file chan_zap.c.

int cidrings[NUM_CADENCE_MAX] [static]

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

Definition at line 750 of file chan_zap.c.

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

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

int distinctiveringaftercid = 0 [static]

Definition at line 209 of file chan_zap.c.

struct zt_distRings drings [static]

Definition at line 368 of file chan_zap.c.

Referenced by process_zap().

char* events[] [static]

Definition at line 1095 of file chan_zap.c.

Referenced by authenticate(), and geteventbyname().

int firstdigittimeout = 16000 [static]

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

Definition at line 223 of file chan_zap.c.

int gendigittimeout = 8000 [static]

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

Definition at line 226 of file chan_zap.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 115 of file chan_zap.c.

int ifcount = 0 [static]

Definition at line 235 of file chan_zap.c.

struct zt_pvt * ifend [static]

struct zt_pvt * iflist [static]

int matchdigittimeout = 3000 [static]

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

Definition at line 229 of file chan_zap.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

Definition at line 247 of file chan_zap.c.

char* name

Definition at line 1119 of file chan_zap.c.

int num_cadence = 4 [static]

Definition at line 736 of file chan_zap.c.

int numbufs = 4 [static]

Definition at line 211 of file chan_zap.c.

char progzone[10] = "" [static]

Definition at line 206 of file chan_zap.c.

int ringt_base = DEFAULT_RINGT [static]

Definition at line 290 of file chan_zap.c.

struct zt_pvt* round_robin[32]

Definition at line 713 of file chan_zap.c.

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

char* subnames[] [static]

Initial value:

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

Definition at line 381 of file chan_zap.c.

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

Definition at line 158 of file chan_zap.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 208 of file chan_zap.c.

int user_has_defined_cadences = 0 [static]

Definition at line 737 of file chan_zap.c.

struct ast_cli_entry zap_cli[] [static]

Definition at line 10059 of file chan_zap.c.

Referenced by __unload_module(), and load_module().

char zap_restart_usage[] [static]

Definition at line 10052 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 9944 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 10044 of file chan_zap.c.

struct ast_channel_tech zap_tech [static]

Definition at line 686 of file chan_zap.c.

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


Generated on Mon May 14 04:46:31 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1