Mon Apr 30 07:40:05 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 10099 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 10453 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 11418 of file chan_zap.c.

Referenced by load_module().

#define TRAILER_MS   5

Referenced by zt_sendtext().

#define TRANSFER   0

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

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

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

10168 {
10169    struct zt_pvt *p = NULL;
10170    const char *channel = astman_get_header(m, "ZapChannel");
10171 
10172    if (ast_strlen_zero(channel)) {
10173       astman_send_error(s, m, "No channel specified");
10174       return 0;
10175    }
10176    p = find_channel(atoi(channel));
10177    if (!p) {
10178       astman_send_error(s, m, "No such channel");
10179       return 0;
10180    }
10181    zap_fake_event(p,TRANSFER);
10182    astman_send_ack(s, m, "ZapTransfer");
10183    return 0;
10184 }

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

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

10187 {
10188    struct zt_pvt *p = NULL;
10189    const char *channel = astman_get_header(m, "ZapChannel");
10190 
10191    if (ast_strlen_zero(channel)) {
10192       astman_send_error(s, m, "No channel specified");
10193       return 0;
10194    }
10195    p = find_channel(atoi(channel));
10196    if (!p) {
10197       astman_send_error(s, m, "No such channel");
10198       return 0;
10199    }
10200    zap_fake_event(p,HANGUP);
10201    astman_send_ack(s, m, "ZapHangup");
10202    return 0;
10203 }

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

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

10206 {
10207    struct zt_pvt *p = NULL;
10208    const char *channel = astman_get_header(m, "ZapChannel");
10209    const char *number = astman_get_header(m, "Number");
10210    int i;
10211 
10212    if (ast_strlen_zero(channel)) {
10213       astman_send_error(s, m, "No channel specified");
10214       return 0;
10215    }
10216    if (ast_strlen_zero(number)) {
10217       astman_send_error(s, m, "No number specified");
10218       return 0;
10219    }
10220    p = find_channel(atoi(channel));
10221    if (!p) {
10222       astman_send_error(s, m, "No such channel");
10223       return 0;
10224    }
10225    if (!p->owner) {
10226       astman_send_error(s, m, "Channel does not have it's owner");
10227       return 0;
10228    }
10229    for (i = 0; i < strlen(number); i++) {
10230       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10231       zap_queue_frame(p, &f, NULL); 
10232    }
10233    astman_send_ack(s, m, "ZapDialOffhook");
10234    return 0;
10235 }

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

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

10149 {
10150    struct zt_pvt *p = NULL;
10151    const char *channel = astman_get_header(m, "ZapChannel");
10152 
10153    if (ast_strlen_zero(channel)) {
10154       astman_send_error(s, m, "No channel specified");
10155       return 0;
10156    }
10157    p = find_channel(atoi(channel));
10158    if (!p) {
10159       astman_send_error(s, m, "No such channel");
10160       return 0;
10161    }
10162    p->dnd = 0;
10163    astman_send_ack(s, m, "DND Disabled");
10164    return 0;
10165 }

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

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

10130 {
10131    struct zt_pvt *p = NULL;
10132    const char *channel = astman_get_header(m, "ZapChannel");
10133 
10134    if (ast_strlen_zero(channel)) {
10135       astman_send_error(s, m, "No channel specified");
10136       return 0;
10137    }
10138    p = find_channel(atoi(channel));
10139    if (!p) {
10140       astman_send_error(s, m, "No such channel");
10141       return 0;
10142    }
10143    p->dnd = 1;
10144    astman_send_ack(s, m, "DND Enabled");
10145    return 0;
10146 }

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

Definition at line 9756 of file chan_zap.c.

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

Referenced by load_module().

09757 {
09758    if (zap_restart() != 0) {
09759       astman_send_error(s, m, "Failed rereading zaptel configuration");
09760       return 1;
09761    }
09762    astman_send_ack(s, m, "ZapRestart: Success");
09763    return 0;
09764 }

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

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

10238 {
10239    struct zt_pvt *tmp = NULL;
10240    const char *id = astman_get_header(m, "ActionID");
10241    char idText[256] = "";
10242 
10243    astman_send_ack(s, m, "Zapata channel status will follow");
10244    if (!ast_strlen_zero(id))
10245       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10246 
10247    ast_mutex_lock(&iflock);
10248    
10249    tmp = iflist;
10250    while (tmp) {
10251       if (tmp->channel > 0) {
10252          int alarm = get_alarms(tmp);
10253          astman_append(s,
10254             "Event: ZapShowChannels\r\n"
10255             "Channel: %d\r\n"
10256             "Signalling: %s\r\n"
10257             "Context: %s\r\n"
10258             "DND: %s\r\n"
10259             "Alarm: %s\r\n"
10260             "%s"
10261             "\r\n",
10262             tmp->channel, sig2str(tmp->sig), tmp->context, 
10263             tmp->dnd ? "Enabled" : "Disabled",
10264             alarm2str(alarm), idText);
10265       } 
10266 
10267       tmp = tmp->next;
10268    }
10269 
10270    ast_mutex_unlock(&iflock);
10271    
10272    astman_append(s, 
10273       "Event: ZapShowChannelsComplete\r\n"
10274       "%s"
10275       "\r\n", 
10276       idText);
10277    return 0;
10278 }

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

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

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

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

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

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

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

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

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

10118 {
10119    struct zt_pvt *p = iflist;
10120    while (p) {
10121       if (p->channel == channel) {
10122          break;
10123       }
10124       p = p->next;
10125    }
10126    return p;
10127 }

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

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

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

Definition at line 9961 of file chan_zap.c.

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

09962 {
09963    int i, j;
09964    for (i = 0; i < num_cadence; i++) {
09965       char output[1024];
09966       char tmp[16], tmp2[64];
09967       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
09968       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
09969 
09970       for (j = 0; j < 16; j++) {
09971          if (cadences[i].ringcadence[j] == 0)
09972             break;
09973          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
09974          if (cidrings[i] * 2 - 1 == j)
09975             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
09976          else
09977             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
09978          if (j != 0)
09979             strncat(output, ",", sizeof(output) - strlen(output) - 1);
09980          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
09981       }
09982       ast_cli(fd,"%s\n",output);
09983    }
09984    return 0;
09985 }

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

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

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

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

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

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

Definition at line 5344 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

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

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

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

static int reload ( void   )  [static]

Definition at line 11399 of file chan_zap.c.

References ast_log(), and setup_zap().

11400 {
11401    int res = 0;
11402 
11403    res = setup_zap(1);
11404    if (res) {
11405       ast_log(LOG_WARNING, "Reload of chan_zap.so is unsuccessful!\n");
11406       return -1;
11407    }
11408    return 0;
11409 }

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

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

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

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

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

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

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

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

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

10352 {
10353 #ifdef HAVE_PRI      
10354    int y;
10355    for (y = 0; y < NUM_SPANS; y++)
10356       ast_mutex_destroy(&pris[y].lock);
10357 #endif
10358    return __unload_module();
10359 }

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

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

09714 {
09715    int channel;
09716    
09717    if (argc != 4)
09718       return RESULT_SHOWUSAGE;
09719    
09720    channel = atoi(argv[3]);
09721 
09722    return zap_destroy_channel_bynum(channel);
09723 }

static int zap_destroy_channel_bynum ( int  channel  )  [static]

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

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

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

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

10102 {
10103    if (p) {
10104       switch (mode) {
10105          case TRANSFER:
10106             p->fake_event = ZT_EVENT_WINKFLASH;
10107             break;
10108          case HANGUP:
10109             p->fake_event = ZT_EVENT_ONHOOK;
10110             break;
10111          default:
10112             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10113       }
10114    }
10115    return 0;
10116 }

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

09727 {
09728    if (option_verbose > 0)
09729       ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
09730    while (iflist) {
09731       if (option_debug)
09732          ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
09733       /* Also updates iflist: */
09734       destroy_channel(NULL, iflist, 1);
09735    }
09736    if (option_debug)
09737       ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
09738    if (setup_zap(0) != 0) {
09739       ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
09740       return 1;
09741    }
09742    return 0;
09743 }

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

Definition at line 9745 of file chan_zap.c.

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

09746 {
09747    if (argc != 2) {
09748       return RESULT_SHOWUSAGE;
09749    }
09750 
09751    if (zap_restart() != 0)
09752       return RESULT_FAILURE;
09753    return RESULT_SUCCESS;
09754 }

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

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

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

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

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

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

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

Definition at line 9988 of file chan_zap.c.

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

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

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, zt_pvt::cid_name, ast_callerid::cid_name, zt_pvt::cid_num, ast_callerid::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, 0, 0, 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 (i->busydetect && CANBUSYDETECT(i))
05220       features |= DSP_FEATURE_BUSY_DETECT;
05221    if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05222       features |= DSP_FEATURE_CALL_PROGRESS;
05223    if ((!i->outgoing && (i->callprogress & 4)) || 
05224        (i->outgoing && (i->callprogress & 2))) {
05225       features |= DSP_FEATURE_FAX_DETECT;
05226    }
05227 #ifdef ZT_TONEDETECT
05228    x = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
05229    if (ioctl(i->subs[index].zfd, ZT_TONEDETECT, &x)) {
05230 #endif      
05231       i->hardwaredtmf = 0;
05232       features |= DSP_FEATURE_DTMF_DETECT;
05233 #ifdef ZT_TONEDETECT
05234    } else if (NEED_MFDETECT(i)) {
05235       i->hardwaredtmf = 1;
05236       features |= DSP_FEATURE_DTMF_DETECT;
05237    }
05238 #endif
05239    if (features) {
05240       if (i->dsp) {
05241          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05242       } else {
05243          if (i->channel != CHAN_PSEUDO)
05244             i->dsp = ast_dsp_new();
05245          else
05246             i->dsp = NULL;
05247          if (i->dsp) {
05248             i->dsp_features = features & ~DSP_PROGRESS_TALK;
05249 #ifdef HAVE_PRI
05250             /* We cannot do progress detection until receives PROGRESS message */
05251             if (i->outgoing && (i->sig == SIG_PRI)) {
05252                /* Remember requested DSP features, don't treat
05253                   talking as ANSWER */
05254                features = 0;
05255             }
05256 #endif
05257             ast_dsp_set_features(i->dsp, features);
05258             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05259             if (!ast_strlen_zero(progzone))
05260                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05261             if (i->busydetect && CANBUSYDETECT(i)) {
05262                ast_dsp_set_busy_count(i->dsp, i->busycount);
05263                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
05264             }
05265          }
05266       }
05267    }
05268       
05269    if (state == AST_STATE_RING)
05270       tmp->rings = 1;
05271    tmp->tech_pvt = i;
05272    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05273       /* Only FXO signalled stuff can be picked up */
05274       tmp->callgroup = i->callgroup;
05275       tmp->pickupgroup = i->pickupgroup;
05276    }
05277    if (!ast_strlen_zero(i->language))
05278       ast_string_field_set(tmp, language, i->language);
05279    if (!i->owner)
05280       i->owner = tmp;
05281    if (!ast_strlen_zero(i->accountcode))
05282       ast_string_field_set(tmp, accountcode, i->accountcode);
05283    if (i->amaflags)
05284       tmp->amaflags = i->amaflags;
05285    i->subs[index].owner = tmp;
05286    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05287    ast_string_field_set(tmp, call_forward, i->call_forward);
05288    /* If we've been told "no ADSI" then enforce it */
05289    if (!i->adsi)
05290       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05291    if (!ast_strlen_zero(i->exten))
05292       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05293    if (!ast_strlen_zero(i->rdnis))
05294       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05295    if (!ast_strlen_zero(i->dnid))
05296       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05297 
05298    /* Don't use ast_set_callerid() here because it will
05299     * generate a needless NewCallerID event */
05300 #ifdef PRI_ANI
05301    tmp->cid.cid_num = ast_strdup(i->cid_num);
05302    tmp->cid.cid_name = ast_strdup(i->cid_name);
05303    if (!ast_strlen_zero(i->cid_ani))
05304       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05305    else  
05306       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05307 #else
05308    tmp->cid.cid_num = ast_strdup(i->cid_num);
05309    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05310    tmp->cid.cid_name = ast_strdup(i->cid_name);
05311 #endif
05312    tmp->cid.cid_pres = i->callingpres;
05313    tmp->cid.cid_ton = i->cid_ton;
05314 #ifdef HAVE_PRI
05315    tmp->transfercapability = transfercapability;
05316    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05317    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05318       i->digital = 1;
05319    /* Assume calls are not idle calls unless we're told differently */
05320    i->isidlecall = 0;
05321    i->alreadyhungup = 0;
05322 #endif
05323    /* clear the fake event in case we posted one before we had ast_channel */
05324    i->fake_event = 0;
05325    /* Assure there is no confmute on this channel */
05326    zt_confmute(i, 0);
05327    /* Configure the new channel jb */
05328    ast_jb_configure(tmp, &global_jbconf);
05329    if (startpbx) {
05330       if (ast_pbx_start(tmp)) {
05331          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05332          ast_hangup(tmp);
05333          i->owner = NULL;
05334          return NULL;
05335       }
05336    }
05337 
05338    ast_module_ref(ast_module_info->self);
05339    
05340    return tmp;
05341 }

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

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

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

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

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

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

Referenced by ss_thread().

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

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 10061 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 10053 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 10049 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 10072 of file chan_zap.c.

Referenced by __unload_module(), and load_module().

char zap_restart_usage[] [static]

Definition at line 10065 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 9957 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 10057 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 Apr 30 07:40:08 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1