Thu Oct 8 21:56:21 2009

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   ZT_MAX_SPANS
#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_GSM   (0x100000 | ZT_SIG_CLEAR)
#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)
static int app_zapEC (struct ast_channel *chan, void *data)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,.load=load_module,.unload=unload_module,.reload=reload,)
 AST_MUTEX_DEFINE_STATIC (monlock)
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
 AST_MUTEX_DEFINE_STATIC (iflock)
 Protect the interface list (of zt_pvt's).
static int attempt_transfer (struct zt_pvt *p)
static int available (struct zt_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct zt_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct zt_pvt *p)
static struct zt_pvtchandup (struct zt_pvt *src)
static int check_for_conference (struct zt_pvt *p)
static int conf_add (struct zt_pvt *p, struct zt_subchannel *c, int index, int slavechannel)
static int conf_del (struct zt_pvt *p, struct zt_subchannel *c, int index)
static int destroy_channel (struct zt_pvt *prev, struct zt_pvt *cur, int now)
static void destroy_zt_pvt (struct zt_pvt **pvt)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct zt_pvt *p)
static void * do_monitor (void *data)
static void enable_dtmf_detect (struct zt_pvt *p)
static char * event2str (int event)
static void fill_rxgain (struct zt_gains *g, float gain, int law)
static void fill_txgain (struct zt_gains *g, float gain, int law)
static struct zt_pvtfind_channel (int channel)
static int get_alarms (struct zt_pvt *p)
static int handle_init_event (struct zt_pvt *i, int event)
static int handle_zap_show_cadences (int fd, int argc, char *argv[])
static int has_voicemail (struct zt_pvt *p)
static int isourconf (struct zt_pvt *p, struct zt_subchannel *c)
static int isslavenative (struct zt_pvt *p, struct zt_pvt **out)
static int load_module (void)
static struct zt_pvtmkintf (int channel, const struct zt_chan_conf *conf, struct zt_pri *pri, int reloading)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static int my_zt_write (struct zt_pvt *p, unsigned char *buf, int len, int index, int linear)
static int 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_sendmessage (struct ast_channel *c, const char *dest, const char *text, int ispdu)
static int zt_sendtext (struct ast_channel *c, const char *text)
static int zt_set_hook (int fd, int hs)
static int zt_setlaw (int zfd, int law)
static int zt_setlinear (int zfd, int linear)
static int zt_setoption (struct ast_channel *chan, int option, void *data, int datalen)
static int zt_tdd_sendtext (struct ast_channel *c, const char *text)
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 char gsm_modem_exten [AST_MAX_EXTENSION]
static char gsm_modem_pin [20]
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
struct zt_pvtround_robin [32]
static char show_channel_usage []
static char show_channels_usage []
static char * subnames []
static const char tdesc [] = "Zapata Telephony Driver"
static int user_has_defined_cadences = 0
static struct ast_cli_entry zap_cli []
static char zap_restart_usage []
static char zap_show_cadences_help []
static char zap_show_status_usage []
static struct ast_channel_tech zap_tech
static char * zapEC_app = "zapEC"
static char * zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel"
static char * zapEC_tdesc = "Enable/disable Echo cancelation"


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

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

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

10,000 ms

Definition at line 290 of file chan_zap.c.

Referenced by zt_callwait().

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

300 ms

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

Referenced by zt_handle_event(), and zt_new().

#define CHAN_PSEUDO   -2

Definition at line 205 of file chan_zap.c.

Referenced by build_channels(), enable_dtmf_detect(), mkintf(), process_zap(), zt_new(), and zt_request().

#define CHANNEL_PSEUDO   -12

Definition at line 160 of file chan_zap.c.

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

500 ms

Definition at line 291 of file chan_zap.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 440 of file chan_zap.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 441 of file chan_zap.c.

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 211 of file chan_zap.c.

Referenced by mkintf().

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 208 of file chan_zap.c.

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 207 of file chan_zap.c.

#define DCHAN_UP   (1 << 2)

Definition at line 209 of file chan_zap.c.

#define DEFAULT_CIDRINGS   1

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

Note:
Define ZHONE_HACK to cause us to go off hook and then back on hook when the user hangs up to reset the state machine so ring works properly. This is used to be able to support kewlstart by putting the zhone in groundstart mode since their forward disconnect supervision is entirely broken even though their documentation says it isn't and their support is entirely unwilling to provide any assistance with their channel banks even though their web site says they support their products for life.

Define if you want to check the hook state for an FXO (FXS signalled) interface before dialing on it. Certain FXO interfaces always think they're out of service with this method however.

Definition at line 158 of file chan_zap.c.

Referenced by zt_chan_conf_default().

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

8,000 ms

Definition at line 293 of file chan_zap.c.

#define END_SILENCE_LEN   400

Referenced by zt_tdd_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 764 of file chan_zap.c.

Referenced by update_conf().

#define HANGUP   1

Definition at line 11544 of file chan_zap.c.

Referenced by action_transferhangup(), and zap_fake_event().

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

#define HEADER_MS   50

Referenced by zt_tdd_sendtext().

#define ISTRUNK (  ) 

Value:

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

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

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_zap().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 203 of file chan_zap.c.

Referenced by mkintf().

#define MAX_SLAVES   4

Definition at line 443 of file chan_zap.c.

Referenced by isslavenative(), update_conf(), zap_show_channel(), zt_link(), and zt_unlink().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

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

Referenced by ss_thread(), and zt_new().

#define NUM_CADENCE_MAX   25

Definition at line 793 of file chan_zap.c.

Referenced by process_zap().

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 202 of file chan_zap.c.

#define NUM_SPANS   ZT_MAX_SPANS

Definition at line 201 of file chan_zap.c.

#define POLARITY_IDLE   0

Definition at line 397 of file chan_zap.c.

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

#define POLARITY_REV   1

Definition at line 398 of file chan_zap.c.

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

#define READ_SIZE   160

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

Definition at line 284 of file chan_zap.c.

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

#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)

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

Referenced by handle_init_event(), mkintf(), process_zap(), and zap_sig2str().

#define SIG_GSM   (0x100000 | ZT_SIG_CLEAR)

#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

Definition at line 114 of file chan_zap.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 393 of file chan_zap.c.

#define SUB_REAL   0

Active call

Definition at line 392 of file chan_zap.c.

#define SUB_THREEWAY   2

Three-way call

Definition at line 394 of file chan_zap.c.

#define tdesc   "Zapata Telephony"

Definition at line 12994 of file chan_zap.c.

#define TRAILER_MS   5

Referenced by zt_tdd_sendtext().

#define TRANSFER   0

Definition at line 11543 of file chan_zap.c.

Referenced by action_transfer(), and zap_fake_event().

#define ZT_EVENT_DTMFDOWN   0

Definition at line 132 of file chan_zap.c.

Referenced by zt_handle_event().

#define ZT_EVENT_DTMFUP   0

Definition at line 133 of file chan_zap.c.

Referenced by zt_handle_event().


Function Documentation

static int __unload_module ( void   )  [static]

Definition at line 11725 of file chan_zap.c.

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

11726 {
11727    int x;
11728    struct zt_pvt *p, *pl;
11729 
11730 #ifdef HAVE_PRI
11731    int i;
11732    for (i = 0; i < NUM_SPANS; i++) {
11733       if (pris[i].master != AST_PTHREADT_NULL) 
11734          pthread_cancel(pris[i].master);
11735    }
11736    ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
11737    ast_unregister_application(zap_send_keypad_facility_app);
11738    ast_unregister_application(zapCD_app);
11739    ast_unregister_application(zapInband_app);
11740 #endif
11741 #ifdef HAVE_GSMAT
11742    ast_cli_unregister_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
11743    ast_cli_unregister(&gsm_send_sms);
11744    ast_cli_unregister(&gsm_send_pdu);
11745    ast_cli_unregister(&gsm_show_status);
11746 #endif
11747    ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
11748    ast_unregister_application(zapEC_app);
11749    ast_manager_unregister( "ZapDialOffhook" );
11750    ast_manager_unregister( "ZapHangup" );
11751    ast_manager_unregister( "ZapTransfer" );
11752    ast_manager_unregister( "ZapDNDoff" );
11753    ast_manager_unregister( "ZapDNDon" );
11754    ast_manager_unregister("ZapShowChannels");
11755    ast_manager_unregister("ZapRestart");
11756    ast_channel_unregister(&zap_tech);
11757    ast_mutex_lock(&iflock);
11758    /* Hangup all interfaces if they have an owner */
11759    p = iflist;
11760    while (p) {
11761       if (p->owner)
11762          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
11763       p = p->next;
11764    }
11765    ast_mutex_unlock(&iflock);
11766    ast_mutex_lock(&monlock);
11767    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11768       pthread_cancel(monitor_thread);
11769       pthread_kill(monitor_thread, SIGURG);
11770       pthread_join(monitor_thread, NULL);
11771    }
11772    monitor_thread = AST_PTHREADT_STOP;
11773    ast_mutex_unlock(&monlock);
11774 
11775    ast_mutex_lock(&iflock);
11776    /* Destroy all the interfaces and free their memory */
11777    p = iflist;
11778    while (p) {
11779       /* Free any callerid */
11780       if (p->cidspill)
11781          free(p->cidspill);
11782       /* Close the zapata thingy */
11783       if (p->subs[SUB_REAL].zfd > -1)
11784          zt_close(p->subs[SUB_REAL].zfd);
11785       pl = p;
11786       p = p->next;
11787       x = pl->channel;
11788       /* Free associated memory */
11789       if (pl)
11790          destroy_zt_pvt(&pl);
11791       ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
11792    }
11793    iflist = NULL;
11794    ifcount = 0;
11795    ast_mutex_unlock(&iflock);
11796 #ifdef HAVE_PRI      
11797    for (i = 0; i < NUM_SPANS; i++) {
11798       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
11799          pthread_join(pris[i].master, NULL);
11800       zt_close(pris[i].fds[i]);
11801    }
11802 #endif
11803    return 0;
11804 }

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

Definition at line 4668 of file chan_zap.c.

References ast_channel::_state, 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::callwaitingrepeat, zt_pvt::channel, zt_pvt::cidcwexpire, ast_frame::data, ast_frame::datalen, ast_frame::delivery, zt_pvt::dialing, event2str(), zt_subchannel::f, zt_pvt::fake_event, ast_channel::fds, zt_pvt::flashtime, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, zt_subchannel::needanswer, zt_subchannel::needunhold, ast_frame::offset, zt_pvt::oprmode, option_debug, option_verbose, zt_subchannel::owner, zt_pvt::owner, zt_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, zt_pvt::subs, ast_channel::tech_pvt, update_conf(), VERBOSE_PREFIX_3, zt_subchannel::zfd, zt_disable_ec(), zt_enable_ec(), zt_get_event(), zt_get_index(), zt_handle_event(), zt_ring_phone(), and zt_set_hook().

Referenced by zt_exception(), and zt_read().

04669 {
04670    struct zt_pvt *p = ast->tech_pvt;
04671    int res;
04672    int usedindex=-1;
04673    int index;
04674    struct ast_frame *f;
04675 
04676 
04677    index = zt_get_index(ast, p, 1);
04678    
04679    p->subs[index].f.frametype = AST_FRAME_NULL;
04680    p->subs[index].f.datalen = 0;
04681    p->subs[index].f.samples = 0;
04682    p->subs[index].f.mallocd = 0;
04683    p->subs[index].f.offset = 0;
04684    p->subs[index].f.subclass = 0;
04685    p->subs[index].f.delivery = ast_tv(0,0);
04686    p->subs[index].f.src = "zt_exception";
04687    p->subs[index].f.data = NULL;
04688    
04689    
04690    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04691       /* If nobody owns us, absorb the event appropriately, otherwise
04692          we loop indefinitely.  This occurs when, during call waiting, the
04693          other end hangs up our channel so that it no longer exists, but we
04694          have neither FLASH'd nor ONHOOK'd to signify our desire to
04695          change to the other channel. */
04696       if (p->fake_event) {
04697          res = p->fake_event;
04698          p->fake_event = 0;
04699       } else
04700          res = zt_get_event(p->subs[SUB_REAL].zfd);
04701       /* Switch to real if there is one and this isn't something really silly... */
04702       if ((res != ZT_EVENT_RINGEROFF) && (res != ZT_EVENT_RINGERON) &&
04703          (res != ZT_EVENT_HOOKCOMPLETE)) {
04704          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04705          p->owner = p->subs[SUB_REAL].owner;
04706          if (p->owner && ast_bridged_channel(p->owner))
04707             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04708          p->subs[SUB_REAL].needunhold = 1;
04709       }
04710       switch (res) {
04711       case ZT_EVENT_ONHOOK:
04712          zt_disable_ec(p);
04713          if (p->owner) {
04714             if (option_verbose > 2) 
04715                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
04716             zt_ring_phone(p);
04717             p->callwaitingrepeat = 0;
04718             p->cidcwexpire = 0;
04719          } else
04720             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04721          update_conf(p);
04722          break;
04723       case ZT_EVENT_RINGOFFHOOK:
04724          zt_enable_ec(p);
04725          zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
04726          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
04727             p->subs[SUB_REAL].needanswer = 1;
04728             p->dialing = 0;
04729          }
04730          break;
04731       case ZT_EVENT_HOOKCOMPLETE:
04732       case ZT_EVENT_RINGERON:
04733       case ZT_EVENT_RINGEROFF:
04734          /* Do nothing */
04735          break;
04736       case ZT_EVENT_WINKFLASH:
04737          gettimeofday(&p->flashtime, NULL);
04738          if (p->owner) {
04739             if (option_verbose > 2) 
04740                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
04741             if (p->owner->_state != AST_STATE_UP) {
04742                /* Answer if necessary */
04743                usedindex = zt_get_index(p->owner, p, 0);
04744                if (usedindex > -1) {
04745                   p->subs[usedindex].needanswer = 1;
04746                }
04747                ast_setstate(p->owner, AST_STATE_UP);
04748             }
04749             p->callwaitingrepeat = 0;
04750             p->cidcwexpire = 0;
04751             if (ast_bridged_channel(p->owner))
04752                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04753             p->subs[SUB_REAL].needunhold = 1;
04754          } else
04755             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04756          update_conf(p);
04757          break;
04758       default:
04759          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
04760       }
04761       f = &p->subs[index].f;
04762       return f;
04763    }
04764    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
04765       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
04766    /* If it's not us, return NULL immediately */
04767    if (ast != p->owner) {
04768       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
04769       f = &p->subs[index].f;
04770       return f;
04771    }
04772    f = zt_handle_event(ast);
04773    return f;
04774 }

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

Definition at line 11612 of file chan_zap.c.

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

Referenced by load_module().

11613 {
11614    struct zt_pvt *p = NULL;
11615    const char *channel = astman_get_header(m, "ZapChannel");
11616 
11617    if (ast_strlen_zero(channel)) {
11618       astman_send_error(s, m, "No channel specified");
11619       return 0;
11620    }
11621    p = find_channel(atoi(channel));
11622    if (!p) {
11623       astman_send_error(s, m, "No such channel");
11624       return 0;
11625    }
11626    zap_fake_event(p,TRANSFER);
11627    astman_send_ack(s, m, "ZapTransfer");
11628    return 0;
11629 }

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

Definition at line 11631 of file chan_zap.c.

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

Referenced by load_module().

11632 {
11633    struct zt_pvt *p = NULL;
11634    const char *channel = astman_get_header(m, "ZapChannel");
11635 
11636    if (ast_strlen_zero(channel)) {
11637       astman_send_error(s, m, "No channel specified");
11638       return 0;
11639    }
11640    p = find_channel(atoi(channel));
11641    if (!p) {
11642       astman_send_error(s, m, "No such channel");
11643       return 0;
11644    }
11645    zap_fake_event(p,HANGUP);
11646    astman_send_ack(s, m, "ZapHangup");
11647    return 0;
11648 }

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

Definition at line 11650 of file chan_zap.c.

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

Referenced by load_module().

11651 {
11652    struct zt_pvt *p = NULL;
11653    const char *channel = astman_get_header(m, "ZapChannel");
11654    const char *number = astman_get_header(m, "Number");
11655    int i;
11656 
11657    if (ast_strlen_zero(channel)) {
11658       astman_send_error(s, m, "No channel specified");
11659       return 0;
11660    }
11661    if (ast_strlen_zero(number)) {
11662       astman_send_error(s, m, "No number specified");
11663       return 0;
11664    }
11665    p = find_channel(atoi(channel));
11666    if (!p) {
11667       astman_send_error(s, m, "No such channel");
11668       return 0;
11669    }
11670    if (!p->owner) {
11671       astman_send_error(s, m, "Channel does not have it's owner");
11672       return 0;
11673    }
11674    for (i = 0; i < strlen(number); i++) {
11675       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
11676       zap_queue_frame(p, &f, NULL); 
11677    }
11678    astman_send_ack(s, m, "ZapDialOffhook");
11679    return 0;
11680 }

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

Definition at line 11593 of file chan_zap.c.

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

Referenced by load_module().

11594 {
11595    struct zt_pvt *p = NULL;
11596    const char *channel = astman_get_header(m, "ZapChannel");
11597 
11598    if (ast_strlen_zero(channel)) {
11599       astman_send_error(s, m, "No channel specified");
11600       return 0;
11601    }
11602    p = find_channel(atoi(channel));
11603    if (!p) {
11604       astman_send_error(s, m, "No such channel");
11605       return 0;
11606    }
11607    p->dnd = 0;
11608    astman_send_ack(s, m, "DND Disabled");
11609    return 0;
11610 }

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

Definition at line 11574 of file chan_zap.c.

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

Referenced by load_module().

11575 {
11576    struct zt_pvt *p = NULL;
11577    const char *channel = astman_get_header(m, "ZapChannel");
11578 
11579    if (ast_strlen_zero(channel)) {
11580       astman_send_error(s, m, "No channel specified");
11581       return 0;
11582    }
11583    p = find_channel(atoi(channel));
11584    if (!p) {
11585       astman_send_error(s, m, "No such channel");
11586       return 0;
11587    }
11588    p->dnd = 1;
11589    astman_send_ack(s, m, "DND Enabled");
11590    return 0;
11591 }

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

Definition at line 11201 of file chan_zap.c.

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

Referenced by load_module().

11202 {
11203    if (zap_restart() != 0) {
11204       astman_send_error(s, m, "Failed rereading zaptel configuration");
11205       return 1;
11206    }
11207    astman_send_ack(s, m, "ZapRestart: Success");
11208    return 0;
11209 }

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

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

Referenced by load_module().

11683 {
11684    struct zt_pvt *tmp = NULL;
11685    const char *id = astman_get_header(m, "ActionID");
11686    char idText[256] = "";
11687 
11688    astman_send_ack(s, m, "Zapata channel status will follow");
11689    if (!ast_strlen_zero(id))
11690       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
11691 
11692    ast_mutex_lock(&iflock);
11693    
11694    tmp = iflist;
11695    while (tmp) {
11696       if (tmp->channel > 0) {
11697          int alarm = get_alarms(tmp);
11698          astman_append(s,
11699             "Event: ZapShowChannels\r\n"
11700             "Channel: %d\r\n"
11701             "Signalling: %s\r\n"
11702             "Context: %s\r\n"
11703             "DND: %s\r\n"
11704             "Alarm: %s\r\n"
11705             "%s"
11706             "\r\n",
11707             tmp->channel, sig2str(tmp->sig), tmp->context, 
11708             tmp->dnd ? "Enabled" : "Disabled",
11709             alarm2str(alarm), idText);
11710       } 
11711 
11712       tmp = tmp->next;
11713    }
11714 
11715    ast_mutex_unlock(&iflock);
11716    
11717    astman_append(s, 
11718       "Event: ZapShowChannelsComplete\r\n"
11719       "%s"
11720       "\r\n", 
11721       idText);
11722    return 0;
11723 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1190 of file chan_zap.c.

References alarms.

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

01191 {
01192    int x;
01193    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01194       if (alarms[x].alarm & alarm)
01195          return alarms[x].name;
01196    }
01197    return alarm ? "Unknown Alarm" : "No Alarm";
01198 }

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

Definition at line 988 of file chan_zap.c.

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

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

00989 {
00990    ZT_BUFFERINFO bi;
00991    int res;
00992    if (p->subs[x].zfd < 0) {
00993       p->subs[x].zfd = zt_open("/dev/zap/pseudo");
00994       if (p->subs[x].zfd > -1) {
00995          res = ioctl(p->subs[x].zfd, ZT_GET_BUFINFO, &bi);
00996          if (!res) {
00997             bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
00998             bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
00999             bi.numbufs = numbufs;
01000             res = ioctl(p->subs[x].zfd, ZT_SET_BUFINFO, &bi);
01001             if (res < 0) {
01002                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", x);
01003             }
01004          } else 
01005             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", x);
01006          if (ioctl(p->subs[x].zfd, ZT_CHANNO, &p->subs[x].chan) == 1) {
01007             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d\n", p->subs[x].zfd);
01008             zt_close(p->subs[x].zfd);
01009             p->subs[x].zfd = -1;
01010             return -1;
01011          }
01012          if (option_debug)
01013             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
01014          return 0;
01015       } else
01016          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01017       return -1;
01018    }
01019    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01020    return -1;
01021 }

static int app_zapEC ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 11120 of file chan_zap.c.

References ast_log(), ast_verbose(), LOG_WARNING, option_verbose, ast_channel::tech, ast_channel::tech_pvt, ast_channel_tech::type, VERBOSE_PREFIX_3, zt_disable_ec(), and zt_enable_ec().

Referenced by load_module().

11121 {
11122  int res=-1;
11123  struct zt_pvt *p = NULL;
11124 
11125  if (!data) {
11126    ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
11127  }
11128  if (chan && !strcasecmp("ZAP",chan->tech->type)) {
11129    p = chan->tech_pvt;
11130    if (!p) return res;
11131    if (!strcasecmp("on",(char *)data)) {
11132        zt_enable_ec(p);
11133        res = 0;
11134        if (option_verbose > 3) {
11135       ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
11136        }
11137    } else if (!strcasecmp("off",(char *)data)) {
11138        zt_disable_ec(p);
11139        res = 0;
11140        if (option_verbose > 3) {
11141       ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
11142        }
11143    } else {
11144        ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
11145    }
11146  } else {
11147   ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
11148   res = 0;
11149  }
11150 
11151  return res;
11152 }

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

03650 {
03651    /* In order to transfer, we need at least one of the channels to
03652       actually be in a call bridge.  We can't conference two applications
03653       together (but then, why would we want to?) */
03654    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03655       /* The three-way person we're about to transfer to could still be in MOH, so
03656          stop if now if appropriate */
03657       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03658          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03659       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03660          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03661       }
03662       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03663          tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, ZT_TONE_RINGTONE);
03664       }
03665       if (p->subs[SUB_REAL].owner->cdr) {
03666          /* Move CDR from second channel to current one */
03667          p->subs[SUB_THREEWAY].owner->cdr =
03668             ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr);
03669          p->subs[SUB_REAL].owner->cdr = NULL;
03670       }
03671       if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) {
03672          /* Move CDR from second channel's bridge to current one */
03673          p->subs[SUB_THREEWAY].owner->cdr =
03674             ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr);
03675          ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL;
03676       }
03677        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03678          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03679                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03680          return -1;
03681       }
03682       /* Orphan the channel after releasing the lock */
03683       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03684       unalloc_sub(p, SUB_THREEWAY);
03685    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03686       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03687       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03688          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03689       }
03690       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03691          tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
03692       }
03693       if (p->subs[SUB_THREEWAY].owner->cdr) {
03694          /* Move CDR from second channel to current one */
03695          p->subs[SUB_REAL].owner->cdr = 
03696             ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr);
03697          p->subs[SUB_THREEWAY].owner->cdr = NULL;
03698       }
03699       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) {
03700          /* Move CDR from second channel's bridge to current one */
03701          p->subs[SUB_REAL].owner->cdr = 
03702             ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr);
03703          ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL;
03704       }
03705       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03706          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03707                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03708          return -1;
03709       }
03710       /* Three-way is now the REAL */
03711       swap_subs(p, SUB_THREEWAY, SUB_REAL);
03712       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03713       unalloc_sub(p, SUB_THREEWAY);
03714       /* Tell the caller not to hangup */
03715       return 1;
03716    } else {
03717       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03718                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03719       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03720       return -1;
03721    }
03722    return 0;
03723 }

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

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

07866 {
07867    int res;
07868    ZT_PARAMS par;
07869 
07870    /* First, check group matching */
07871    if (groupmatch) {
07872       if ((p->group & groupmatch) != groupmatch)
07873          return 0;
07874       *groupmatched = 1;
07875    }
07876    /* Check to see if we have a channel match */
07877    if (channelmatch != -1) {
07878       if (p->channel != channelmatch)
07879          return 0;
07880       *channelmatched = 1;
07881    }
07882    /* We're at least busy at this point */
07883    if (busy) {
07884       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07885          *busy = 1;
07886    }
07887    /* If do not disturb, definitely not */
07888    if (p->dnd)
07889       return 0;
07890    /* If guard time, definitely not */
07891    if (p->guardtime && (time(NULL) < p->guardtime)) 
07892       return 0;
07893       
07894    /* If no owner definitely available */
07895    if (!p->owner) {
07896 #ifdef HAVE_PRI
07897       /* Trust PRI */
07898       if (p->pri) {
07899          if (p->resetting || p->call)
07900             return 0;
07901          else
07902             return 1;
07903       }
07904 #endif
07905 #ifdef HAVE_GSMAT
07906       if (p->gsm.modul) {
07907           return gsm_available(p->gsm.modul);
07908       }
07909 
07910 #endif
07911       if (!(p->radio || (p->oprmode < 0)))
07912       {
07913          if (!p->sig || (p->sig == SIG_FXSLS))
07914             return 1;
07915          /* Check hook state */
07916          if (p->subs[SUB_REAL].zfd > -1)
07917             res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
07918          else {
07919             /* Assume not off hook on CVRS */
07920             res = 0;
07921             par.rxisoffhook = 0;
07922          }
07923          if (res) {
07924             ast_log(LOG_WARNING, "Unable to check hook state on channel %d\n", p->channel);
07925          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07926             /* When "onhook" that means no battery on the line, and thus
07927               it is out of service..., if it's on a TDM card... If it's a channel
07928               bank, there is no telling... */
07929             if (par.rxbits > -1)
07930                return 1;
07931             if (par.rxisoffhook)
07932                return 1;
07933             else
07934 #ifdef ZAP_CHECK_HOOKSTATE
07935                return 0;
07936 #else
07937                return 1;
07938 #endif
07939          } else if (par.rxisoffhook) {
07940             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07941             /* Not available when the other end is off hook */
07942             return 0;
07943          }
07944       }
07945       return 1;
07946    }
07947 
07948    /* If it's not an FXO, forget about call wait */
07949    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
07950       return 0;
07951 
07952    if (!p->callwaiting) {
07953       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
07954       return 0;
07955    }
07956 
07957    if (p->subs[SUB_CALLWAIT].zfd > -1) {
07958       /* If there is already a call waiting call, then we can't take a second one */
07959       return 0;
07960    }
07961    
07962    if ((p->owner->_state != AST_STATE_UP) &&
07963        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07964       /* If the current call is not up, then don't allow the call */
07965       return 0;
07966    }
07967    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07968       /* Can't take a call wait when the three way calling hasn't been merged yet. */
07969       return 0;
07970    }
07971    /* We're cool */
07972    return 1;
07973 }

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

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

Referenced by process_zap().

11817 {
11818    char *c, *chan;
11819    int x, start, finish;
11820    struct zt_pvt *tmp;
11821 #ifdef HAVE_PRI
11822    struct zt_pri *pri;
11823    int trunkgroup, y;
11824 #endif
11825    
11826    if ((reload == 0) && (conf->chan.sig < 0)) {
11827       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
11828       return -1;
11829    }
11830 
11831    c = ast_strdupa(value);
11832 
11833 #ifdef HAVE_PRI
11834    pri = NULL;
11835    if (iscrv) {
11836       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
11837          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
11838          return -1;
11839       }
11840       if (trunkgroup < 1) {
11841          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
11842          return -1;
11843       }
11844       c += y;
11845       for (y = 0; y < NUM_SPANS; y++) {
11846          if (pris[y].trunkgroup == trunkgroup) {
11847             pri = pris + y;
11848             break;
11849          }
11850       }
11851       if (!pri) {
11852          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
11853          return -1;
11854       }
11855    }
11856 #endif         
11857 
11858    while ((chan = strsep(&c, ","))) {
11859       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
11860          /* Range */
11861       } else if (sscanf(chan, "%d", &start)) {
11862          /* Just one */
11863          finish = start;
11864       } else if (!strcasecmp(chan, "pseudo")) {
11865          finish = start = CHAN_PSEUDO;
11866          if (found_pseudo)
11867             *found_pseudo = 1;
11868       } else {
11869          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
11870          return -1;
11871       }
11872       if (finish < start) {
11873          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
11874          x = finish;
11875          finish = start;
11876          start = x;
11877       }
11878 
11879       for (x = start; x <= finish; x++) {
11880 #ifdef HAVE_PRI
11881          tmp = mkintf(x, conf, pri, reload);
11882 #else       
11883          tmp = mkintf(x, conf, NULL, reload);
11884 #endif         
11885 
11886          if (tmp) {
11887             if (option_verbose > 2) {
11888 #ifdef HAVE_PRI
11889                if (pri)
11890                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
11891                else
11892 #endif
11893                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
11894             }
11895          } else {
11896             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
11897                (reload == 1) ? "reconfigure" : "register", value);
11898             return -1;
11899          }
11900       }
11901    }
11902 
11903    return 0;
11904 }

static int bump_gains ( struct zt_pvt p  )  [static]

Definition at line 1647 of file chan_zap.c.

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

Referenced by ss_thread().

01648 {
01649    int res;
01650 
01651    /* Bump receive gain by 5.0db */
01652    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01653    if (res) {
01654       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01655       return -1;
01656    }
01657 
01658    return 0;
01659 }

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

Definition at line 7975 of file chan_zap.c.

References ast_log(), ast_malloc, ast_mutex_init(), zt_pvt::destroy, destroy_zt_pvt(), errno, iflist, zt_pvt::lock, LOG_ERROR, LOG_WARNING, oh323_pvt::next, zt_pvt::next, zt_pvt::prev, SUB_REAL, zt_pvt::subs, zt_subchannel::zfd, and zt_open().

Referenced by zt_request().

07976 {
07977    struct zt_pvt *p;
07978    ZT_BUFFERINFO bi;
07979    int res;
07980    
07981    if ((p = ast_malloc(sizeof(*p)))) {
07982       memcpy(p, src, sizeof(struct zt_pvt));
07983       ast_mutex_init(&p->lock);
07984       p->subs[SUB_REAL].zfd = zt_open("/dev/zap/pseudo");
07985       /* Allocate a zapata structure */
07986       if (p->subs[SUB_REAL].zfd < 0) {
07987          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
07988          destroy_zt_pvt(&p);
07989          return NULL;
07990       }
07991       res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
07992       if (!res) {
07993          bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
07994          bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
07995          bi.numbufs = numbufs;
07996          res = ioctl(p->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
07997          if (res < 0) {
07998             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel\n");
07999          }
08000       } else
08001          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel\n");
08002    }
08003    p->destroy = 1;
08004    p->next = iflist;
08005    p->prev = NULL;
08006    iflist = p;
08007    if (iflist->next)
08008       iflist->next->prev = p;
08009    return p;
08010 }

static int check_for_conference ( struct zt_pvt p  )  [static]

Definition at line 3725 of file chan_zap.c.

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

Referenced by zt_handle_event().

03726 {
03727    ZT_CONFINFO ci;
03728    /* Fine if we already have a master, etc */
03729    if (p->master || (p->confno > -1))
03730       return 0;
03731    memset(&ci, 0, sizeof(ci));
03732    if (ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
03733       ast_log(LOG_WARNING, "Failed to get conference info on channel %d\n", p->channel);
03734       return 0;
03735    }
03736    /* If we have no master and don't have a confno, then 
03737       if we're in a conference, it's probably a MeetMe room or
03738       some such, so don't let us 3-way out! */
03739    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03740       if (option_verbose > 2) 
03741          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03742       return 1;
03743    }
03744    return 0;
03745 }

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

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

01284 {
01285    /* If the conference already exists, and we're already in it
01286       don't bother doing anything */
01287    ZT_CONFINFO zi;
01288    
01289    memset(&zi, 0, sizeof(zi));
01290    zi.chan = 0;
01291 
01292    if (slavechannel > 0) {
01293       /* If we have only one slave, do a digital mon */
01294       zi.confmode = ZT_CONF_DIGITALMON;
01295       zi.confno = slavechannel;
01296    } else {
01297       if (!index) {
01298          /* Real-side and pseudo-side both participate in conference */
01299          zi.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER |
01300             ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
01301       } else
01302          zi.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
01303       zi.confno = p->confno;
01304    }
01305    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01306       return 0;
01307    if (c->zfd < 0)
01308       return 0;
01309    if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
01310       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d\n", c->zfd, zi.confmode, zi.confno);
01311       return -1;
01312    }
01313    if (slavechannel < 1) {
01314       p->confno = zi.confno;
01315    }
01316    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01317    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01318    return 0;
01319 }

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

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

01333 {
01334    ZT_CONFINFO zi;
01335    if (/* Can't delete if there's no zfd */
01336       (c->zfd < 0) ||
01337       /* Don't delete from the conference if it's not our conference */
01338       !isourconf(p, c)
01339       /* Don't delete if we don't think it's conferenced at all (implied) */
01340       ) return 0;
01341    memset(&zi, 0, sizeof(zi));
01342    zi.chan = 0;
01343    zi.confno = 0;
01344    zi.confmode = 0;
01345    if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
01346       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01347       return -1;
01348    }
01349    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01350    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01351    return 0;
01352 }

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

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

02325 {
02326    int owned = 0;
02327    int i = 0;
02328 
02329    if (!now) {
02330       if (cur->owner) {
02331          owned = 1;
02332       }
02333 
02334       for (i = 0; i < 3; i++) {
02335          if (cur->subs[i].owner) {
02336             owned = 1;
02337          }
02338       }
02339       if (!owned) {
02340          if (prev) {
02341             prev->next = cur->next;
02342             if (prev->next)
02343                prev->next->prev = prev;
02344             else
02345                ifend = prev;
02346          } else {
02347             iflist = cur->next;
02348             if (iflist)
02349                iflist->prev = NULL;
02350             else
02351                ifend = NULL;
02352          }
02353          if (cur->subs[SUB_REAL].zfd > -1) {
02354             zt_close(cur->subs[SUB_REAL].zfd);
02355          }
02356          destroy_zt_pvt(&cur);
02357       }
02358    } else {
02359       if (prev) {
02360          prev->next = cur->next;
02361          if (prev->next)
02362             prev->next->prev = prev;
02363          else
02364             ifend = prev;
02365       } else {
02366          iflist = cur->next;
02367          if (iflist)
02368             iflist->prev = NULL;
02369          else
02370             ifend = NULL;
02371       }
02372       if (cur->subs[SUB_REAL].zfd > -1) {
02373          zt_close(cur->subs[SUB_REAL].zfd);
02374       }
02375       destroy_zt_pvt(&cur);
02376    }
02377    return 0;
02378 }

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

Definition at line 2309 of file chan_zap.c.

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

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

02310 {
02311    struct zt_pvt *p = *pvt;
02312    /* Remove channel from the list */
02313    if (p->prev)
02314       p->prev->next = p->next;
02315    if (p->next)
02316       p->next->prev = p->prev;
02317    if (p->use_smdi)
02318       ast_smdi_interface_unref(p->smdi_iface);
02319    ast_mutex_destroy(&p->lock);
02320    free(p);
02321    *pvt = NULL;
02322 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1043 of file chan_zap.c.

Referenced by zt_digit_begin().

01044 {
01045    if (isdigit(digit))
01046       return ZT_TONE_DTMF_BASE + (digit - '0');
01047    else if (digit >= 'A' && digit <= 'D')
01048       return ZT_TONE_DTMF_A + (digit - 'A');
01049    else if (digit >= 'a' && digit <= 'd')
01050       return ZT_TONE_DTMF_A + (digit - 'a');
01051    else if (digit == '*')
01052       return ZT_TONE_DTMF_s;
01053    else if (digit == '#')
01054       return ZT_TONE_DTMF_p;
01055    else
01056       return -1;
01057 }

static void disable_dtmf_detect ( struct zt_pvt p  )  [static]

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

03255 {
03256 #ifdef ZT_TONEDETECT
03257    int val;
03258 #endif
03259 
03260    p->ignoredtmf = 1;
03261 
03262 #ifdef ZT_TONEDETECT
03263    val = 0;
03264    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03265 #endif      
03266    if (!p->hardwaredtmf && p->dsp) {
03267       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03268       ast_dsp_set_features(p->dsp, p->dsp_features);
03269    }
03270 }

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

Definition at line 7008 of file chan_zap.c.

References ast_app_has_voicemail(), ast_calloc, ast_fdisset(), AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), zt_pvt::channel, zt_pvt::cidlen, zt_pvt::cidpos, zt_pvt::cidspill, errno, event2str(), pollfd::events, pollfd::fd, free, handle_init_event(), iflist, last, LOG_DEBUG, LOG_WARNING, zt_pvt::mailbox, MAX_CALLERID_SIZE, zt_pvt::msgstate, zt_pvt::next, zt_pvt::onhooktime, option_debug, zt_subchannel::owner, zt_pvt::owner, poll(), POLLIN, POLLPRI, zt_pvt::radio, pollfd::revents, zt_pvt::sig, SUB_REAL, zt_pvt::subs, vmwi_generate(), zt_subchannel::zfd, and zt_get_event().

07009 {
07010    int count, res, res2, spoint, pollres=0;
07011    struct zt_pvt *i;
07012    struct zt_pvt *last = NULL;
07013    time_t thispass = 0, lastpass = 0;
07014    int found;
07015    char buf[1024];
07016    struct pollfd *pfds=NULL;
07017    int lastalloc = -1;
07018    /* This thread monitors all the frame relay interfaces which are not yet in use
07019       (and thus do not have a separate thread) indefinitely */
07020    /* From here on out, we die whenever asked */
07021 #if 0
07022    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
07023       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
07024       return NULL;
07025    }
07026    ast_log(LOG_DEBUG, "Monitor starting...\n");
07027 #endif
07028    for (;;) {
07029       /* Lock the interface list */
07030       ast_mutex_lock(&iflock);
07031       if (!pfds || (lastalloc != ifcount)) {
07032          if (pfds) {
07033             free(pfds);
07034             pfds = NULL;
07035          }
07036          if (ifcount) {
07037             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
07038                ast_mutex_unlock(&iflock);
07039                return NULL;
07040             }
07041          }
07042          lastalloc = ifcount;
07043       }
07044       /* Build the stuff we're going to poll on, that is the socket of every
07045          zt_pvt that does not have an associated owner channel */
07046       count = 0;
07047       i = iflist;
07048       while (i) {
07049          if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
07050             if (!i->owner && !i->subs[SUB_REAL].owner) {
07051                /* This needs to be watched, as it lacks an owner */
07052                pfds[count].fd = i->subs[SUB_REAL].zfd;
07053                pfds[count].events = POLLPRI;
07054                pfds[count].revents = 0;
07055                /* Message waiting or r2 channels also get watched for reading */
07056                if (i->cidspill)
07057                   pfds[count].events |= POLLIN;
07058                count++;
07059             }
07060          }
07061          i = i->next;
07062       }
07063       /* Okay, now that we know what to do, release the interface lock */
07064       ast_mutex_unlock(&iflock);
07065       
07066       pthread_testcancel();
07067       /* Wait at least a second for something to happen */
07068       res = poll(pfds, count, 1000);
07069       pthread_testcancel();
07070       /* Okay, poll has finished.  Let's see what happened.  */
07071       if (res < 0) {
07072          if ((errno != EAGAIN) && (errno != EINTR))
07073             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07074          continue;
07075       }
07076       /* Alright, lock the interface list again, and let's look and see what has
07077          happened */
07078       ast_mutex_lock(&iflock);
07079       found = 0;
07080       spoint = 0;
07081       lastpass = thispass;
07082       thispass = time(NULL);
07083       i = iflist;
07084       while (i) {
07085          if (thispass != lastpass) {
07086             if (!found && ((i == last) || ((i == iflist) && !last))) {
07087                last = i;
07088                if (last) {
07089                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07090                      (last->sig & __ZT_SIG_FXO)) {
07091                      res = ast_app_has_voicemail(last->mailbox, NULL);
07092                      if (last->msgstate != res) {
07093                         int x;
07094                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07095                         x = ZT_FLUSH_BOTH;
07096                         res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
07097                         if (res2)
07098                            ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
07099                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07100                            /* Turn on on hook transfer for 4 seconds */
07101                            x = 4000;
07102                            ioctl(last->subs[SUB_REAL].zfd, ZT_ONHOOKTRANSFER, &x);
07103                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07104                            last->cidpos = 0;
07105                            last->msgstate = res;
07106                            last->onhooktime = thispass;
07107                         }
07108                         found ++;
07109                      }
07110                   }
07111                   last = last->next;
07112                }
07113             }
07114          }
07115          if ((i->subs[SUB_REAL].zfd > -1) && i->sig) {
07116             if (i->radio && !i->owner)
07117             {
07118                res = zt_get_event(i->subs[SUB_REAL].zfd);
07119                if (res)
07120                {
07121                   if (option_debug)
07122                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07123                   /* Don't hold iflock while handling init events */
07124                   ast_mutex_unlock(&iflock);
07125                   handle_init_event(i, res);
07126                   ast_mutex_lock(&iflock);   
07127                }
07128                i = i->next;
07129                continue;
07130             }              
07131             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint);
07132             if (pollres & POLLIN) {
07133                if (i->owner || i->subs[SUB_REAL].owner) {
07134 #ifdef HAVE_PRI
07135                   if (!i->pri)
07136 #endif                  
07137                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].zfd);
07138                   i = i->next;
07139                   continue;
07140                }
07141                if (!i->cidspill) {
07142                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
07143                   i = i->next;
07144                   continue;
07145                }
07146                res = read(i->subs[SUB_REAL].zfd, buf, sizeof(buf));
07147                if (res > 0) {
07148                   /* We read some number of bytes.  Write an equal amount of data */
07149                   if (res > i->cidlen - i->cidpos) 
07150                      res = i->cidlen - i->cidpos;
07151                   res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
07152                   if (res2 > 0) {
07153                      i->cidpos += res2;
07154                      if (i->cidpos >= i->cidlen) {
07155                         free(i->cidspill);
07156                         i->cidspill = 0;
07157                         i->cidpos = 0;
07158                         i->cidlen = 0;
07159                      }
07160                   } else {
07161                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07162                      i->msgstate = -1;
07163                   }
07164                } else {
07165                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07166                }
07167             }
07168             if (pollres & POLLPRI) {
07169                if (i->owner || i->subs[SUB_REAL].owner) {
07170 #ifdef HAVE_PRI
07171                   if (!i->pri)
07172 #endif                  
07173                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].zfd);
07174                   i = i->next;
07175                   continue;
07176                }
07177                res = zt_get_event(i->subs[SUB_REAL].zfd);
07178                if (option_debug)
07179                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07180                /* Don't hold iflock while handling init events */
07181                ast_mutex_unlock(&iflock);
07182                handle_init_event(i, res);
07183                ast_mutex_lock(&iflock);   
07184             }
07185          }
07186          i=i->next;
07187       }
07188       ast_mutex_unlock(&iflock);
07189    }
07190    /* Never reached */
07191    return NULL;
07192    
07193 }

static void enable_dtmf_detect ( struct zt_pvt p  )  [static]

Definition at line 3272 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_answer(), and zt_bridge().

03273 {
03274 #ifdef ZT_TONEDETECT
03275    int val;
03276 #endif
03277 
03278    if (p->channel == CHAN_PSEUDO)
03279       return;
03280 
03281    p->ignoredtmf = 0;
03282 
03283 #ifdef ZT_TONEDETECT
03284    val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
03285    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03286 #endif      
03287    if (!p->hardwaredtmf && p->dsp) {
03288       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03289       ast_dsp_set_features(p->dsp, p->dsp_features);
03290    }
03291 }

static char* event2str ( int  event  )  [static]

Definition at line 1200 of file chan_zap.c.

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

01201 {
01202    static char buf[256];
01203    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01204       return events[event];
01205    sprintf(buf, "Event %d", event); /* safe */
01206    return buf;
01207 }

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

Definition at line 1571 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

01572 {
01573    int j;
01574    int k;
01575    float linear_gain = pow(10.0, gain / 20.0);
01576 
01577    switch (law) {
01578    case ZT_LAW_ALAW:
01579       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01580          if (gain) {
01581             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01582             if (k > 32767) k = 32767;
01583             if (k < -32767) k = -32767;
01584             g->rxgain[j] = AST_LIN2A(k);
01585          } else {
01586             g->rxgain[j] = j;
01587          }
01588       }
01589       break;
01590    case ZT_LAW_MULAW:
01591       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01592          if (gain) {
01593             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01594             if (k > 32767) k = 32767;
01595             if (k < -32767) k = -32767;
01596             g->rxgain[j] = AST_LIN2MU(k);
01597          } else {
01598             g->rxgain[j] = j;
01599          }
01600       }
01601       break;
01602    }
01603 }

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

Definition at line 1537 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

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

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

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

11563 {
11564    struct zt_pvt *p = iflist;
11565    while (p) {
11566       if (p->channel == channel) {
11567          break;
11568       }
11569       p = p->next;
11570    }
11571    return p;
11572 }

static int get_alarms ( struct zt_pvt p  )  [static]

Definition at line 3747 of file chan_zap.c.

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

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

03748 {
03749    int res;
03750    ZT_SPANINFO zi;
03751    memset(&zi, 0, sizeof(zi));
03752    zi.spanno = p->span;
03753    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SPANSTAT, &zi);
03754    if (res < 0) {
03755       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03756       return 0;
03757    }
03758    return zi.alarms;
03759 }

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

Definition at line 6760 of file chan_zap.c.

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

Referenced by do_monitor().

06761 {
06762    int res;
06763    pthread_t threadid;
06764    pthread_attr_t attr;
06765    struct ast_channel *chan;
06766    pthread_attr_init(&attr);
06767    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06768    /* Handle an event on a given channel for the monitor thread. */
06769    switch (event) {
06770    case ZT_EVENT_NONE:
06771    case ZT_EVENT_BITSCHANGED:
06772       break;
06773    case ZT_EVENT_WINKFLASH:
06774    case ZT_EVENT_RINGOFFHOOK:
06775       if (i->inalarm) break;
06776       if (i->radio) break;
06777       /* Got a ring/answer.  What kind of channel are we? */
06778       switch (i->sig) {
06779       case SIG_FXOLS:
06780       case SIG_FXOGS:
06781       case SIG_FXOKS:
06782          res = zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
06783          if (res && (errno == EBUSY))
06784             break;
06785          if (i->cidspill) {
06786             /* Cancel VMWI spill */
06787             free(i->cidspill);
06788             i->cidspill = NULL;
06789          }
06790          if (i->immediate) {
06791             zt_enable_ec(i);
06792             /* The channel is immediately up.  Start right away */
06793             res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
06794             chan = zt_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06795             if (!chan) {
06796                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06797                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06798                if (res < 0)
06799                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06800             }
06801          } else {
06802             /* Check for callerid, digits, etc */
06803             chan = zt_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06804             if (chan) {
06805                if (has_voicemail(i))
06806                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_STUTTER);
06807                else
06808                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
06809                if (res < 0) 
06810                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06811                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06812                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06813                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06814                   if (res < 0)
06815                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06816                   ast_hangup(chan);
06817                }
06818             } else
06819                ast_log(LOG_WARNING, "Unable to create channel\n");
06820          }
06821          break;
06822       case SIG_FXSLS:
06823       case SIG_FXSGS:
06824       case SIG_FXSKS:
06825             i->ringt = i->ringt_base;
06826             /* Fall through */
06827       case SIG_EMWINK:
06828       case SIG_FEATD:
06829       case SIG_FEATDMF:
06830       case SIG_FEATDMF_TA:
06831       case SIG_E911:
06832       case SIG_FGC_CAMA:
06833       case SIG_FGC_CAMAMF:
06834       case SIG_FEATB:
06835       case SIG_EM:
06836       case SIG_EM_E1:
06837       case SIG_SFWINK:
06838       case SIG_SF_FEATD:
06839       case SIG_SF_FEATDMF:
06840       case SIG_SF_FEATB:
06841       case SIG_SF:
06842             /* Check for callerid, digits, etc */
06843             chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06844             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06845                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06846                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06847                if (res < 0)
06848                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06849                ast_hangup(chan);
06850             } else if (!chan) {
06851                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06852             }
06853             break;
06854       default:
06855          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06856          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06857          if (res < 0)
06858                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06859          return -1;
06860       }
06861       break;
06862    case ZT_EVENT_NOALARM:
06863       i->inalarm = 0;
06864       if (!i->unknown_alarm) {
06865 #ifdef HAVE_PRI
06866           if (i->pri) {
06867          if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
06868              /* dont annoy BRI TE mode users with layer2layer alarms */
06869          } else {
06870 #endif
06871          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06872          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06873             "Channel: %d\r\n", i->channel);
06874 #ifdef HAVE_PRI
06875          }
06876           }
06877 #endif
06878 
06879       } else {
06880          i->unknown_alarm = 0;
06881       }
06882       break;
06883    case ZT_EVENT_ALARM:
06884       i->inalarm = 1;
06885       res = get_alarms(i);
06886       do {
06887 #ifdef HAVE_PRI
06888           if (i->pri) {
06889          if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
06890              /* dont annoy BRI TE mode users with layer2layer alarms */
06891          } else {
06892 #endif
06893              const char *alarm_str = alarm2str(res);
06894 
06895          /* hack alert!  Zaptel 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
06896           * doesn't know what to do with it.  Don't confuse users with log messages. */
06897          if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
06898             i->unknown_alarm = 1;
06899             break;
06900          } else {
06901             i->unknown_alarm = 0;
06902          }
06903 
06904          ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm_str);
06905          manager_event(EVENT_FLAG_SYSTEM, "Alarm",
06906             "Alarm: %s\r\n"
06907             "Channel: %d\r\n",
06908             alarm_str, i->channel);
06909 #ifdef HAVE_PRI
06910          }
06911           }
06912 #endif
06913       } while (0);
06914       /* fall thru intentionally */
06915    case ZT_EVENT_ONHOOK:
06916       if (i->radio)
06917          break;
06918       /* Back on hook.  Hang up. */
06919       switch (i->sig) {
06920       case SIG_FXOLS:
06921       case SIG_FXOGS:
06922       case SIG_FEATD:
06923       case SIG_FEATDMF:
06924       case SIG_FEATDMF_TA:
06925       case SIG_E911:
06926       case SIG_FGC_CAMA:
06927       case SIG_FGC_CAMAMF:
06928       case SIG_FEATB:
06929       case SIG_EM:
06930       case SIG_EM_E1:
06931       case SIG_EMWINK:
06932       case SIG_SF_FEATD:
06933       case SIG_SF_FEATDMF:
06934       case SIG_SF_FEATB:
06935       case SIG_SF:
06936       case SIG_SFWINK:
06937       case SIG_FXSLS:
06938       case SIG_FXSGS:
06939       case SIG_FXSKS:
06940       case SIG_GR303FXSKS:
06941          zt_disable_ec(i);
06942          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06943          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
06944          break;
06945       case SIG_GR303FXOKS:
06946       case SIG_FXOKS:
06947          zt_disable_ec(i);
06948          /* Diddle the battery for the zhone */
06949 #ifdef ZHONE_HACK
06950          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
06951          usleep(1);
06952 #endif         
06953          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06954          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
06955          break;
06956       case SIG_PRI:
06957          if (event != ZT_EVENT_ALARM) {
06958              zt_disable_ec(i);
06959              res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06960          }
06961          break;
06962       default:
06963          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06964          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
06965          return -1;
06966       }
06967       break;
06968    case ZT_EVENT_POLARITY:
06969       switch (i->sig) {
06970       case SIG_FXSLS:
06971       case SIG_FXSKS:
06972       case SIG_FXSGS:
06973          /* We have already got a PR before the channel was 
06974             created, but it wasn't handled. We need polarity 
06975             to be REV for remote hangup detection to work. 
06976             At least in Spain */
06977          if (i->hanguponpolarityswitch)
06978             i->polarity = POLARITY_REV;
06979 
06980          if (i->cid_start == CID_START_POLARITY) {
06981             i->polarity = POLARITY_REV;
06982             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
06983                    "CID detection on channel %d\n",
06984                    i->channel);
06985             chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
06986             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06987                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06988             }
06989          }
06990          break;
06991       default:
06992          ast_log(LOG_WARNING, "handle_init_event detected "
06993             "polarity reversal on non-FXO (SIG_FXS) "
06994             "interface %d\n", i->channel);
06995       }
06996       break;
06997    case ZT_EVENT_REMOVED: /* destroy channel */
06998       ast_log(LOG_NOTICE, 
06999             "Got ZT_EVENT_REMOVED. Destroying channel %d\n", 
07000             i->channel);
07001       zap_destroy_channel_bynum(i->channel);
07002       break;
07003    }
07004    pthread_attr_destroy(&attr);
07005    return 0;
07006 }

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

Definition at line 11406 of file chan_zap.c.

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

11407 {
11408    int i, j;
11409    for (i = 0; i < num_cadence; i++) {
11410       char output[1024];
11411       char tmp[16], tmp2[64];
11412       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
11413       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
11414 
11415       for (j = 0; j < 16; j++) {
11416          if (cadences[i].ringcadence[j] == 0)
11417             break;
11418          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
11419          if (cidrings[i] * 2 - 1 == j)
11420             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
11421          else
11422             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
11423          if (j != 0)
11424             strncat(output, ",", sizeof(output) - strlen(output) - 1);
11425          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
11426       }
11427       ast_cli(fd,"%s\n",output);
11428    }
11429    return 0;
11430 }

static int has_voicemail ( struct zt_pvt p  )  [static]

Definition at line 1768 of file chan_zap.c.

References ast_app_has_voicemail(), and zt_pvt::mailbox.

01769 {
01770 
01771    return ast_app_has_voicemail(p->mailbox, NULL);
01772 }

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

Definition at line 1321 of file chan_zap.c.

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

Referenced by conf_del().

01322 {
01323    /* If they're listening to our channel, they're ours */  
01324    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == ZT_CONF_DIGITALMON))
01325       return 1;
01326    /* If they're a talker on our (allocated) conference, they're ours */
01327    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & ZT_CONF_TALKER))
01328       return 1;
01329    return 0;
01330 }

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

Definition at line 1354 of file chan_zap.c.

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

Referenced by update_conf().

01355 {
01356    int x;
01357    int useslavenative;
01358    struct zt_pvt *slave = NULL;
01359    /* Start out optimistic */
01360    useslavenative = 1;
01361    /* Update conference state in a stateless fashion */
01362    for (x = 0; x < 3; x++) {
01363       /* Any three-way calling makes slave native mode *definitely* out
01364          of the question */
01365       if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway)
01366          useslavenative = 0;
01367    }
01368    /* If we don't have any 3-way calls, check to see if we have
01369       precisely one slave */
01370    if (useslavenative) {
01371       for (x = 0; x < MAX_SLAVES; x++) {
01372          if (p->slaves[x]) {
01373             if (slave) {
01374                /* Whoops already have a slave!  No 
01375                   slave native and stop right away */
01376                slave = NULL;
01377                useslavenative = 0;
01378                break;
01379             } else {
01380                /* We have one slave so far */
01381                slave = p->slaves[x];
01382             }
01383          }
01384       }
01385    }
01386    /* If no slave, slave native definitely out */
01387    if (!slave)
01388       useslavenative = 0;
01389    else if (slave->law != p->law) {
01390       useslavenative = 0;
01391       slave = NULL;
01392    }
01393    if (out)
01394       *out = slave;
01395    return useslavenative;
01396 }

static int load_module ( void   )  [static]

Definition at line 12754 of file chan_zap.c.

References __unload_module(), action_transfer(), action_transferhangup(), action_zapdialoffhook(), action_zapdndoff(), action_zapdndon(), action_zaprestart(), action_zapshowchannels(), app_zapEC(), ast_channel_register(), ast_cli_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, and setup_zap().

12755 {
12756    int res;
12757 
12758 #ifdef HAVE_PRI
12759    int y,i;
12760    memset(pris, 0, sizeof(pris));
12761    for (y = 0; y < NUM_SPANS; y++) {
12762       ast_mutex_init(&pris[y].lock);
12763       pris[y].offset = -1;
12764       pris[y].master = AST_PTHREADT_NULL;
12765       for (i = 0; i < NUM_DCHANS; i++)
12766          pris[y].fds[i] = -1;
12767    }
12768    pri_set_error(zt_pri_error);
12769    pri_set_message(zt_pri_message);
12770    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
12771          zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
12772 #endif
12773 #ifdef HAVE_GSMAT
12774    gsm_set_error(zt_gsm_error);
12775    gsm_set_message(zt_gsm_message);
12776 #endif
12777    res = setup_zap(0);
12778    /* Make sure we can register our Zap channel type */
12779    if (res)
12780       return AST_MODULE_LOAD_DECLINE;
12781    if (ast_channel_register(&zap_tech)) {
12782       ast_log(LOG_ERROR, "Unable to register channel class 'Zap'\n");
12783       __unload_module();
12784       return -1;
12785    }
12786 #ifdef HAVE_PRI
12787    ast_string_field_init(&inuse, 16);
12788    ast_string_field_set(&inuse, name, "GR-303InUse");
12789    ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
12790    ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
12791         ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
12792 #endif   
12793    ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
12794    ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
12795 #ifdef HAVE_GSMAT
12796    ast_cli_register(&gsm_send_sms);
12797    ast_cli_register(&gsm_send_pdu);
12798    ast_cli_register(&gsm_show_status);
12799    ast_cli_register_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
12800 #endif
12801    
12802    memset(round_robin, 0, sizeof(round_robin));
12803    ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
12804    ast_manager_register( "ZapHangup", 0, action_transferhangup, "Hangup Zap Channel" );
12805    ast_manager_register( "ZapDialOffhook", 0, action_zapdialoffhook, "Dial over Zap channel while offhook" );
12806    ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
12807    ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
12808    ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
12809    ast_manager_register("ZapRestart", 0, action_zaprestart, "Fully Restart zaptel channels (terminates calls)");
12810 
12811    return res;
12812 }

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

Definition at line 7346 of file chan_zap.c.

References zt_pvt::accountcode, zt_pvt::adsi, zt_pvt::amaflags, zt_pvt::answeronpolarityswitch, ast_calloc, ast_dsp_digitmode(), ast_log(), ast_mutex_init(), ast_pthread_create, ast_smdi_interface_find(), ast_strlen_zero(), 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, CHAN_PSEUDO, zt_pvt::channel, zt_pvt::cid_name, zt_pvt::cid_num, CID_SIG_SMDI, zt_pvt::cid_signalling, zt_pvt::cid_start, zt_pvt::cid_ton, zt_pvt::confno, zt_pvt::context, DCHAN_AVAILABLE, zt_pvt::defcontext, zt_pvt::destroy, destroy_zt_pvt(), drings, zt_pvt::drings, zt_pvt::dsp, DSP_DIGITMODE_DTMF, zt_pvt::dtmfrelax, zt_pvt::echocanbridged, zt_pvt::echocancel, zt_pvt::echotraining, errno, zt_pvt::exten, zt_pvt::firstradio, zt_pvt::group, gsm_new(), zt_pvt::hanguponpolarityswitch, zt_pvt::hidecallerid, iflist, zt_pvt::immediate, zt_pvt::inalarm, zt_pvt::language, zt_pvt::law, zt_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, zt_pvt::mailbox, zt_pvt::master, MAX_CHANNELS, zt_pvt::mohinterpret, zt_pvt::mohsuggest, zt_pvt::msgstate, zt_pvt::next, zt_pvt::onhooktime, zt_pvt::outsigmod, zt_pvt::permcallwaiting, zt_pvt::permhidecallerid, zt_pvt::pickupgroup, zt_pvt::polarityonanswerdelay, zt_pvt::prev, zt_pvt::priexclusive, zt_pvt::priindication_oob, zt_pvt::pritransfer, zt_pvt::propconfno, zt_pvt::pulse, zt_pvt::radio, zt_pvt::restrictcid, zt_pvt::ringt_base, zt_pvt::rxgain, zt_pvt::sendcalleridafter, set_actual_gain(), 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_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_GSM, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, zt_pvt::smdi_iface, zt_chan_conf::smdi_port, zt_pvt::span, zt_pvt::stripmsd, SUB_REAL, zt_pvt::subs, zt_pvt::threewaycalling, zt_chan_conf::timing, zt_pvt::tonezone, zt_pvt::transfer, zt_pvt::transfertobusy, zt_pvt::txgain, update_conf(), zt_pvt::use_callerid, zt_pvt::use_callingpres, zt_pvt::use_smdi, zt_pvt::usedistinctiveringdetection, zt_pvt::zaptrcallerid, zt_subchannel::zfd, zt_close(), zt_open(), and zt_set_hook().

Referenced by build_channels(), and process_zap().

07347 {
07348    /* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
07349    struct zt_pvt *tmp = NULL, *tmp2,  *prev = NULL;
07350    char fn[80];
07351 #if 1
07352    struct zt_bufferinfo bi;
07353 #endif
07354    struct zt_spaninfo si;
07355    int res;
07356    int span=0;
07357    int here = 0;
07358    int x;
07359    struct zt_pvt **wlist;
07360    struct zt_pvt **wend;
07361    ZT_PARAMS p;
07362 
07363    wlist = &iflist;
07364    wend = &ifend;
07365 
07366 #ifdef HAVE_PRI
07367    if (pri) {
07368       wlist = &pri->crvs;
07369       wend = &pri->crvend;
07370    }
07371 #endif
07372 
07373    tmp2 = *wlist;
07374    prev = NULL;
07375 
07376    while (tmp2) {
07377       if (!tmp2->destroy) {
07378          if (tmp2->channel == channel) {
07379             tmp = tmp2;
07380             here = 1;
07381             break;
07382          }
07383          if (tmp2->channel > channel) {
07384             break;
07385          }
07386       }
07387       prev = tmp2;
07388       tmp2 = tmp2->next;
07389    }
07390 
07391    if (!here && !reloading) {
07392       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07393          destroy_zt_pvt(&tmp);
07394          return NULL;
07395       }
07396       ast_mutex_init(&tmp->lock);
07397       ifcount++;
07398       for (x = 0; x < 3; x++)
07399          tmp->subs[x].zfd = -1;
07400       tmp->channel = channel;
07401    }
07402 
07403    if (tmp) {
07404       int chan_sig = conf->chan.sig;
07405       if (!here) {
07406          if ((channel != CHAN_PSEUDO) && !pri) {
07407             snprintf(fn, sizeof(fn), "%d", channel);
07408             /* Open non-blocking */
07409             if (!here)
07410                tmp->subs[SUB_REAL].zfd = zt_open(fn);
07411             /* Allocate a zapata structure */
07412             if (tmp->subs[SUB_REAL].zfd < 0) {
07413                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);
07414                destroy_zt_pvt(&tmp);
07415                return NULL;
07416             }
07417             memset(&p, 0, sizeof(p));
07418             res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &p);
07419             if (res < 0) {
07420                ast_log(LOG_ERROR, "Unable to get parameters\n");
07421                destroy_zt_pvt(&tmp);
07422                return NULL;
07423             }
07424             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07425                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));
07426                destroy_zt_pvt(&tmp);
07427                return NULL;
07428             }
07429             tmp->law = p.curlaw;
07430             tmp->span = p.spanno;
07431             span = p.spanno - 1;
07432          } else {
07433             if (channel == CHAN_PSEUDO)
07434                chan_sig = 0;
07435             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07436                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07437                return NULL;
07438             }
07439          }
07440 #ifdef HAVE_PRI
07441          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07442             int offset;
07443             int myswitchtype;
07444             int matchesdchan;
07445             int x,y;
07446             offset = 0;
07447             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &offset)) {
07448                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07449                destroy_zt_pvt(&tmp);
07450                return NULL;
07451             }
07452             if (span >= NUM_SPANS) {
07453                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07454                destroy_zt_pvt(&tmp);
07455                return NULL;
07456             } else {
07457                si.spanno = 0;
07458                if (ioctl(tmp->subs[SUB_REAL].zfd,ZT_SPANSTAT,&si) == -1) {
07459                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07460                   destroy_zt_pvt(&tmp);
07461                   return NULL;
07462                }
07463                /* Store the logical span first based upon the real span */
07464                tmp->logicalspan = pris[span].prilogicalspan;
07465                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07466                if (span < 0) {
07467                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07468                   destroy_zt_pvt(&tmp);
07469                   return NULL;
07470                }
07471                if (chan_sig == SIG_PRI)
07472                   myswitchtype = conf->pri.switchtype;
07473                else
07474                   myswitchtype = PRI_SWITCH_GR303_TMC;
07475                /* Make sure this isn't a d-channel */
07476                matchesdchan=0;
07477                for (x = 0; x < NUM_SPANS; x++) {
07478                   for (y = 0; y < NUM_DCHANS; y++) {
07479                      if (pris[x].dchannels[y] == tmp->channel) {
07480                         matchesdchan = 1;
07481                         break;
07482                      }
07483                   }
07484                }
07485                offset = p.chanpos;
07486                if (!matchesdchan) {
07487                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07488                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07489                      destroy_zt_pvt(&tmp);
07490                      return NULL;
07491                   }
07492                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07493                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07494                      destroy_zt_pvt(&tmp);
07495                      return NULL;
07496                   }
07497                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07498                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07499                      destroy_zt_pvt(&tmp);
07500                      return NULL;
07501                   }
07502                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07503                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07504                      destroy_zt_pvt(&tmp);
07505                      return NULL;
07506                   }
07507                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07508                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07509                      destroy_zt_pvt(&tmp);
07510                      return NULL;
07511                   }
07512                                              if ((pris[span].localdialplan) && (pris[span].localdialplan != conf->pri.localdialplan)) {
07513                      ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
07514                      destroy_zt_pvt(&tmp);
07515                                                    return NULL;
07516                      }
07517                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07518                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07519                      destroy_zt_pvt(&tmp);
07520                      return NULL;
07521                   }
07522                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07523                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07524                      destroy_zt_pvt(&tmp);
07525                      return NULL;
07526                   }
07527                   if (pris[span].numchans >= MAX_CHANNELS) {
07528                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07529                         pris[span].trunkgroup);
07530                      destroy_zt_pvt(&tmp);
07531                      return NULL;
07532                   }
07533                   pris[span].nodetype = conf->pri.nodetype;
07534 
07535                   if (conf->pri.nodetype == BRI_NETWORK_PTMP) {
07536                       pris[span].dchanavail[0] =  DCHAN_AVAILABLE;
07537                       pri_find_dchan(&pris[span]);
07538                   }
07539                   pris[span].switchtype = myswitchtype;
07540                   pris[span].nsf = conf->pri.nsf;
07541                   pris[span].dialplan = conf->pri.dialplan;
07542                   pris[span].localdialplan = conf->pri.localdialplan;
07543                   pris[span].pvts[pris[span].numchans++] = tmp;
07544                   pris[span].minunused = conf->pri.minunused;
07545                   pris[span].minidle = conf->pri.minidle;
07546                   pris[span].overlapdial = conf->pri.overlapdial;
07547                   pris[span].usercid = conf->pri.usercid;
07548                   pris[span].suspended_calls = NULL;
07549                   pris[span].facilityenable = conf->pri.facilityenable;
07550                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07551                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07552                   ast_copy_string(pris[span].nocid, conf->pri.nocid, sizeof(pris[span].nocid));
07553                   ast_copy_string(pris[span].withheldcid, conf->pri.withheldcid, sizeof(pris[span].withheldcid));
07554                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07555                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07556                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07557                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07558                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07559                   pris[span].resetinterval = conf->pri.resetinterval;
07560                   
07561                   tmp->pri = &pris[span];
07562                   tmp->prioffset = offset;
07563                   tmp->call = NULL;
07564                } else {
07565                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07566                   destroy_zt_pvt(&tmp);
07567                   return NULL;
07568                }
07569             }
07570          } else {
07571             tmp->prioffset = 0;
07572          }
07573 #endif
07574 #ifdef HAVE_GSMAT
07575       if (conf->chan.sig == SIG_GSM) {
07576           struct zt_bufferinfo bi;
07577           ast_mutex_init(&tmp->gsm.lock);
07578           strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
07579           strncpy(tmp->gsm.exten, gsm_modem_exten, sizeof(tmp->gsm.exten) - 1);
07580           tmp->gsm.available = 0;
07581           snprintf(fn, sizeof(fn), "%d", channel + 1);
07582           /* Open non-blocking */
07583           tmp->gsm.fd = zt_open(fn);
07584           bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
07585           bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
07586           bi.numbufs = 16;
07587           bi.bufsize = 1024;
07588           if (ioctl(tmp->gsm.fd, ZT_SET_BUFINFO, &bi)) {
07589          ast_log(LOG_ERROR, "Unable to set buffer info on channel '%s': %s\n", fn, strerror(errno));
07590          return NULL;
07591           }
07592           tmp->gsm.pvt = tmp;
07593           tmp->gsm.span = tmp->span;
07594           tmp->gsm.modul = gsm_new(tmp->gsm.fd, 0, tmp->gsm.pin, tmp->span, tmp->channel);
07595           if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, tmp->channel)) {
07596          ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d: %s\n", tmp->channel, strerror(errno));
07597          destroy_zt_pvt(&tmp);
07598          return NULL;
07599           }
07600           if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
07601          zt_close(tmp->gsm.fd);
07602           }
07603       }
07604 #endif
07605       } else {
07606          chan_sig = tmp->sig;
07607          memset(&p, 0, sizeof(p));
07608          if (tmp->subs[SUB_REAL].zfd > -1)
07609             res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &p);
07610       }
07611       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
07612       switch (chan_sig) {
07613       case SIG_FXSKS:
07614       case SIG_FXSLS:
07615       case SIG_EM:
07616       case SIG_EM_E1:
07617       case SIG_EMWINK:
07618       case SIG_FEATD:
07619       case SIG_FEATDMF:
07620       case SIG_FEATDMF_TA:
07621       case SIG_FEATB:
07622       case SIG_E911:
07623       case SIG_SF:
07624       case SIG_SFWINK:
07625       case SIG_FGC_CAMA:
07626       case SIG_FGC_CAMAMF:
07627       case SIG_SF_FEATD:
07628       case SIG_SF_FEATDMF:
07629       case SIG_SF_FEATB:
07630          p.starttime = 250;
07631          break;
07632       }
07633 
07634       if (tmp->radio) {
07635          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
07636          p.channo = channel;
07637          p.rxwinktime = 1;
07638          p.rxflashtime = 1;
07639          p.starttime = 1;
07640          p.debouncetime = 5;
07641       }
07642       if (!tmp->radio) {
07643          p.channo = channel;
07644          /* Override timing settings based on config file */
07645          if (conf->timing.prewinktime >= 0)
07646             p.prewinktime = conf->timing.prewinktime;
07647          if (conf->timing.preflashtime >= 0)
07648             p.preflashtime = conf->timing.preflashtime;
07649          if (conf->timing.winktime >= 0)
07650             p.winktime = conf->timing.winktime;
07651          if (conf->timing.flashtime >= 0)
07652             p.flashtime = conf->timing.flashtime;
07653          if (conf->timing.starttime >= 0)
07654             p.starttime = conf->timing.starttime;
07655          if (conf->timing.rxwinktime >= 0)
07656             p.rxwinktime = conf->timing.rxwinktime;
07657          if (conf->timing.rxflashtime >= 0)
07658             p.rxflashtime = conf->timing.rxflashtime;
07659          if (conf->timing.debouncetime >= 0)
07660             p.debouncetime = conf->timing.debouncetime;
07661       }
07662       
07663       /* dont set parms on a pseudo-channel (or CRV) */
07664       if (tmp->subs[SUB_REAL].zfd >= 0)
07665       {
07666          res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_PARAMS, &p);
07667          if (res < 0) {
07668             ast_log(LOG_ERROR, "Unable to set parameters\n");
07669             destroy_zt_pvt(&tmp);
07670             return NULL;
07671          }
07672       }
07673 #if 1
07674       if (!here && (tmp->subs[SUB_REAL].zfd > -1)) {
07675          memset(&bi, 0, sizeof(bi));
07676          res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
07677          if (!res) {
07678             bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
07679             bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
07680             bi.numbufs = numbufs;
07681             res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
07682             if (res < 0) {
07683                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", channel);
07684             }
07685          } else
07686             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", channel);
07687       }
07688 #endif
07689       tmp->immediate = conf->chan.immediate;
07690       tmp->transfertobusy = conf->chan.transfertobusy;
07691       tmp->sig = chan_sig;
07692       tmp->outsigmod = conf->chan.outsigmod;
07693       tmp->ringt_base = ringt_base;
07694       tmp->firstradio = 0;
07695       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07696          tmp->permcallwaiting = conf->chan.callwaiting;
07697       else
07698          tmp->permcallwaiting = 0;
07699       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
07700       tmp->destroy = 0;
07701       tmp->drings = drings;
07702       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07703       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07704       tmp->threewaycalling = conf->chan.threewaycalling;
07705       tmp->adsi = conf->chan.adsi;
07706       tmp->use_smdi = conf->chan.use_smdi;
07707       tmp->permhidecallerid = conf->chan.hidecallerid;
07708       tmp->callreturn = conf->chan.callreturn;
07709       tmp->echocancel = conf->chan.echocancel;
07710       tmp->echotraining = conf->chan.echotraining;
07711       tmp->pulse = conf->chan.pulse;
07712       if (tmp->echocancel)
07713          tmp->echocanbridged = conf->chan.echocanbridged;
07714       else {
07715          if (conf->chan.echocanbridged)
07716             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07717          tmp->echocanbridged = 0;
07718       }
07719       tmp->busydetect = conf->chan.busydetect;
07720       tmp->busycount = conf->chan.busycount;
07721       tmp->busy_tonelength = conf->chan.busy_tonelength;
07722       tmp->busy_quietlength = conf->chan.busy_quietlength;
07723       tmp->callprogress = conf->chan.callprogress;
07724       tmp->cancallforward = conf->chan.cancallforward;
07725       tmp->dtmfrelax = conf->chan.dtmfrelax;
07726       tmp->callwaiting = tmp->permcallwaiting;
07727       tmp->hidecallerid = tmp->permhidecallerid;
07728       tmp->channel = channel;
07729       tmp->stripmsd = conf->chan.stripmsd;
07730       tmp->use_callerid = conf->chan.use_callerid;
07731       tmp->cid_signalling = conf->chan.cid_signalling;
07732       tmp->cid_start = conf->chan.cid_start;
07733       tmp->zaptrcallerid = conf->chan.zaptrcallerid;
07734       tmp->restrictcid = conf->chan.restrictcid;
07735       tmp->use_callingpres = conf->chan.use_callingpres;
07736       tmp->priindication_oob = conf->chan.priindication_oob;
07737       tmp->pritransfer = conf->chan.pritransfer;
07738       tmp->priexclusive = conf->chan.priexclusive;
07739       if (tmp->usedistinctiveringdetection) {
07740          if (!tmp->use_callerid) {
07741             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07742             tmp->use_callerid = 1;
07743          }
07744       }
07745 
07746       if (tmp->cid_signalling == CID_SIG_SMDI) {
07747          if (!tmp->use_smdi) {
07748             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07749             tmp->use_smdi = 1;
07750          }
07751       }
07752       if (tmp->use_smdi) {
07753          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07754          if (!(tmp->smdi_iface)) {
07755             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07756             tmp->use_smdi = 0;
07757          }
07758       }
07759 
07760       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
07761       tmp->amaflags = conf->chan.amaflags;
07762       if (!here) {
07763          tmp->confno = -1;
07764          tmp->propconfno = -1;
07765       }
07766       tmp->canpark = conf->chan.canpark;
07767       tmp->transfer = conf->chan.transfer;
07768       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
07769       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
07770       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
07771       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
07772       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
07773       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
07774       tmp->cid_ton = 0;
07775       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
07776       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
07777       tmp->msgstate = -1;
07778       tmp->group = conf->chan.group;
07779       tmp->callgroup = conf->chan.callgroup;
07780       tmp->pickupgroup= conf->chan.pickupgroup;
07781       tmp->rxgain = conf->chan.rxgain;
07782       tmp->txgain = conf->chan.txgain;
07783       tmp->tonezone = conf->chan.tonezone;
07784       tmp->onhooktime = time(NULL);
07785       if (tmp->subs[SUB_REAL].zfd > -1) {
07786          set_actual_gain(tmp->subs[SUB_REAL].zfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
07787          if (tmp->dsp)
07788             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
07789          update_conf(tmp);
07790          if (!here) {
07791             if (chan_sig != SIG_PRI)
07792                /* Hang it up to be sure it's good */
07793                zt_set_hook(tmp->subs[SUB_REAL].zfd, ZT_ONHOOK);
07794          }
07795          ioctl(tmp->subs[SUB_REAL].zfd,ZT_SETTONEZONE,&tmp->tonezone);
07796 #ifdef HAVE_PRI
07797          /* the dchannel is down so put the channel in alarm */
07798          if (tmp->pri && !pri_is_up(tmp->pri))
07799             tmp->inalarm = 1;
07800          else
07801             tmp->inalarm = 0;
07802 #endif            
07803          memset(&si, 0, sizeof(si));
07804          if (ioctl(tmp->subs[SUB_REAL].zfd,ZT_SPANSTAT,&si) == -1) {
07805             ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07806             destroy_zt_pvt(&tmp);
07807             return NULL;
07808          }
07809          if (si.alarms) tmp->inalarm = 1;
07810       }
07811 
07812       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
07813       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
07814       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
07815       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
07816 
07817    }
07818    if (tmp && !here) {
07819       /* nothing on the iflist */
07820       if (!*wlist) {
07821          *wlist = tmp;
07822          tmp->prev = NULL;
07823          tmp->next = NULL;
07824          *wend = tmp;
07825       } else {
07826          /* at least one member on the iflist */
07827          struct zt_pvt *working = *wlist;
07828 
07829          /* check if we maybe have to put it on the begining */
07830          if (working->channel > tmp->channel) {
07831             tmp->next = *wlist;
07832             tmp->prev = NULL;
07833             (*wlist)->prev = tmp;
07834             *wlist = tmp;
07835          } else {
07836          /* go through all the members and put the member in the right place */
07837             while (working) {
07838                /* in the middle */
07839                if (working->next) {
07840                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
07841                      tmp->next = working->next;
07842                      tmp->prev = working;
07843                      working->next->prev = tmp;
07844                      working->next = tmp;
07845                      break;
07846                   }
07847                } else {
07848                /* the last */
07849                   if (working->channel < tmp->channel) {
07850                      working->next = tmp;
07851                      tmp->next = NULL;
07852                      tmp->prev = working;
07853                      *wend = tmp;
07854                      break;
07855                   }
07856                }
07857                working = working->next;
07858             }
07859          }
07860       }
07861    }
07862    return tmp;
07863 }

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

Definition at line 5549 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

05550 {
05551    char c;
05552 
05553    *str = 0; /* start with empty output buffer */
05554    for (;;)
05555    {
05556       /* Wait for the first digit (up to specified ms). */
05557       c = ast_waitfordigit(chan, ms);
05558       /* if timeout, hangup or error, return as such */
05559       if (c < 1)
05560          return c;
05561       *str++ = c;
05562       *str = 0;
05563       if (strchr(term, c))
05564          return 1;
05565    }
05566 }

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

Definition at line 5076 of file chan_zap.c.

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

Referenced by zt_write().

05077 {
05078    int sent=0;
05079    int size;
05080    int res;
05081    int fd;
05082    fd = p->subs[index].zfd;
05083    while (len) {
05084       size = len;
05085       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05086          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05087       res = write(fd, buf, size);
05088       if (res != size) {
05089          if (option_debug)
05090             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05091          return sent;
05092       }
05093       len -= size;
05094       buf += size;
05095    }
05096    return sent;
05097 }

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

Definition at line 11909 of file chan_zap.c.

References zt_pvt::accountcode, zt_pvt::adsi, zt_pvt::amaflags, zt_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_get_group(), ast_jb_read_conf(), ast_log(), ast_strlen_zero(), ast_true(), ast_verbose(), build_channels(), zt_pvt::busy_quietlength, zt_pvt::busy_tonelength, zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::callgroup, zt_pvt::callprogress, zt_pvt::callreturn, zt_pvt::callwaiting, zt_pvt::callwaitingcallerid, zt_pvt::cancallforward, zt_pvt::canpark, zt_chan_conf::chan, CHAN_PSEUDO, zt_pvt::cid_name, zt_pvt::cid_num, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, zt_pvt::cid_signalling, zt_pvt::cid_start, CID_START_POLARITY, CID_START_RING, zt_pvt::context, ringContextData::contextData, drings, DSP_DIGITMODE_RELAXDTMF, zt_pvt::dtmfrelax, zt_pvt::echocanbridged, zt_pvt::echocancel, zt_pvt::echotraining, global_jbconf, zt_pvt::group, zt_pvt::hanguponpolarityswitch, HAVE_PRI, zt_pvt::hidecallerid, zt_pvt::hidecalleridname, zt_pvt::immediate, zt_pvt::language, ast_variable::lineno, LOG_ERROR, LOG_WARNING, zt_pvt::mailbox, MAX_CHANLIST_LEN, mkintf(), zt_pvt::mohinterpret, zt_pvt::mohsuggest, ast_variable::name, ast_variable::next, NUM_CADENCE_MAX, option_verbose, zt_pvt::outsigmod, zt_pvt::pickupgroup, zt_pvt::polarityonanswerdelay, zt_pvt::priexclusive, zt_pvt::priindication_oob, zt_pvt::pritransfer, zt_pvt::pulse, zt_pvt::radio, READ_SIZE, zt_pvt::restrictcid, distRingData::ring, zt_distRings::ringContext, zt_distRings::ringnum, zt_pvt::rxgain, zt_pvt::sendcalleridafter, zt_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_GSM, 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().

11910 {
11911    struct zt_pvt *tmp;
11912    char *ringc; /* temporary string for parsing the dring number. */
11913    int y;
11914    int found_pseudo = 0;
11915         char zapchan[MAX_CHANLIST_LEN] = {};
11916 
11917    for (; v; v = v->next) {
11918       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11919          continue;
11920 
11921       /* Create the interface list */
11922       if (!strcasecmp(v->name, "channel")
11923 #ifdef HAVE_PRI
11924           || !strcasecmp(v->name, "crv")
11925 #endif         
11926          ) {
11927          int iscrv;
11928          if (skipchannels)
11929             continue;
11930          iscrv = !strcasecmp(v->name, "crv");
11931          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11932                return -1;
11933       } else if (!strcasecmp(v->name, "zapchan")) {
11934          ast_copy_string(zapchan, v->value, sizeof(zapchan));
11935       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11936          if (ast_true(v->value))
11937             confp->chan.usedistinctiveringdetection = 1;
11938       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11939          if (ast_true(v->value))
11940             distinctiveringaftercid = 1;
11941       } else if (!strcasecmp(v->name, "dring1context")) {
11942          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11943       } else if (!strcasecmp(v->name, "dring2context")) {
11944          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11945       } else if (!strcasecmp(v->name, "dring3context")) {
11946          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11947       } else if (!strcasecmp(v->name, "dring1")) {
11948          ringc = v->value;
11949          sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11950       } else if (!strcasecmp(v->name, "dring2")) {
11951          ringc = v->value;
11952          sscanf(ringc, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11953       } else if (!strcasecmp(v->name, "dring3")) {
11954          ringc = v->value;
11955          sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11956       } else if (!strcasecmp(v->name, "usecallerid")) {
11957          confp->chan.use_callerid = ast_true(v->value);
11958       } else if (!strcasecmp(v->name, "cidsignalling")) {
11959          if (!strcasecmp(v->value, "bell"))
11960             confp->chan.cid_signalling = CID_SIG_BELL;
11961          else if (!strcasecmp(v->value, "v23"))
11962             confp->chan.cid_signalling = CID_SIG_V23;
11963          else if (!strcasecmp(v->value, "dtmf"))
11964             confp->chan.cid_signalling = CID_SIG_DTMF;
11965          else if (!strcasecmp(v->value, "smdi"))
11966             confp->chan.cid_signalling = CID_SIG_SMDI;
11967          else if (!strcasecmp(v->value, "v23_jp"))
11968             confp->chan.cid_signalling = CID_SIG_V23_JP;
11969          else if (ast_true(v->value))
11970             confp->chan.cid_signalling = CID_SIG_BELL;
11971       } else if (!strcasecmp(v->name, "cidstart")) {
11972          if (!strcasecmp(v->value, "ring"))
11973             confp->chan.cid_start = CID_START_RING;
11974          else if (!strcasecmp(v->value, "polarity"))
11975             confp->chan.cid_start = CID_START_POLARITY;
11976          else if (ast_true(v->value))
11977             confp->chan.cid_start = CID_START_RING;
11978       } else if (!strcasecmp(v->name, "threewaycalling")) {
11979          confp->chan.threewaycalling = ast_true(v->value);
11980       } else if (!strcasecmp(v->name, "cancallforward")) {
11981          confp->chan.cancallforward = ast_true(v->value);
11982       } else if (!strcasecmp(v->name, "relaxdtmf")) {
11983          if (ast_true(v->value)) 
11984             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11985          else
11986             confp->chan.dtmfrelax = 0;
11987       } else if (!strcasecmp(v->name, "mailbox")) {
11988          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11989       } else if (!strcasecmp(v->name, "adsi")) {
11990          confp->chan.adsi = ast_true(v->value);
11991       } else if (!strcasecmp(v->name, "usesmdi")) {
11992          confp->chan.use_smdi = ast_true(v->value);
11993       } else if (!strcasecmp(v->name, "smdiport")) {
11994          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11995       } else if (!strcasecmp(v->name, "transfer")) {
11996          confp->chan.transfer = ast_true(v->value);
11997       } else if (!strcasecmp(v->name, "canpark")) {
11998          confp->chan.canpark = ast_true(v->value);
11999       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
12000          confp->chan.echocanbridged = ast_true(v->value);
12001       } else if (!strcasecmp(v->name, "busydetect")) {
12002          confp->chan.busydetect = ast_true(v->value);
12003       } else if (!strcasecmp(v->name, "busycount")) {
12004          confp->chan.busycount = atoi(v->value);
12005       } else if (!strcasecmp(v->name, "busypattern")) {
12006          if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
12007             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
12008          }
12009       } else if (!strcasecmp(v->name, "callprogress")) {
12010          if (ast_true(v->value))
12011             confp->chan.callprogress |= 1;
12012          else
12013             confp->chan.callprogress &= ~1;
12014       } else if (!strcasecmp(v->name, "faxdetect")) {
12015          if (!strcasecmp(v->value, "incoming")) {
12016             confp->chan.callprogress |= 4;
12017             confp->chan.callprogress &= ~2;
12018          } else if (!strcasecmp(v->value, "outgoing")) {
12019             confp->chan.callprogress &= ~4;
12020             confp->chan.callprogress |= 2;
12021          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
12022             confp->chan.callprogress |= 6;
12023          else
12024             confp->chan.callprogress &= ~6;
12025       } else if (!strcasecmp(v->name, "echocancel")) {
12026          if (!ast_strlen_zero(v->value)) {
12027             y = atoi(v->value);
12028          } else
12029             y = 0;
12030          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
12031             confp->chan.echocancel = y;
12032          else {
12033             confp->chan.echocancel = ast_true(v->value);
12034             if (confp->chan.echocancel)
12035                confp->chan.echocancel=128;
12036          }
12037       } else if (!strcasecmp(v->name, "echotraining")) {
12038          if (sscanf(v->value, "%d", &y) == 1) {
12039             if ((y < 10) || (y > 4000)) {
12040                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
12041             } else {
12042                confp->chan.echotraining = y;
12043             }
12044          } else if (ast_true(v->value)) {
12045             confp->chan.echotraining = 400;
12046          } else
12047             confp->chan.echotraining = 0;
12048       } else if (!strcasecmp(v->name, "hidecallerid")) {
12049          confp->chan.hidecallerid = ast_true(v->value);
12050       } else if (!strcasecmp(v->name, "hidecalleridname")) {
12051          confp->chan.hidecalleridname = ast_true(v->value);
12052       } else if (!strcasecmp(v->name, "pulsedial")) {
12053          confp->chan.pulse = ast_true(v->value);
12054       } else if (!strcasecmp(v->name, "callreturn")) {
12055          confp->chan.callreturn = ast_true(v->value);
12056       } else if (!strcasecmp(v->name, "callwaiting")) {
12057          confp->chan.callwaiting = ast_true(v->value);
12058       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
12059          confp->chan.callwaitingcallerid = ast_true(v->value);
12060       } else if (!strcasecmp(v->name, "context")) {
12061          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
12062       } else if (!strcasecmp(v->name, "language")) {
12063          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
12064       } else if (!strcasecmp(v->name, "progzone")) {
12065          ast_copy_string(progzone, v->value, sizeof(progzone));
12066       } else if (!strcasecmp(v->name, "mohinterpret") 
12067          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
12068          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
12069       } else if (!strcasecmp(v->name, "mohsuggest")) {
12070          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
12071       } else if (!strcasecmp(v->name, "stripmsd")) {
12072          confp->chan.stripmsd = atoi(v->value);
12073       } else if (!strcasecmp(v->name, "jitterbuffers")) {
12074          numbufs = atoi(v->value);
12075       } else if (!strcasecmp(v->name, "group")) {
12076          confp->chan.group = ast_get_group(v->value);
12077       } else if (!strcasecmp(v->name, "callgroup")) {
12078          confp->chan.callgroup = ast_get_group(v->value);
12079       } else if (!strcasecmp(v->name, "pickupgroup")) {
12080          confp->chan.pickupgroup = ast_get_group(v->value);
12081       } else if (!strcasecmp(v->name, "immediate")) {
12082          confp->chan.immediate = ast_true(v->value);
12083       } else if (!strcasecmp(v->name, "transfertobusy")) {
12084          confp->chan.transfertobusy = ast_true(v->value);
12085       } else if (!strcasecmp(v->name, "rxgain")) {
12086          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
12087             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
12088          }
12089       } else if (!strcasecmp(v->name, "txgain")) {
12090          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
12091             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
12092          }
12093       } else if (!strcasecmp(v->name, "tonezone")) {
12094          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
12095             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
12096          }
12097       } else if (!strcasecmp(v->name, "callerid")) {
12098          if (!strcasecmp(v->value, "asreceived")) {
12099             confp->chan.cid_num[0] = '\0';
12100             confp->chan.cid_name[0] = '\0';
12101          } else {
12102             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
12103          } 
12104       } else if (!strcasecmp(v->name, "fullname")) {
12105          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
12106       } else if (!strcasecmp(v->name, "cid_number")) {
12107          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
12108       } else if (!strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
12109          confp->chan.zaptrcallerid = ast_true(v->value);
12110       } else if (!strcasecmp(v->name, "restrictcid")) {
12111          confp->chan.restrictcid = ast_true(v->value);
12112       } else if (!strcasecmp(v->name, "usecallingpres")) {
12113          confp->chan.use_callingpres = ast_true(v->value);
12114       } else if (!strcasecmp(v->name, "accountcode")) {
12115          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
12116       } else if (!strcasecmp(v->name, "amaflags")) {
12117          y = ast_cdr_amaflags2int(v->value);
12118          if (y < 0) 
12119             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
12120          else
12121             confp->chan.amaflags = y;
12122       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
12123          confp->chan.polarityonanswerdelay = atoi(v->value);
12124       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
12125          confp->chan.answeronpolarityswitch = ast_true(v->value);
12126       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
12127          confp->chan.hanguponpolarityswitch = ast_true(v->value);
12128       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
12129          confp->chan.sendcalleridafter = atoi(v->value);
12130       } else if (!reload){ 
12131           if (!strcasecmp(v->name, "signalling")) {
12132             confp->chan.outsigmod = -1;
12133             if (!strcasecmp(v->value, "em")) {
12134                confp->chan.sig = SIG_EM;
12135             } else if (!strcasecmp(v->value, "em_e1")) {
12136                confp->chan.sig = SIG_EM_E1;
12137             } else if (!strcasecmp(v->value, "em_w")) {
12138                confp->chan.sig = SIG_EMWINK;
12139                confp->chan.radio = 0;
12140             } else if (!strcasecmp(v->value, "fxs_ls")) {
12141                confp->chan.sig = SIG_FXSLS;
12142                confp->chan.radio = 0;
12143             } else if (!strcasecmp(v->value, "fxs_gs")) {
12144                confp->chan.sig = SIG_FXSGS;
12145                confp->chan.radio = 0;
12146             } else if (!strcasecmp(v->value, "fxs_ks")) {
12147                confp->chan.sig = SIG_FXSKS;
12148                confp->chan.radio = 0;
12149             } else if (!strcasecmp(v->value, "fxo_ls")) {
12150                confp->chan.sig = SIG_FXOLS;
12151                confp->chan.radio = 0;
12152             } else if (!strcasecmp(v->value, "fxo_gs")) {
12153                confp->chan.sig = SIG_FXOGS;
12154                confp->chan.radio = 0;
12155             } else if (!strcasecmp(v->value, "fxo_ks")) {
12156                confp->chan.sig = SIG_FXOKS;
12157                confp->chan.radio = 0;
12158             } else if (!strcasecmp(v->value, "fxs_rx")) {
12159                confp->chan.sig = SIG_FXSKS;
12160                confp->chan.radio = 1;
12161             } else if (!strcasecmp(v->value, "fxo_rx")) {
12162                confp->chan.sig = SIG_FXOLS;
12163                confp->chan.radio = 1;
12164             } else if (!strcasecmp(v->value, "fxs_tx")) {
12165                confp->chan.sig = SIG_FXSLS;
12166                confp->chan.radio = 1;
12167             } else if (!strcasecmp(v->value, "fxo_tx")) {
12168                confp->chan.sig = SIG_FXOGS;
12169                confp->chan.radio = 1;
12170             } else if (!strcasecmp(v->value, "em_rx")) {
12171                confp->chan.sig = SIG_EM;
12172                confp->chan.radio = 1;
12173             } else if (!strcasecmp(v->value, "em_tx")) {
12174                confp->chan.sig = SIG_EM;
12175                confp->chan.radio = 1;
12176             } else if (!strcasecmp(v->value, "em_rxtx")) {
12177                confp->chan.sig = SIG_EM;
12178                confp->chan.radio = 2;
12179             } else if (!strcasecmp(v->value, "em_txrx")) {
12180                confp->chan.sig = SIG_EM;
12181                confp->chan.radio = 2;
12182             } else if (!strcasecmp(v->value, "sf")) {
12183                confp->chan.sig = SIG_SF;
12184                confp->chan.radio = 0;
12185             } else if (!strcasecmp(v->value, "sf_w")) {
12186                confp->chan.sig = SIG_SFWINK;
12187                confp->chan.radio = 0;
12188             } else if (!strcasecmp(v->value, "sf_featd")) {
12189                confp->chan.sig = SIG_FEATD;
12190                confp->chan.radio = 0;
12191             } else if (!strcasecmp(v->value, "sf_featdmf")) {
12192                confp->chan.sig = SIG_FEATDMF;
12193                confp->chan.radio = 0;
12194             } else if (!strcasecmp(v->value, "sf_featb")) {
12195                confp->chan.sig = SIG_SF_FEATB;
12196                confp->chan.radio = 0;
12197             } else if (!strcasecmp(v->value, "sf")) {
12198                confp->chan.sig = SIG_SF;
12199                confp->chan.radio = 0;
12200             } else if (!strcasecmp(v->value, "sf_rx")) {
12201                confp->chan.sig = SIG_SF;
12202                confp->chan.radio = 1;
12203             } else if (!strcasecmp(v->value, "sf_tx")) {
12204                confp->chan.sig = SIG_SF;
12205                confp->chan.radio = 1;
12206             } else if (!strcasecmp(v->value, "sf_rxtx")) {
12207                confp->chan.sig = SIG_SF;
12208                confp->chan.radio = 2;
12209             } else if (!strcasecmp(v->value, "sf_txrx")) {
12210                confp->chan.sig = SIG_SF;
12211                confp->chan.radio = 2;
12212             } else if (!strcasecmp(v->value, "featd")) {
12213                confp->chan.sig = SIG_FEATD;
12214                confp->chan.radio = 0;
12215             } else if (!strcasecmp(v->value, "featdmf")) {
12216                confp->chan.sig = SIG_FEATDMF;
12217                confp->chan.radio = 0;
12218             } else if (!strcasecmp(v->value, "featdmf_ta")) {
12219                confp->chan.sig = SIG_FEATDMF_TA;
12220                confp->chan.radio = 0;
12221             } else if (!strcasecmp(v->value, "e911")) {
12222                confp->chan.sig = SIG_E911;
12223                confp->chan.radio = 0;
12224             } else if (!strcasecmp(v->value, "fgccama")) {
12225                confp->chan.sig = SIG_FGC_CAMA;
12226                confp->chan.radio = 0;
12227             } else if (!strcasecmp(v->value, "fgccamamf")) {
12228                confp->chan.sig = SIG_FGC_CAMAMF;
12229                confp->chan.radio = 0;
12230             } else if (!strcasecmp(v->value, "featb")) {
12231                confp->chan.sig = SIG_FEATB;
12232                confp->chan.radio = 0;
12233 #ifdef HAVE_PRI
12234             } else if (!strcasecmp(v->value, "pri_net")) {
12235                confp->chan.radio = 0;
12236                confp->chan.sig = SIG_PRI;
12237                confp->pri.nodetype = PRI_NETWORK;
12238             } else if (!strcasecmp(v->value, "pri_cpe")) {
12239                confp->chan.sig = SIG_PRI;
12240                confp->chan.radio = 0;
12241                confp->pri.nodetype = PRI_CPE;
12242             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
12243                confp->chan.sig = SIG_GR303FXOKS;
12244                confp->chan.radio = 0;
12245                confp->pri.nodetype = PRI_NETWORK;
12246             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
12247                confp->chan.sig = SIG_GR303FXSKS;
12248                confp->chan.radio = 0;
12249                confp->pri.nodetype = PRI_CPE;
12250             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
12251                confp->chan.radio = 0;
12252                confp->chan.sig = SIG_PRI;
12253                confp->pri.nodetype = BRI_NETWORK_PTMP;
12254             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
12255                confp->chan.sig = SIG_PRI;
12256                confp->chan.radio = 0;
12257                confp->pri.nodetype = BRI_CPE_PTMP;
12258             } else if (!strcasecmp(v->value, "bri_net")) {
12259                confp->chan.radio = 0;
12260                confp->chan.sig = SIG_PRI;
12261                confp->pri.nodetype = BRI_NETWORK;
12262             } else if (!strcasecmp(v->value, "bri_cpe")) {
12263                confp->chan.sig = SIG_PRI;
12264                confp->chan.radio = 0;
12265                confp->pri.nodetype = BRI_CPE;
12266 #endif
12267 #ifdef HAVE_GSMAT
12268             } else if (!strcasecmp(v->value, "gsm")) {
12269                confp->chan.sig = SIG_GSM;
12270                confp->chan.radio = 0;
12271 #endif
12272             } else {
12273                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
12274             }
12275           } else if (!strcasecmp(v->name, "outsignalling")) {
12276             if (!strcasecmp(v->value, "em")) {
12277                confp->chan.outsigmod = SIG_EM;
12278             } else if (!strcasecmp(v->value, "em_e1")) {
12279                confp->chan.outsigmod = SIG_EM_E1;
12280             } else if (!strcasecmp(v->value, "em_w")) {
12281                confp->chan.outsigmod = SIG_EMWINK;
12282             } else if (!strcasecmp(v->value, "sf")) {
12283                confp->chan.outsigmod = SIG_SF;
12284             } else if (!strcasecmp(v->value, "sf_w")) {
12285                confp->chan.outsigmod = SIG_SFWINK;
12286             } else if (!strcasecmp(v->value, "sf_featd")) {
12287                confp->chan.outsigmod = SIG_FEATD;
12288             } else if (!strcasecmp(v->value, "sf_featdmf")) {
12289                confp->chan.outsigmod = SIG_FEATDMF;
12290             } else if (!strcasecmp(v->value, "sf_featb")) {
12291                confp->chan.outsigmod = SIG_SF_FEATB;
12292             } else if (!strcasecmp(v->value, "sf")) {
12293                confp->chan.outsigmod = SIG_SF;
12294             } else if (!strcasecmp(v->value, "featd")) {
12295                confp->chan.outsigmod = SIG_FEATD;
12296             } else if (!strcasecmp(v->value, "featdmf")) {
12297                confp->chan.outsigmod = SIG_FEATDMF;
12298             } else if (!strcasecmp(v->value, "featdmf_ta")) {
12299                confp->chan.outsigmod = SIG_FEATDMF_TA;
12300             } else if (!strcasecmp(v->value, "e911")) {
12301                confp->chan.outsigmod = SIG_E911;
12302             } else if (!strcasecmp(v->value, "fgccama")) {
12303                confp->chan.outsigmod = SIG_FGC_CAMA;
12304             } else if (!strcasecmp(v->value, "fgccamamf")) {
12305                confp->chan.outsigmod = SIG_FGC_CAMAMF;
12306             } else if (!strcasecmp(v->value, "featb")) {
12307                confp->chan.outsigmod = SIG_FEATB;
12308             } else {
12309                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
12310             }
12311 #ifdef HAVE_PRI
12312          } else if (!strcasecmp(v->name, "pridialplan")) {
12313             if (!strcasecmp(v->value, "national")) {
12314                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
12315             } else if (!strcasecmp(v->value, "unknown")) {
12316                confp->pri.dialplan = PRI_UNKNOWN + 1;
12317             } else if (!strcasecmp(v->value, "private")) {
12318                confp->pri.dialplan = PRI_PRIVATE + 1;
12319             } else if (!strcasecmp(v->value, "international")) {
12320                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
12321             } else if (!strcasecmp(v->value, "local")) {
12322                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
12323             } else if (!strcasecmp(v->value, "dynamic")) {
12324                confp->pri.dialplan = -1;
12325             } else {
12326                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
12327             }
12328          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
12329             if (!strcasecmp(v->value, "national")) {
12330                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
12331             } else if (!strcasecmp(v->value, "unknown")) {
12332                confp->pri.localdialplan = PRI_UNKNOWN + 1;
12333             } else if (!strcasecmp(v->value, "private")) {
12334                confp->pri.localdialplan = PRI_PRIVATE + 1;
12335             } else if (!strcasecmp(v->value, "international")) {
12336                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
12337             } else if (!strcasecmp(v->value, "local")) {
12338                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
12339             } else if (!strcasecmp(v->value, "dynamic")) {
12340                confp->pri.localdialplan = -1;
12341             } else {
12342                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
12343             }
12344          } else if (!strcasecmp(v->name, "switchtype")) {
12345             if (!strcasecmp(v->value, "national")) 
12346                confp->pri.switchtype = PRI_SWITCH_NI2;
12347             else if (!strcasecmp(v->value, "ni1"))
12348                confp->pri.switchtype = PRI_SWITCH_NI1;
12349             else if (!strcasecmp(v->value, "dms100"))
12350                confp->pri.switchtype = PRI_SWITCH_DMS100;
12351             else if (!strcasecmp(v->value, "4ess"))
12352                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
12353             else if (!strcasecmp(v->value, "5ess"))
12354                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
12355             else if (!strcasecmp(v->value, "euroisdn"))
12356                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
12357             else if (!strcasecmp(v->value, "qsig"))
12358                confp->pri.switchtype = PRI_SWITCH_QSIG;
12359             else {
12360                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
12361                return -1;
12362             }
12363          } else if (!strcasecmp(v->name, "nsf")) {
12364             if (!strcasecmp(v->value, "sdn"))
12365                confp->pri.nsf = PRI_NSF_SDN;
12366             else if (!strcasecmp(v->value, "megacom"))
12367                confp->pri.nsf = PRI_NSF_MEGACOM;
12368             else if (!strcasecmp(v->value, "tollfreemegacom"))
12369                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
12370             else if (!strcasecmp(v->value, "accunet"))
12371                confp->pri.nsf = PRI_NSF_ACCUNET;
12372             else if (!strcasecmp(v->value, "none"))
12373                confp->pri.nsf = PRI_NSF_NONE;
12374             else {
12375                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
12376                confp->pri.nsf = PRI_NSF_NONE;
12377             }
12378          } else if (!strcasecmp(v->name, "priindication")) {
12379             if (!strcasecmp(v->value, "outofband"))
12380                confp->chan.priindication_oob = 1;
12381             else if (!strcasecmp(v->value, "inband"))
12382                confp->chan.priindication_oob = 0;
12383             else if (!strcasecmp(v->value, "passthrough"))
12384                confp->chan.priindication_oob = 2;
12385             else
12386                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband', 'outofband' or 'passthrough' at line %d\n",
12387                   v->value, v->lineno);
12388          } else if (!strcasecmp(v->name, "pritransfer")) {
12389             if (!strcasecmp(v->value, "no"))
12390                confp->chan.pritransfer = 0;
12391             else if (!strcasecmp(v->value, "ect"))
12392                confp->chan.pritransfer = 1;
12393             else if (!strcasecmp(v->value, "hangup"))
12394                confp->chan.pritransfer = 2;
12395             else
12396                ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
12397                   v->value, v->lineno);
12398          } else if (!strcasecmp(v->name, "priexclusive")) {
12399             confp->chan.priexclusive = ast_true(v->value);
12400          } else if (!strcasecmp(v->name, "internationalprefix")) {
12401             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
12402          } else if (!strcasecmp(v->name, "nationalprefix")) {
12403             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
12404          } else if (!strcasecmp(v->name, "localprefix")) {
12405             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
12406          } else if (!strcasecmp(v->name, "privateprefix")) {
12407             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
12408          } else if (!strcasecmp(v->name, "unknownprefix")) {
12409             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
12410          } else if (!strcasecmp(v->name, "nocid")) {
12411             ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
12412          } else if (!strcasecmp(v->name, "withheldcid")) {
12413             ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
12414          } else if (!strcasecmp(v->name, "pin")) {
12415             ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
12416          } else if (!strcasecmp(v->name, "exten")) {
12417             ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
12418          } else if (!strcasecmp(v->name, "resetinterval")) {
12419             if (!strcasecmp(v->value, "never"))
12420                confp->pri.resetinterval = -1;
12421             else if (atoi(v->value) >= 60)
12422                confp->pri.resetinterval = atoi(v->value);
12423             else
12424                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
12425                   v->value, v->lineno);
12426          } else if (!strcasecmp(v->name, "minunused")) {
12427             confp->pri.minunused = atoi(v->value);
12428          } else if (!strcasecmp(v->name, "minidle")) {
12429             confp->pri.minidle = atoi(v->value); 
12430          } else if (!strcasecmp(v->name, "idleext")) {
12431             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
12432          } else if (!strcasecmp(v->name, "idledial")) {
12433             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
12434          } else if (!strcasecmp(v->name, "pritrustusercid")) {
12435             confp->pri.usercid = ast_true(v->value);
12436          } else if (!strcasecmp(v->name, "overlapdial")) {
12437             confp->pri.overlapdial = ast_true(v->value);
12438          } else if (!strcasecmp(v->name, "pritimer")) {
12439 #ifdef PRI_GETSET_TIMERS
12440             char *timerc, *c;
12441             int timer, timeridx;
12442             c = v->value;
12443             timerc = strsep(&c, ",");
12444             if (timerc) {
12445                timer = atoi(c);
12446                if (!timer)
12447                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
12448                else {
12449                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
12450                      pritimers[timeridx] = timer;
12451                   else
12452                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
12453                }
12454             } else
12455                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
12456 
12457          } else if (!strcasecmp(v->name, "facilityenable")) {
12458             confp->pri.facilityenable = ast_true(v->value);
12459 #endif /* PRI_GETSET_TIMERS */
12460 #endif /* HAVE_PRI */
12461          } else if (!strcasecmp(v->name, "cadence")) {
12462             /* setup to scan our argument */
12463             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
12464             int i;
12465             struct zt_ring_cadence new_cadence;
12466             int cid_location = -1;
12467             int firstcadencepos = 0;
12468             char original_args[80];
12469             int cadence_is_ok = 1;
12470 
12471             ast_copy_string(original_args, v->value, sizeof(original_args));
12472             /* 16 cadences allowed (8 pairs) */
12473             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]);
12474    
12475             /* Cadence must be even (on/off) */
12476             if (element_count % 2 == 1) {
12477                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
12478                cadence_is_ok = 0;
12479             }
12480    
12481             /* Ring cadences cannot be negative */
12482             for (i = 0; i < element_count; i++) {
12483                if (c[i] == 0) {
12484                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
12485                   cadence_is_ok = 0;
12486                   break;
12487                } else if (c[i] < 0) {
12488                   if (i % 2 == 1) {
12489                      /* Silence duration, negative possibly okay */
12490                      if (cid_location == -1) {
12491                         cid_location = i;
12492                         c[i] *= -1;
12493                      } else {
12494                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
12495                         cadence_is_ok = 0;
12496                         break;
12497                      }
12498                   } else {
12499                      if (firstcadencepos == 0) {
12500                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
12501                                  /* duration will be passed negative to the zaptel driver */
12502                      } else {
12503                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
12504                         cadence_is_ok = 0;
12505                         break;
12506                      }
12507                   }
12508                }
12509             }
12510    
12511             /* Substitute our scanned cadence */
12512             for (i = 0; i < 16; i++) {
12513                new_cadence.ringcadence[i] = c[i];
12514             }
12515    
12516             if (cadence_is_ok) {
12517                /* ---we scanned it without getting annoyed; now some sanity checks--- */
12518                if (element_count < 2) {
12519                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
12520                } else {
12521                   if (cid_location == -1) {
12522                      /* user didn't say; default to first pause */
12523                      cid_location = 1;
12524                   } else {
12525                      /* convert element_index to cidrings value */
12526                      cid_location = (cid_location + 1) / 2;
12527                   }
12528                   /* ---we like their cadence; try to install it--- */
12529                   if (!user_has_defined_cadences++)
12530                      /* this is the first user-defined cadence; clear the default user cadences */
12531                      num_cadence = 0;
12532                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
12533                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
12534                   else {
12535                      cadences[num_cadence] = new_cadence;
12536                      cidrings[num_cadence++] = cid_location;
12537                      if (option_verbose > 2)
12538                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
12539                   }
12540                }
12541             }
12542          } else if (!strcasecmp(v->name, "ringtimeout")) {
12543             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
12544          } else if (!strcasecmp(v->name, "prewink")) {
12545             confp->timing.prewinktime = atoi(v->value);
12546          } else if (!strcasecmp(v->name, "preflash")) {
12547             confp->timing.preflashtime = atoi(v->value);
12548          } else if (!strcasecmp(v->name, "wink")) {
12549             confp->timing.winktime = atoi(v->value);
12550          } else if (!strcasecmp(v->name, "flash")) {
12551             confp->timing.flashtime = atoi(v->value);
12552          } else if (!strcasecmp(v->name, "start")) {
12553             confp->timing.starttime = atoi(v->value);
12554          } else if (!strcasecmp(v->name, "rxwink")) {
12555             confp->timing.rxwinktime = atoi(v->value);
12556          } else if (!strcasecmp(v->name, "rxflash")) {
12557             confp->timing.rxflashtime = atoi(v->value);
12558          } else if (!strcasecmp(v->name, "debounce")) {
12559             confp->timing.debouncetime = atoi(v->value);
12560          } else if (!strcasecmp(v->name, "toneduration")) {
12561             int toneduration;
12562             int ctlfd;
12563             int res;
12564             struct zt_dialparams dps;
12565 
12566             ctlfd = open("/dev/zap/ctl", O_RDWR);
12567             if (ctlfd == -1) {
12568                ast_log(LOG_ERROR, "Unable to open /dev/zap/ctl to set toneduration\n");
12569                return -1;
12570             }
12571 
12572             toneduration = atoi(v->value);
12573             if (toneduration > -1) {
12574                memset(&dps, 0, sizeof(dps));
12575 
12576                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
12577                res = ioctl(ctlfd, ZT_SET_DIALPARAMS, &dps);
12578                if (res < 0) {
12579                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms\n", toneduration);
12580                   return -1;
12581                }
12582             }
12583             close(ctlfd);
12584          } else if (!strcasecmp(v->name, "defaultcic")) {
12585             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
12586          } else if (!strcasecmp(v->name, "defaultozz")) {
12587             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
12588          } 
12589       } else if (!skipchannels)
12590          ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
12591    }
12592    if (zapchan[0]) { 
12593       /* The user has set 'zapchan' */
12594       /*< \todo pass proper line number instead of 0 */
12595       if (build_channels(confp, 0, zapchan, reload, 0, &found_pseudo)) {
12596          return -1;
12597       }
12598    }
12599    /*< \todo why check for the pseudo in the per-channel section.
12600     * Any actual use for manual setup of the pseudo channel? */
12601    if (!found_pseudo && reload == 0) {
12602       /* Make sure pseudo isn't a member of any groups if
12603          we're automatically making it. */   
12604       
12605       confp->chan.group = 0;
12606       confp->chan.callgroup = 0;
12607       confp->chan.pickupgroup = 0;
12608 
12609       tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
12610 
12611       if (tmp) {
12612          if (option_verbose > 2)
12613             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
12614       } else {
12615          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
12616       }
12617    }
12618    return 0;
12619 }

static int reload ( void   )  [static]

Definition at line 12975 of file chan_zap.c.

References ast_log(), LOG_WARNING, and setup_zap().

12976 {
12977    int res = 0;
12978 
12979    res = setup_zap(1);
12980    if (res) {
12981       ast_log(LOG_WARNING, "Reload of chan_zap.so is unsuccessful!\n");
12982       return -1;
12983    }
12984    return 0;
12985 }

static int reset_conf ( struct zt_pvt p  )  [static]

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

01399 {
01400    ZT_CONFINFO zi;
01401    memset(&zi, 0, sizeof(zi));
01402    p->confno = -1;
01403    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01404    if (p->subs[SUB_REAL].zfd > -1) {
01405       if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &zi))
01406          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d!\n", p->channel);
01407    }
01408    return 0;
01409 }

static int restart_monitor ( void   )  [static]

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

07196 {
07197    pthread_attr_t attr;
07198    pthread_attr_init(&attr);
07199    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07200    /* If we're supposed to be stopped -- stay stopped */
07201    if (monitor_thread == AST_PTHREADT_STOP)
07202       return 0;
07203    ast_mutex_lock(&monlock);
07204    if (monitor_thread == pthread_self()) {
07205       ast_mutex_unlock(&monlock);
07206       ast_log(LOG_WARNING, "Cannot kill myself\n");
07207       return -1;
07208    }
07209    if (monitor_thread != AST_PTHREADT_NULL) {
07210       /* Wake up the thread */
07211       pthread_kill(monitor_thread, SIGURG);
07212    } else {
07213       /* Start a new monitor */
07214       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07215          ast_mutex_unlock(&monlock);
07216          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07217          pthread_attr_destroy(&attr);
07218          return -1;
07219       }
07220    }
07221    ast_mutex_unlock(&monlock);
07222    pthread_attr_destroy(&attr);
07223    return 0;
07224 }

static int restore_conference ( struct zt_pvt p  )  [static]

Definition at line 1734 of file chan_zap.c.

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

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

01735 {
01736    int res;
01737    if (p->saveconf.confmode) {
01738       res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &p->saveconf);
01739       p->saveconf.confmode = 0;
01740       if (res) {
01741          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01742          return -1;
01743       }
01744    }
01745    if (option_debug)
01746       ast_log(LOG_DEBUG, "Restored conferencing\n");
01747    return 0;
01748 }

static int restore_gains ( struct zt_pvt p  )  [static]

Definition at line 1661 of file chan_zap.c.

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

Referenced by ss_thread(), and zt_hangup().

01662 {
01663    int res;
01664 
01665    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
01666    if (res) {
01667       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01668       return -1;
01669    }
01670 
01671    return 0;
01672 }

static int save_conference ( struct zt_pvt p  )  [static]

Definition at line 1706 of file chan_zap.c.

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

Referenced by zt_callwait(), and zt_handle_event().

01707 {
01708    struct zt_confinfo c;
01709    int res;
01710    if (p->saveconf.confmode) {
01711       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01712       return -1;
01713    }
01714    p->saveconf.chan = 0;
01715    res = ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &p->saveconf);
01716    if (res) {
01717       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01718       p->saveconf.confmode = 0;
01719       return -1;
01720    }
01721    c.chan = 0;
01722    c.confno = 0;
01723    c.confmode = ZT_CONF_NORMAL;
01724    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &c);
01725    if (res) {
01726       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01727       return -1;
01728    }
01729    if (option_debug)
01730       ast_log(LOG_DEBUG, "Disabled conferencing\n");
01731    return 0;
01732 }

static int send_callerid ( struct zt_pvt p  )  [static]

Definition at line 1774 of file chan_zap.c.

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

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

01775 {
01776    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
01777    int res;
01778    /* Take out of linear mode if necessary */
01779    if (p->subs[SUB_REAL].linear) {
01780       p->subs[SUB_REAL].linear = 0;
01781       zt_setlinear(p->subs[SUB_REAL].zfd, 0);
01782    }
01783    while (p->cidpos < p->cidlen) {
01784       res = write(p->subs[SUB_REAL].zfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01785       if (res < 0) {
01786          if (errno == EAGAIN)
01787             return 0;
01788          else {
01789             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01790             return -1;
01791          }
01792       }
01793       if (!res)
01794          return 0;
01795       p->cidpos += res;
01796    }
01797    free(p->cidspill);
01798    p->cidspill = NULL;
01799    if (p->callwaitcas) {
01800       /* Wait for CID/CW to expire */
01801       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01802    } else
01803       restore_conference(p);
01804    return 0;
01805 }

static int send_cwcidspill ( struct zt_pvt p  )  [static]

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

01753 {
01754    p->callwaitcas = 0;
01755    p->cidcwexpire = 0;
01756    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01757       return -1;
01758    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01759    /* Make sure we account for the end */
01760    p->cidlen += READ_SIZE * 4;
01761    p->cidpos = 0;
01762    send_callerid(p);
01763    if (option_verbose > 2)
01764       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01765    return 0;
01766 }

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

Definition at line 1642 of file chan_zap.c.

References set_actual_rxgain(), and set_actual_txgain().

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

01643 {
01644    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01645 }

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

Definition at line 1624 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

01625 {
01626    struct zt_gains g;
01627    int res;
01628 
01629    memset(&g, 0, sizeof(g));
01630    g.chan = chan;
01631    res = ioctl(fd, ZT_GETGAINS, &g);
01632    if (res) {
01633       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01634       return res;
01635    }
01636 
01637    fill_rxgain(&g, gain, law);
01638 
01639    return ioctl(fd, ZT_SETGAINS, &g);
01640 }

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

Definition at line 1605 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

01606 {
01607    struct zt_gains g;
01608    int res;
01609 
01610    memset(&g, 0, sizeof(g));
01611    g.chan = chan;
01612    res = ioctl(fd, ZT_GETGAINS, &g);
01613    if (res) {
01614       if (option_debug)
01615          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01616       return res;
01617    }
01618 
01619    fill_txgain(&g, gain, law);
01620 
01621    return ioctl(fd, ZT_SETGAINS, &g);
01622 }

static int setup_zap ( int  reload  )  [static]

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

12622 {
12623    struct ast_config *cfg;
12624    struct ast_variable *v;
12625    struct zt_chan_conf conf = zt_chan_conf_default();
12626    int res;
12627 
12628 #ifdef HAVE_PRI
12629    char *c;
12630    int spanno;
12631    int i, x;
12632    int logicalspan;
12633    int trunkgroup;
12634    int dchannels[NUM_DCHANS];
12635 #endif
12636 
12637    cfg = ast_config_load(config);
12638 
12639    /* Error if we have no config file */
12640    if (!cfg) {
12641       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
12642       return 0;
12643    }
12644 
12645    /* It's a little silly to lock it, but we mind as well just to be sure */
12646    ast_mutex_lock(&iflock);
12647 #ifdef HAVE_PRI
12648    if (!reload) {
12649       /* Process trunkgroups first */
12650       v = ast_variable_browse(cfg, "trunkgroups");
12651       while (v) {
12652          if (!strcasecmp(v->name, "trunkgroup")) {
12653             trunkgroup = atoi(v->value);
12654             if (trunkgroup > 0) {
12655                if ((c = strchr(v->value, ','))) {
12656                   i = 0;
12657                   memset(dchannels, 0, sizeof(dchannels));
12658                   while (c && (i < NUM_DCHANS)) {
12659                      dchannels[i] = atoi(c + 1);
12660                      if (dchannels[i] < 0) {
12661                         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);
12662                      } else
12663                         i++;
12664                      c = strchr(c + 1, ',');
12665                   }
12666                   if (i) {
12667                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
12668                         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);
12669                      } else if (option_verbose > 1)
12670                         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");
12671                   } else
12672                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
12673                } else
12674                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
12675             } else
12676                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
12677          } else if (!strcasecmp(v->name, "spanmap")) {
12678             spanno = atoi(v->value);
12679             if (spanno > 0) {
12680                if ((c = strchr(v->value, ','))) {
12681                   trunkgroup = atoi(c + 1);
12682                   if (trunkgroup > 0) {
12683                      if ((c = strchr(c + 1, ','))) 
12684                         logicalspan = atoi(c + 1);
12685                      else
12686                         logicalspan = 0;
12687                      if (logicalspan >= 0) {
12688                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
12689                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12690                         } else if (option_verbose > 1) 
12691                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12692                      } else
12693                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
12694                   } else
12695                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
12696                } else
12697                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
12698             } else
12699                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
12700          } else {
12701             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
12702          }
12703          v = v->next;
12704       }
12705    }
12706 #endif
12707    
12708    /* Copy the default jb config over global_jbconf */
12709    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
12710 
12711    v = ast_variable_browse(cfg, "channels");
12712    res = process_zap(&conf, v, reload, 0);
12713    ast_mutex_unlock(&iflock);
12714    ast_config_destroy(cfg);
12715    if (res)
12716       return res;
12717    cfg = ast_config_load("users.conf");
12718    if (cfg) {
12719       char *cat;
12720       const char *chans;
12721       process_zap(&conf, ast_variable_browse(cfg, "general"), 1, 1);
12722       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
12723          if (!strcasecmp(cat, "general"))
12724             continue;
12725          chans = ast_variable_retrieve(cfg, cat, "zapchan");
12726          if (!ast_strlen_zero(chans)) {
12727             struct zt_chan_conf sect_conf;
12728             memcpy(&sect_conf, &conf, sizeof(sect_conf));
12729 
12730             process_zap(&sect_conf, ast_variable_browse(cfg, cat), reload, 0);
12731          }
12732       }
12733       ast_config_destroy(cfg);
12734    }
12735 #ifdef HAVE_PRI
12736    if (!reload) {
12737       for (x = 0; x < NUM_SPANS; x++) {
12738          pris[x].debugfd = -1;
12739          if (pris[x].pvts[0]) {
12740             if (start_pri(pris + x)) {
12741                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
12742                return -1;
12743             } else if (option_verbose > 1)
12744                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
12745          }
12746       }
12747    }
12748 #endif
12749    /* And start the monitor for the first time */
12750    restart_monitor();
12751    return 0;
12752 }

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

Definition at line 5586 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_shrink_phone_number(), ast_smdi_md_message_destroy(), 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(), ASTOBJ_UNREF, 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, CID_START_RING, zt_pvt::context, ast_channel::context, ringContextData::contextData, zt_pvt::defcontext, zt_pvt::dnd, zt_pvt::dop, zt_pvt::drings, zt_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, zt_pvt::dtmfrelax, errno, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, zt_pvt::exten, exten, ast_frame::frametype, free, func, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, zt_pvt::hanguponpolarityswitch, zt_pvt::hardwaredtmf, zt_pvt::hidecallerid, zt_pvt::immediate, ISTRUNK, zt_pvt::lastcid_num, len, zt_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event(), my_getsigstr(), name, NEED_MFDETECT, option_debug, option_verbose, zt_pvt::owner, zt_subchannel::owner, pbx_builtin_setvar_helper(), zt_pvt::polarity, POLARITY_IDLE, POLARITY_REV, restore_gains(), distRingData::ring, zt_distRings::ringContext, zt_distRings::ringnum, ast_channel::rings, 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_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, ast_frame::subclass, zt_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, zt_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), zt_pvt::use_callerid, zt_pvt::use_smdi, zt_pvt::usedistinctiveringdetection, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, 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().

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

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

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

00898 {
00899    int tchan;
00900    int tinthreeway;
00901    struct ast_channel *towner;
00902 
00903    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
00904 
00905    tchan = p->subs[a].chan;
00906    towner = p->subs[a].owner;
00907    tinthreeway = p->subs[a].inthreeway;
00908 
00909    p->subs[a].chan = p->subs[b].chan;
00910    p->subs[a].owner = p->subs[b].owner;
00911    p->subs[a].inthreeway = p->subs[b].inthreeway;
00912 
00913    p->subs[b].chan = tchan;
00914    p->subs[b].owner = towner;
00915    p->subs[b].inthreeway = tinthreeway;
00916 
00917    if (p->subs[a].owner) 
00918       p->subs[a].owner->fds[0] = p->subs[a].zfd;
00919    if (p->subs[b].owner) 
00920       p->subs[b].owner->fds[0] = p->subs[b].zfd;
00921    wakeup_sub(p, a, NULL);
00922    wakeup_sub(p, b, NULL);
00923 }

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

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

01024 {
01025    if (!x) {
01026       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01027       return -1;
01028    }
01029    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01030    if (p->subs[x].zfd > -1) {
01031       zt_close(p->subs[x].zfd);
01032    }
01033    p->subs[x].zfd = -1;
01034    p->subs[x].linear = 0;
01035    p->subs[x].chan = 0;
01036    p->subs[x].owner = NULL;
01037    p->subs[x].inthreeway = 0;
01038    p->polarity = POLARITY_IDLE;
01039    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01040    return 0;
01041 }

static int unload_module ( void   )  [static]

Definition at line 11806 of file chan_zap.c.

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

11807 {
11808 #ifdef HAVE_PRI      
11809    int y;
11810    for (y = 0; y < NUM_SPANS; y++)
11811       ast_mutex_destroy(&pris[y].lock);
11812 #endif
11813    return __unload_module();
11814 }

static int update_conf ( struct zt_pvt p  )  [static]

Definition at line 1411 of file chan_zap.c.

References ast_log(), zt_pvt::channel, conf_add(), conf_del(), zt_pvt::confno, GET_CHANNEL, zt_pvt::inconference, zt_subchannel::inthreeway, isslavenative(), LOG_DEBUG, zt_pvt::master, MAX_SLAVES, option_debug, zt_pvt::slaves, SUB_REAL, zt_pvt::subs, and zt_subchannel::zfd.

Referenced by __zt_exception(), mkintf(), zt_bridge(), zt_fixup(), zt_handle_event(), zt_hangup(), and zt_unlink().

01412 {
01413    int needconf = 0;
01414    int x;
01415    int useslavenative;
01416    struct zt_pvt *slave = NULL;
01417 
01418    useslavenative = isslavenative(p, &slave);
01419    /* Start with the obvious, general stuff */
01420    for (x = 0; x < 3; x++) {
01421       /* Look for three way calls */
01422       if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway) {
01423          conf_add(p, &p->subs[x], x, 0);
01424          needconf++;
01425       } else {
01426          conf_del(p, &p->subs[x], x);
01427       }
01428    }
01429    /* If we have a slave, add him to our conference now. or DAX
01430       if this is slave native */
01431    for (x = 0; x < MAX_SLAVES; x++) {
01432       if (p->slaves[x]) {
01433          if (useslavenative)
01434             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01435          else {
01436             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01437             needconf++;
01438          }
01439       }
01440    }
01441    /* If we're supposed to be in there, do so now */
01442    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01443       if (useslavenative)
01444          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01445       else {
01446          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01447          needconf++;
01448       }
01449    }
01450    /* If we have a master, add ourselves to his conference */
01451    if (p->master) {
01452       if (isslavenative(p->master, NULL)) {
01453          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01454       } else {
01455          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01456       }
01457    }
01458    if (!needconf) {
01459       /* Nobody is left (or should be left) in our conference.
01460          Kill it. */
01461       p->confno = -1;
01462    }
01463    if (option_debug)
01464       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01465    return 0;
01466 }

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

Definition at line 841 of file chan_zap.c.

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

Referenced by swap_subs().

00843 {
00844 #ifdef HAVE_PRI
00845    if (pri)
00846       ast_mutex_unlock(&pri->lock);
00847 #endif         
00848    for (;;) {
00849       if (p->subs[a].owner) {
00850          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00851             DEADLOCK_AVOIDANCE(&p->lock);
00852          } else {
00853             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
00854             ast_mutex_unlock(&p->subs[a].owner->lock);
00855             break;
00856          }
00857       } else
00858          break;
00859    }
00860 #ifdef HAVE_PRI
00861    if (pri)
00862       ast_mutex_lock(&pri->lock);
00863 #endif         
00864 }

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

Definition at line 11158 of file chan_zap.c.

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

11159 {
11160    int channel;
11161    
11162    if (argc != 4)
11163       return RESULT_SHOWUSAGE;
11164    
11165    channel = atoi(argv[3]);
11166 
11167    return zap_destroy_channel_bynum(channel);
11168 }

static int zap_destroy_channel_bynum ( int  channel  )  [static]

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

06744 {
06745    struct zt_pvt *tmp = NULL;
06746    struct zt_pvt *prev = NULL;
06747 
06748    tmp = iflist;
06749    while (tmp) {
06750       if (tmp->channel == channel) {
06751          destroy_channel(prev, tmp, 1);
06752          return RESULT_SUCCESS;
06753       }
06754       prev = tmp;
06755       tmp = tmp->next;
06756    }
06757    return RESULT_FAILURE;
06758 }

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

Definition at line 11546 of file chan_zap.c.

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

Referenced by action_transfer(), and action_transferhangup().

11547 {
11548    if (p) {
11549       switch (mode) {
11550          case TRANSFER:
11551             p->fake_event = ZT_EVENT_WINKFLASH;
11552             break;
11553          case HANGUP:
11554             p->fake_event = ZT_EVENT_ONHOOK;
11555             break;
11556          default:
11557             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
11558       }
11559    }
11560    return 0;
11561 }

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

Definition at line 869 of file chan_zap.c.

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

Referenced by action_zapdialoffhook().

00871 {
00872    /* We must unlock the PRI to avoid the possibility of a deadlock */
00873 #ifdef HAVE_PRI
00874    if (pri)
00875       ast_mutex_unlock(&pri->lock);
00876 #endif      
00877    for (;;) {
00878       if (p->owner) {
00879          if (ast_mutex_trylock(&p->owner->lock)) {
00880             DEADLOCK_AVOIDANCE(&p->lock);
00881          } else {
00882             ast_queue_frame(p->owner, f);
00883             ast_mutex_unlock(&p->owner->lock);
00884             break;
00885          }
00886       } else
00887          break;
00888    }
00889 #ifdef HAVE_PRI
00890    if (pri)
00891       ast_mutex_lock(&pri->lock);
00892 #endif      
00893 }

static int zap_restart ( void   )  [static]

Definition at line 11171 of file chan_zap.c.

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

Referenced by action_zaprestart(), and zap_restart_cmd().

11172 {
11173    if (option_verbose > 0)
11174       ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
11175    while (iflist) {
11176       if (option_debug)
11177          ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
11178       /* Also updates iflist: */
11179       destroy_channel(NULL, iflist, 1);
11180    }
11181    if (option_debug)
11182       ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
11183    if (setup_zap(0) != 0) {
11184       ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
11185       return 1;
11186    }
11187    return 0;
11188 }

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

Definition at line 11190 of file chan_zap.c.

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

11191 {
11192    if (argc != 2) {
11193       return RESULT_SHOWUSAGE;
11194    }
11195 
11196    if (zap_restart() != 0)
11197       return RESULT_FAILURE;
11198    return RESULT_SUCCESS;
11199 }

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

Definition at line 11272 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, LOG_WARNING, zt_pvt::master, MAX_SLAVES, 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_THREEWAY, zt_pvt::subs, and zt_subchannel::zfd.

11273 {
11274    int channel;
11275    struct zt_pvt *tmp = NULL;
11276    ZT_CONFINFO ci;
11277    ZT_PARAMS ps;
11278    int x;
11279    ast_mutex_t *lock;
11280    struct zt_pvt *start;
11281 #ifdef HAVE_PRI
11282    char *c;
11283    int trunkgroup;
11284    struct zt_pri *pri=NULL;
11285 #endif
11286 
11287    lock = &iflock;
11288    start = iflist;
11289 
11290    if (argc != 4)
11291       return RESULT_SHOWUSAGE;
11292 #ifdef HAVE_PRI
11293    if ((c = strchr(argv[3], ':'))) {
11294       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
11295          return RESULT_SHOWUSAGE;
11296       if ((trunkgroup < 1) || (channel < 1))
11297          return RESULT_SHOWUSAGE;
11298       for (x = 0; x < NUM_SPANS; x++) {
11299          if (pris[x].trunkgroup == trunkgroup) {
11300             pri = pris + x;
11301             break;
11302          }
11303       }
11304       if (pri) {
11305          start = pri->crvs;
11306          lock = &pri->lock;
11307       } else {
11308          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
11309          return RESULT_FAILURE;
11310       }
11311    } else
11312 #endif
11313       channel = atoi(argv[3]);
11314 
11315    ast_mutex_lock(lock);
11316    tmp = start;
11317    while (tmp) {
11318       if (tmp->channel == channel) {
11319 #ifdef HAVE_PRI
11320          if (pri) 
11321             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
11322          else
11323 #endif         
11324          ast_cli(fd, "Channel: %d\n", tmp->channel);
11325          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
11326          ast_cli(fd, "Span: %d\n", tmp->span);
11327          ast_cli(fd, "Extension: %s\n", tmp->exten);
11328          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
11329          ast_cli(fd, "Context: %s\n", tmp->context);
11330          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
11331          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
11332          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
11333          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
11334          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
11335          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
11336          ast_cli(fd, "Radio: %d\n", tmp->radio);
11337          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
11338          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)" : "");
11339          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)" : "");
11340          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)" : "");
11341          ast_cli(fd, "Confno: %d\n", tmp->confno);
11342          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
11343          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
11344          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
11345          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
11346          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
11347          ast_cli(fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
11348          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
11349          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
11350          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
11351          if (tmp->master)
11352             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
11353          for (x = 0; x < MAX_SLAVES; x++) {
11354             if (tmp->slaves[x])
11355                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
11356          }
11357 #ifdef HAVE_PRI
11358          if (tmp->pri) {
11359             ast_cli(fd, "PRI Flags: ");
11360             if (tmp->resetting)
11361                ast_cli(fd, "Resetting ");
11362             if (tmp->call)
11363                ast_cli(fd, "Call ");
11364             if (tmp->bearer)
11365                ast_cli(fd, "Bearer ");
11366             ast_cli(fd, "\n");
11367             if (tmp->logicalspan) 
11368                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
11369             else
11370                ast_cli(fd, "PRI Logical Span: Implicit\n");
11371          }
11372             
11373 #endif
11374          memset(&ci, 0, sizeof(ci));
11375          ps.channo = tmp->channel;
11376          if (tmp->subs[SUB_REAL].zfd > -1) {
11377             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
11378                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
11379             }
11380 #ifdef ZT_GETCONFMUTE
11381             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) {
11382                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
11383             }
11384 #endif
11385             if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
11386                ast_log(LOG_WARNING, "Failed to get parameters on channel %d\n", tmp->channel);
11387             } else {
11388                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
11389             }
11390          }
11391          ast_mutex_unlock(lock);
11392          return RESULT_SUCCESS;
11393       }
11394       tmp = tmp->next;
11395    }
11396    
11397    ast_cli(fd, "Unable to find given channel %d\n", channel);
11398    ast_mutex_unlock(lock);
11399    return RESULT_FAILURE;
11400 }

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

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

11212 {
11213 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
11214 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
11215    struct zt_pvt *tmp = NULL;
11216    char tmps[20] = "";
11217    ast_mutex_t *lock;
11218    struct zt_pvt *start;
11219 #ifdef HAVE_PRI
11220    int trunkgroup;
11221    struct zt_pri *pri = NULL;
11222    int x;
11223 #endif
11224 
11225    lock = &iflock;
11226    start = iflist;
11227 
11228 #ifdef HAVE_PRI
11229    if (argc == 4) {
11230       if ((trunkgroup = atoi(argv[3])) < 1)
11231          return RESULT_SHOWUSAGE;
11232       for (x = 0; x < NUM_SPANS; x++) {
11233          if (pris[x].trunkgroup == trunkgroup) {
11234             pri = pris + x;
11235             break;
11236          }
11237       }
11238       if (pri) {
11239          start = pri->crvs;
11240          lock = &pri->lock;
11241       } else {
11242          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
11243          return RESULT_FAILURE;
11244       }
11245    } else
11246 #endif
11247    if (argc != 3)
11248       return RESULT_SHOWUSAGE;
11249 
11250    ast_mutex_lock(lock);
11251 #ifdef HAVE_PRI
11252    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
11253 #else
11254    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
11255 #endif   
11256    
11257    tmp = start;
11258    while (tmp) {
11259       if (tmp->channel > 0) {
11260          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
11261       } else
11262          ast_copy_string(tmps, "pseudo", sizeof(tmps));
11263       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
11264       tmp = tmp->next;
11265    }
11266    ast_mutex_unlock(lock);
11267    return RESULT_SUCCESS;
11268 #undef FORMAT
11269 #undef FORMAT2
11270 }

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

Definition at line 11433 of file chan_zap.c.

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

11433                                                            {
11434    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
11435    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
11436 
11437    int span;
11438    int res;
11439    char alarms[50];
11440 
11441    int ctl;
11442    ZT_SPANINFO s;
11443 
11444    ctl = open("/dev/zap/ctl", O_RDWR);
11445    if (ctl < 0) {
11446       ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
11447       ast_cli(fd, "No Zaptel interface found.\n");
11448       return RESULT_FAILURE;
11449    }
11450    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
11451 
11452    for (span = 1; span < ZT_MAX_SPANS; ++span) {
11453       s.spanno = span;
11454       res = ioctl(ctl, ZT_SPANSTAT, &s);
11455       if (res) {
11456          continue;
11457       }
11458       alarms[0] = '\0';
11459       if (s.alarms > 0) {
11460          if (s.alarms & ZT_ALARM_BLUE)
11461             strcat(alarms, "BLU/");
11462          if (s.alarms & ZT_ALARM_YELLOW)
11463             strcat(alarms, "YEL/");
11464          if (s.alarms & ZT_ALARM_RED)
11465             strcat(alarms, "RED/");
11466          if (s.alarms & ZT_ALARM_LOOPBACK)
11467             strcat(alarms, "LB/");
11468          if (s.alarms & ZT_ALARM_RECOVER)
11469             strcat(alarms, "REC/");
11470          if (s.alarms & ZT_ALARM_NOTOPEN)
11471             strcat(alarms, "NOP/");
11472          if (!strlen(alarms))
11473             strcat(alarms, "UUU/");
11474          if (strlen(alarms)) {
11475             /* Strip trailing / */
11476             alarms[strlen(alarms) - 1] = '\0';
11477          }
11478       } else {
11479          if (s.numchans)
11480             strcpy(alarms, "OK");
11481          else
11482             strcpy(alarms, "UNCONFIGURED");
11483       }
11484 
11485       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
11486    }
11487    close(ctl);
11488 
11489    return RESULT_SUCCESS;
11490 #undef FORMAT
11491 #undef FORMAT2
11492 }

static char* zap_sig2str ( int  sig  )  [static]

Definition at line 1219 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_GSM, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

01220 {
01221    static char buf[256];
01222    switch (sig) {
01223    case SIG_EM:
01224       return "E & M Immediate";
01225    case SIG_EMWINK:
01226       return "E & M Wink";
01227    case SIG_EM_E1:
01228       return "E & M E1";
01229    case SIG_FEATD:
01230       return "Feature Group D (DTMF)";
01231    case SIG_FEATDMF:
01232       return "Feature Group D (MF)";
01233    case SIG_FEATDMF_TA:
01234       return "Feature Groud D (MF) Tandem Access";
01235    case SIG_FEATB:
01236       return "Feature Group B (MF)";
01237    case SIG_E911:
01238       return "E911 (MF)";
01239    case SIG_FGC_CAMA:
01240       return "FGC/CAMA (Dialpulse)";
01241    case SIG_FGC_CAMAMF:
01242       return "FGC/CAMA (MF)";
01243    case SIG_FXSLS:
01244       return "FXS Loopstart";
01245    case SIG_FXSGS:
01246       return "FXS Groundstart";
01247    case SIG_FXSKS:
01248       return "FXS Kewlstart";
01249    case SIG_FXOLS:
01250       return "FXO Loopstart";
01251    case SIG_FXOGS:
01252       return "FXO Groundstart";
01253    case SIG_FXOKS:
01254       return "FXO Kewlstart";
01255    case SIG_PRI:
01256       return "ISDN PRI";
01257    case SIG_SF:
01258       return "SF (Tone) Immediate";
01259    case SIG_SFWINK:
01260       return "SF (Tone) Wink";
01261    case SIG_SF_FEATD:
01262       return "SF (Tone) with Feature Group D (DTMF)";
01263    case SIG_SF_FEATDMF:
01264       return "SF (Tone) with Feature Group D (MF)";
01265    case SIG_SF_FEATB:
01266       return "SF (Tone) with Feature Group B (MF)";
01267    case SIG_GR303FXOKS:
01268       return "GR-303 with FXOKS";
01269    case SIG_GR303FXSKS:
01270       return "GR-303 with FXSKS";
01271    case SIG_GSM:
01272       return "GSM";
01273    case 0:
01274       return "Pseudo";
01275    default:
01276       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01277       return buf;
01278    }
01279 }

static int zt_answer ( struct ast_channel ast  )  [static]

Definition at line 2875 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, enable_dtmf_detect(), 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_GSM, 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().

02876 {
02877    struct zt_pvt *p = ast->tech_pvt;
02878    int res = 0;
02879    int index;
02880    int oldstate = ast->_state;
02881    ast_setstate(ast, AST_STATE_UP);
02882    ast_mutex_lock(&p->lock);
02883    index = zt_get_index(ast, p, 0);
02884    if (index < 0)
02885       index = SUB_REAL;
02886    /* nothing to do if a radio channel */
02887    if ((p->radio || (p->oprmode < 0))) {
02888       ast_mutex_unlock(&p->lock);
02889       return 0;
02890    }
02891    switch (p->sig) {
02892    case SIG_FXSLS:
02893    case SIG_FXSGS:
02894    case SIG_FXSKS:
02895       p->ringt = 0;
02896       /* Fall through */
02897    case SIG_EM:
02898    case SIG_EM_E1:
02899    case SIG_EMWINK:
02900    case SIG_FEATD:
02901    case SIG_FEATDMF:
02902    case SIG_FEATDMF_TA:
02903    case SIG_E911:
02904    case SIG_FGC_CAMA:
02905    case SIG_FGC_CAMAMF:
02906    case SIG_FEATB:
02907    case SIG_SF:
02908    case SIG_SFWINK:
02909    case SIG_SF_FEATD:
02910    case SIG_SF_FEATDMF:
02911    case SIG_SF_FEATB:
02912    case SIG_FXOLS:
02913    case SIG_FXOGS:
02914    case SIG_FXOKS:
02915       /* Pick up the line */
02916       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
02917       if (p->hanguponpolarityswitch) {
02918          gettimeofday(&p->polaritydelaytv, NULL);
02919       }
02920       res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
02921       tone_zone_play_tone(p->subs[index].zfd, -1);
02922       p->dialing = 0;
02923       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
02924          if (oldstate == AST_STATE_RINGING) {
02925             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
02926             tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, -1);
02927             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02928             p->owner = p->subs[SUB_REAL].owner;
02929          }
02930       }
02931       if (p->sig & __ZT_SIG_FXS) {
02932          zt_enable_ec(p);
02933          zt_train_ec(p);
02934       }
02935       break;
02936 #ifdef HAVE_PRI
02937    case SIG_PRI:
02938       /* Send a pri acknowledge */
02939       if (!pri_grab(p, p->pri)) {
02940          p->proceeding = 1;
02941          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
02942          pri_rel(p->pri);
02943          /* stop ignoring inband dtmf */
02944          enable_dtmf_detect(p);
02945       } else {
02946          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02947          res = -1;
02948       }
02949       /* the audio path is complete now, train the echo canceler */
02950       zt_train_ec(p);
02951       break;
02952 #endif
02953 #ifdef HAVE_GSMAT
02954    case SIG_GSM:
02955       if (p->gsm.modul) {
02956           gsm_answer(p->gsm.modul);
02957       }
02958       break;
02959 #endif
02960    case 0:
02961       ast_mutex_unlock(&p->lock);
02962       return 0;
02963    default:
02964       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
02965       res = -1;
02966    }
02967    ast_mutex_unlock(&p->lock);
02968    return res;
02969 }

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

References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verbose(), ast_waitfor_n(), ast_write(), zt_pvt::channel, DEADLOCK_AVOIDANCE, disable_dtmf_detect(), zt_pvt::echocanbridged, enable_dtmf_detect(), ast_channel::fds, ast_frame::frametype, zt_pvt::inconference, zt_subchannel::inthreeway, zt_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, 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().

03294 {
03295    struct ast_channel *who;
03296    struct zt_pvt *p0, *p1, *op0, *op1;
03297    struct zt_pvt *master = NULL, *slave = NULL;
03298    struct ast_frame *f;
03299    int inconf = 0;
03300    int nothingok = 1;
03301    int ofd0, ofd1;
03302    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03303    int os0 = -1, os1 = -1;
03304    int priority = 0;
03305    struct ast_channel *oc0, *oc1;
03306    enum ast_bridge_result res;
03307 
03308 #ifdef PRI_2BCT
03309    int triedtopribridge = 0;
03310    q931_call *q931c0 = NULL, *q931c1 = NULL;
03311 #endif
03312 
03313    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
03314       There is code below to handle it properly until DTMF is actually seen,
03315       but due to currently unresolved issues it's ignored...
03316    */
03317 
03318    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03319       return AST_BRIDGE_FAILED_NOWARN;
03320 
03321    ast_mutex_lock(&c0->lock);
03322    while (ast_mutex_trylock(&c1->lock)) {
03323       DEADLOCK_AVOIDANCE(&c0->lock);
03324    }
03325 
03326    p0 = c0->tech_pvt;
03327    p1 = c1->tech_pvt;
03328    /* cant do pseudo-channels here */
03329    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03330       ast_mutex_unlock(&c0->lock);
03331       ast_mutex_unlock(&c1->lock);
03332       return AST_BRIDGE_FAILED_NOWARN;
03333    }
03334 
03335    oi0 = zt_get_index(c0, p0, 0);
03336    oi1 = zt_get_index(c1, p1, 0);
03337    if ((oi0 < 0) || (oi1 < 0)) {
03338       ast_mutex_unlock(&c0->lock);
03339       ast_mutex_unlock(&c1->lock);
03340       return AST_BRIDGE_FAILED;
03341    }
03342 
03343    op0 = p0 = c0->tech_pvt;
03344    op1 = p1 = c1->tech_pvt;
03345    ofd0 = c0->fds[0];
03346    ofd1 = c1->fds[0];
03347    oc0 = p0->owner;
03348    oc1 = p1->owner;
03349 
03350    if (ast_mutex_trylock(&p0->lock)) {
03351       /* Don't block, due to potential for deadlock */
03352       ast_mutex_unlock(&c0->lock);
03353       ast_mutex_unlock(&c1->lock);
03354       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03355       return AST_BRIDGE_RETRY;
03356    }
03357    if (ast_mutex_trylock(&p1->lock)) {
03358       /* Don't block, due to potential for deadlock */
03359       ast_mutex_unlock(&p0->lock);
03360       ast_mutex_unlock(&c0->lock);
03361       ast_mutex_unlock(&c1->lock);
03362       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03363       return AST_BRIDGE_RETRY;
03364    }
03365 
03366    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03367       if (p0->owner && p1->owner) {
03368          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
03369          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03370             master = p0;
03371             slave = p1;
03372             inconf = 1;
03373          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03374             master = p1;
03375             slave = p0;
03376             inconf = 1;
03377          } else {
03378             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
03379             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03380                p0->channel,
03381                oi0, (p0->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
03382                p0->subs[SUB_REAL].inthreeway, p0->channel,
03383                oi0, (p1->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
03384                p1->subs[SUB_REAL].inthreeway);
03385          }
03386          nothingok = 0;
03387       }
03388    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03389       if (p1->subs[SUB_THREEWAY].inthreeway) {
03390          master = p1;
03391          slave = p0;
03392          nothingok = 0;
03393       }
03394    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03395       if (p0->subs[SUB_THREEWAY].inthreeway) {
03396          master = p0;
03397          slave = p1;
03398          nothingok = 0;
03399       }
03400    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03401       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
03402          don't put us in anything */
03403       if (p1->subs[SUB_CALLWAIT].inthreeway) {
03404          master = p1;
03405          slave = p0;
03406          nothingok = 0;
03407       }
03408    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03409       /* Same as previous */
03410       if (p0->subs[SUB_CALLWAIT].inthreeway) {
03411          master = p0;
03412          slave = p1;
03413          nothingok = 0;
03414       }
03415    }
03416    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03417       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03418    if (master && slave) {
03419       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
03420          in an active threeway call with a channel that is ringing, we should
03421          indicate ringing. */
03422       if ((oi1 == SUB_THREEWAY) && 
03423           p1->subs[SUB_THREEWAY].inthreeway && 
03424           p1->subs[SUB_REAL].owner && 
03425           p1->subs[SUB_REAL].inthreeway && 
03426           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03427          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03428          tone_zone_play_tone(p0->subs[oi0].zfd, ZT_TONE_RINGTONE);
03429          os1 = p1->subs[SUB_REAL].owner->_state;
03430       } else {
03431          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03432          tone_zone_play_tone(p0->subs[oi0].zfd, -1);
03433       }
03434       if ((oi0 == SUB_THREEWAY) && 
03435           p0->subs[SUB_THREEWAY].inthreeway && 
03436           p0->subs[SUB_REAL].owner && 
03437           p0->subs[SUB_REAL].inthreeway && 
03438           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03439          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03440          tone_zone_play_tone(p1->subs[oi1].zfd, ZT_TONE_RINGTONE);
03441          os0 = p0->subs[SUB_REAL].owner->_state;
03442       } else {
03443          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03444          tone_zone_play_tone(p1->subs[oi0].zfd, -1);
03445       }
03446       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03447          if (!p0->echocanbridged || !p1->echocanbridged) {
03448             /* Disable echo cancellation if appropriate */
03449             zt_disable_ec(p0);
03450             zt_disable_ec(p1);
03451          }
03452       }
03453       zt_link(slave, master);
03454       master->inconference = inconf;
03455    } else if (!nothingok)
03456       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03457 
03458    update_conf(p0);
03459    update_conf(p1);
03460    t0 = p0->subs[SUB_REAL].inthreeway;
03461    t1 = p1->subs[SUB_REAL].inthreeway;
03462 
03463    ast_mutex_unlock(&p0->lock);
03464    ast_mutex_unlock(&p1->lock);
03465 
03466    ast_mutex_unlock(&c0->lock);
03467    ast_mutex_unlock(&c1->lock);
03468 
03469    /* Native bridge failed */
03470    if ((!master || !slave) && !nothingok) {
03471       zt_enable_ec(p0);
03472       zt_enable_ec(p1);
03473       return AST_BRIDGE_FAILED;
03474    }
03475    
03476    if (option_verbose > 2) 
03477       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03478 
03479    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03480       disable_dtmf_detect(op0);
03481 
03482    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03483       disable_dtmf_detect(op1);
03484 
03485    for (;;) {
03486       struct ast_channel *c0_priority[2] = {c0, c1};
03487       struct ast_channel *c1_priority[2] = {c1, c0};
03488 
03489       /* Here's our main loop...  Start by locking things, looking for private parts, 
03490          and then balking if anything is wrong */
03491       ast_mutex_lock(&c0->lock);
03492       while (ast_mutex_trylock(&c1->lock)) {
03493          DEADLOCK_AVOIDANCE(&c0->lock);
03494       }
03495 
03496       p0 = c0->tech_pvt;
03497       p1 = c1->tech_pvt;
03498 
03499       if (op0 == p0)
03500          i0 = zt_get_index(c0, p0, 1);
03501       if (op1 == p1)
03502          i1 = zt_get_index(c1, p1, 1);
03503       ast_mutex_unlock(&c0->lock);
03504       ast_mutex_unlock(&c1->lock);
03505 
03506       if (!timeoutms || 
03507           (op0 != p0) ||
03508           (op1 != p1) || 
03509           (ofd0 != c0->fds[0]) || 
03510           (ofd1 != c1->fds[0]) ||
03511           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
03512           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
03513           (oc0 != p0->owner) || 
03514           (oc1 != p1->owner) ||
03515           (t0 != p0->subs[SUB_REAL].inthreeway) ||
03516           (t1 != p1->subs[SUB_REAL].inthreeway) ||
03517           (oi0 != i0) ||
03518           (oi1 != i1)) {
03519          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03520             op0->channel, oi0, op1->channel, oi1);
03521          res = AST_BRIDGE_RETRY;
03522          goto return_from_bridge;
03523       }
03524 
03525 #ifdef PRI_2BCT
03526       q931c0 = p0->call;
03527       q931c1 = p1->call;
03528       if (p0->transfer && p1->transfer 
03529           && q931c0 && q931c1 
03530           && !triedtopribridge) {
03531          pri_channel_bridge(q931c0, q931c1);
03532          triedtopribridge = 1;
03533       }
03534 #endif
03535 
03536       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03537       if (!who) {
03538          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03539          continue;
03540       }
03541       f = ast_read(who);
03542       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03543          *fo = f;
03544          *rc = who;
03545          res = AST_BRIDGE_COMPLETE;
03546          goto return_from_bridge;
03547       }
03548       if (f->frametype == AST_FRAME_DTMF) {
03549          if ((who == c0) && p0->pulsedial) {
03550             ast_write(c1, f);
03551          } else if ((who == c1) && p1->pulsedial) {
03552             ast_write(c0, f);
03553          } else {
03554             *fo = f;
03555             *rc = who;
03556             res = AST_BRIDGE_COMPLETE;
03557             goto return_from_bridge;
03558          }
03559       }
03560       ast_frfree(f);
03561       
03562       /* Swap who gets priority */
03563       priority = !priority;
03564    }
03565 
03566 return_from_bridge:
03567    if (op0 == p0)
03568       zt_enable_ec(p0);
03569 
03570    if (op1 == p1)
03571       zt_enable_ec(p1);
03572 
03573    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03574       enable_dtmf_detect(op0);
03575 
03576    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03577       enable_dtmf_detect(op1);
03578 
03579    zt_unlink(slave, master, 1);
03580 
03581    return res;
03582 }

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

Definition at line 1835 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, disable_dtmf_detect(), zt_pvt::distinctivering, zt_pvt::dnid, zt_pvt::dop, zt_pvt::echobreak, zt_pvt::echorest, zt_pvt::echotraining, errno, zt_pvt::finaldial, free, zt_pvt::hidecallerid, zt_pvt::hidecalleridname, IS_DIGITAL, zt_pvt::lastcid_name, zt_pvt::lastcid_num, zt_pvt::law, zt_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_channel::lowlayercompat, 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_GSM, 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().

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

static int zt_callwait ( struct ast_channel ast  )  [static]

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

01808 {
01809    struct zt_pvt *p = ast->tech_pvt;
01810    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01811    if (p->cidspill) {
01812       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01813       free(p->cidspill);
01814    }
01815    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01816       return -1;
01817    save_conference(p);
01818    /* Silence */
01819    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01820    if (!p->callwaitrings && p->callwaitingcallerid) {
01821       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01822       p->callwaitcas = 1;
01823       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01824    } else {
01825       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01826       p->callwaitcas = 0;
01827       p->cidlen = 2400 + READ_SIZE * 4;
01828    }
01829    p->cidpos = 0;
01830    send_callerid(p);
01831    
01832    return 0;
01833 }

static struct zt_chan_conf zt_chan_conf_default ( void   )  [static, read]

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

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

00643                                                       {
00644    /* recall that if a field is not included here it is initialized
00645     * to 0 or equivalent
00646     */
00647    struct zt_chan_conf conf = {
00648 #ifdef HAVE_PRI
00649       .pri = {
00650          .nsf = PRI_NSF_NONE,
00651          .switchtype = PRI_SWITCH_NI2,
00652          .dialplan = PRI_NATIONAL_ISDN + 1,
00653          .localdialplan = PRI_NATIONAL_ISDN + 1,
00654          .nodetype = PRI_CPE,
00655 
00656          .minunused = 2,
00657          .idleext = "",
00658          .idledial = "",
00659          .nocid = "No CID available",
00660          .withheldcid = "CID withheld",
00661          .internationalprefix = "",
00662          .nationalprefix = "",
00663          .localprefix = "",
00664          .privateprefix = "",
00665          .unknownprefix = "",
00666          .usercid = 0,
00667 
00668          .resetinterval = 3600
00669       },
00670 #endif
00671       .chan = {
00672          .context = "default",
00673          .cid_num = "",
00674          .cid_name = "",
00675          .mohinterpret = "default",
00676          .mohsuggest = "",
00677          .transfertobusy = 1,
00678          .priindication_oob = 0,
00679          .pritransfer = 0,
00680 
00681          .cid_signalling = CID_SIG_BELL,
00682          .cid_start = CID_START_RING,
00683          .zaptrcallerid = 0,
00684          .use_callerid = 1,
00685          .sig = -1,
00686          .outsigmod = -1,
00687 
00688          .tonezone = -1,
00689 
00690          .echocancel = 1,
00691 
00692          .busycount = 3,
00693 
00694          .accountcode = "",
00695 
00696          .mailbox = "",
00697 
00698 
00699          .polarityonanswerdelay = 600,
00700 
00701          .sendcalleridafter = DEFAULT_CIDRINGS
00702       },
00703       .timing = {
00704          .prewinktime = -1,
00705          .preflashtime = -1,
00706          .winktime = -1,
00707          .flashtime = -1,
00708          .starttime = -1,
00709          .rxwinktime = -1,
00710          .rxflashtime = -1,
00711          .debouncetime = -1
00712       },
00713       .smdi_port = "/dev/ttyS0",
00714    };
00715 
00716    return conf;
00717 }

static void zt_close ( int  fd  )  [static]

Definition at line 972 of file chan_zap.c.

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

00973 {
00974    if (fd > 0)
00975       close(fd);
00976 }

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

Definition at line 1690 of file chan_zap.c.

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

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

01691 {
01692    int x, y, res;
01693    x = muted;
01694    if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
01695       y = 1;
01696       res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
01697       if (res)
01698          ast_log(LOG_WARNING, "Unable to set audio mode on '%d'\n", p->channel);
01699    }
01700    res = ioctl(p->subs[SUB_REAL].zfd, ZT_CONFMUTE, &x);
01701    if (res < 0)
01702       ast_log(LOG_WARNING, "zt confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01703    return res;
01704 }

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

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

01060 {
01061    struct zt_pvt *pvt;
01062    int index;
01063    int dtmf = -1;
01064    
01065    pvt = chan->tech_pvt;
01066 
01067    ast_mutex_lock(&pvt->lock);
01068 
01069    index = zt_get_index(chan, pvt, 0);
01070 
01071    if ((index != SUB_REAL) || !pvt->owner)
01072       goto out;
01073 
01074 #ifdef HAVE_PRI
01075    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01076       if (pvt->setup_ack) {
01077          if (!pri_grab(pvt, pvt->pri)) {
01078             pri_information(pvt->pri->pri, pvt->call, digit);
01079             pri_rel(pvt->pri);
01080          } else
01081             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01082       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01083          int res;
01084          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01085          res = strlen(pvt->dialdest);
01086          pvt->dialdest[res++] = digit;
01087          pvt->dialdest[res] = '\0';
01088       }
01089       goto out;
01090    }
01091 #endif
01092    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01093       goto out;
01094 
01095    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &dtmf)) {
01096       int res;
01097       ZT_DIAL_OPERATION zo = {
01098          .op = ZT_DIAL_OP_APPEND,
01099          .dialstr[0] = 'T',
01100          .dialstr[1] = digit,
01101          .dialstr[2] = 0,
01102       };
01103       if ((res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_DIAL, &zo)))
01104          ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
01105       else
01106          pvt->dialing = 1;
01107    } else {
01108       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01109       pvt->dialing = 1;
01110       pvt->begindigit = digit;
01111    }
01112 
01113 out:
01114    ast_mutex_unlock(&pvt->lock);
01115 
01116    return 0;
01117 }

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

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

01120 {
01121    struct zt_pvt *pvt;
01122    int res = 0;
01123    int index;
01124    int x;
01125    
01126    pvt = chan->tech_pvt;
01127 
01128    ast_mutex_lock(&pvt->lock);
01129    
01130    index = zt_get_index(chan, pvt, 0);
01131 
01132    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01133       goto out;
01134 
01135 #ifdef HAVE_PRI
01136    /* This means that the digit was already sent via PRI signalling */
01137    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01138       goto out;
01139 #endif
01140 
01141    if (pvt->begindigit) {
01142       x = -1;
01143       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01144       res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &x);
01145       pvt->dialing = 0;
01146       pvt->begindigit = 0;
01147    }
01148 
01149 out:
01150    ast_mutex_unlock(&pvt->lock);
01151 
01152    return res;
01153 }

static void zt_disable_ec ( struct zt_pvt p  )  [static]

Definition at line 1522 of file chan_zap.c.

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

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

01523 {
01524    int x;
01525    int res;
01526    if (p->echocancel) {
01527       x = 0;
01528       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01529       if (res)
01530          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
01531       else if (option_debug)
01532          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01533    }
01534    p->echocanon = 0;
01535 }

static void zt_enable_ec ( struct zt_pvt p  )  [static]

Definition at line 1468 of file chan_zap.c.

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

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

01469 {
01470    int x;
01471    int res;
01472    if (!p)
01473       return;
01474    if (p->faxhandled)  {
01475       ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
01476       return;
01477    }
01478    if (p->echocanon) {
01479       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01480       return;
01481    }
01482    if (p->digital) {
01483       ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
01484       return;
01485    }
01486    if (p->echocancel) {
01487       if (p->sig == SIG_PRI) {
01488          x = 1;
01489          res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x);
01490          if (res)
01491             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01492       }
01493       x = p->echocancel;
01494       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01495       if (res) 
01496          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01497       else {
01498          p->echocanon = 1;
01499          if (option_debug)
01500             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01501       }
01502    } else if (option_debug)
01503       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01504 }

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

Definition at line 4776 of file chan_zap.c.

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

04777 {
04778    struct zt_pvt *p = ast->tech_pvt;
04779    struct ast_frame *f;
04780    ast_mutex_lock(&p->lock);
04781    f = __zt_exception(ast);
04782    ast_mutex_unlock(&p->lock);
04783    return f;
04784 }

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

Definition at line 3584 of file chan_zap.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, zt_pvt::channel, zt_pvt::lock, LOG_DEBUG, LOG_ERROR, zt_subchannel::owner, zt_pvt::owner, zt_pvt::subs, ast_channel::tech_pvt, update_conf(), zt_indicate(), and zt_unlink().

03585 {
03586    struct zt_pvt *p = newchan->tech_pvt;
03587    int x;
03588    if (newchan && newchan->tech_pvt) {
03589        p = newchan->tech_pvt;
03590    }
03591    if (!p) {
03592        if (newchan) {
03593       ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
03594        }
03595        return 0;
03596    }
03597    ast_mutex_lock(&p->lock);
03598    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03599    if (p->owner == oldchan) {
03600       p->owner = newchan;
03601    }
03602    for (x = 0; x < 3; x++)
03603       if (p->subs[x].owner == oldchan) {
03604          if (!x)
03605             zt_unlink(NULL, p, 0);
03606          p->subs[x].owner = newchan;
03607       }
03608    if (newchan->_state == AST_STATE_RINGING) 
03609       zt_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03610    update_conf(p);
03611    ast_mutex_unlock(&p->lock);
03612    return 0;
03613 }

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

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

03157 {
03158    struct zt_pvt *p = chan->tech_pvt;
03159    
03160    if (!strcasecmp(data, "rxgain")) {
03161       ast_mutex_lock(&p->lock);
03162       snprintf(buf, len, "%f", p->rxgain);
03163       ast_mutex_unlock(&p->lock);   
03164    } else if (!strcasecmp(data, "txgain")) {
03165       ast_mutex_lock(&p->lock);
03166       snprintf(buf, len, "%f", p->txgain);
03167       ast_mutex_unlock(&p->lock);   
03168    } else {
03169       ast_copy_string(buf, "", len);
03170    }
03171    return 0;
03172 }

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

Avoid the silly zt_getevent which ignores a bunch of events.

Definition at line 263 of file chan_zap.c.

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

00264 {
00265    int j;
00266    if (ioctl(fd, ZT_GETEVENT, &j) == -1)
00267       return -1;
00268    return j;
00269 }

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

Definition at line 821 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_setoption(), zt_tdd_sendtext(), and zt_write().

00822 {
00823    int res;
00824    if (p->subs[0].owner == ast)
00825       res = 0;
00826    else if (p->subs[1].owner == ast)
00827       res = 1;
00828    else if (p->subs[2].owner == ast)
00829       res = 2;
00830    else {
00831       res = -1;
00832       if (!nullok)
00833          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
00834    }
00835    return res;
00836 }

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

Definition at line 3761 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, zt_pvt::faxhandled, ast_frame::frametype, free, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, option_debug, option_verbose, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, zt_pvt::subs, ast_channel::tech_pvt, VERBOSE_PREFIX_3, and zt_confmute().

Referenced by zt_handle_event(), and zt_read().

03762 {
03763    struct zt_pvt *p = ast->tech_pvt;
03764    struct ast_frame *f = *dest;
03765 
03766    if (option_debug)
03767       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
03768 
03769    if (p->confirmanswer) {
03770       if (option_debug)
03771          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
03772       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
03773          of a DTMF digit */
03774       p->subs[index].f.frametype = AST_FRAME_CONTROL;
03775       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03776       *dest = &p->subs[index].f;
03777       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
03778       p->confirmanswer = 0;
03779    } else if (p->callwaitcas) {
03780       if ((f->subclass == 'A') || (f->subclass == 'D')) {
03781          if (option_debug)
03782             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
03783          if (p->cidspill)
03784             free(p->cidspill);
03785          send_cwcidspill(p);
03786       }
03787       if ((f->subclass != 'm') && (f->subclass != 'u')) 
03788          p->callwaitcas = 0;
03789       p->subs[index].f.frametype = AST_FRAME_NULL;
03790       p->subs[index].f.subclass = 0;
03791       *dest = &p->subs[index].f;
03792    } else if (f->subclass == 'f') {
03793       /* Fax tone -- Handle and return NULL */
03794       if ((p->callprogress & 0x6) && !p->faxhandled) {
03795          p->faxhandled++;
03796          if (strcmp(ast->exten, "fax")) {
03797             const char *target_context = S_OR(ast->macrocontext, ast->context);
03798 
03799             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
03800                if (option_verbose > 2)
03801                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
03802                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
03803                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
03804                if (ast_async_goto(ast, target_context, "fax", 1))
03805                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
03806             } else {
03807                 if (option_verbose > 2)
03808                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
03809             }
03810          } else if (option_debug)
03811             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
03812       } else if (option_debug)
03813             ast_log(LOG_DEBUG, "Fax already handled\n");
03814       zt_confmute(p, 0);
03815       p->subs[index].f.frametype = AST_FRAME_NULL;
03816       p->subs[index].f.subclass = 0;
03817       *dest = &p->subs[index].f;
03818    } else if (f->subclass == 'm') {
03819       /* Confmute request */
03820       zt_confmute(p, 1);
03821       p->subs[index].f.frametype = AST_FRAME_NULL;
03822       p->subs[index].f.subclass = 0;
03823       *dest = &p->subs[index].f;    
03824    } else if (f->subclass == 'u') {
03825       /* Unmute */
03826       zt_confmute(p, 0);
03827       p->subs[index].f.frametype = AST_FRAME_NULL;
03828       p->subs[index].f.subclass = 0;
03829       *dest = &p->subs[index].f;    
03830    } else
03831       zt_confmute(p, 0);
03832 }

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

Definition at line 3834 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::callprogress, zt_pvt::callwaitcas, zt_pvt::callwaitingrepeat, 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::cidcwexpire, zt_pvt::cidrings, zt_pvt::cidspill, zt_pvt::confirmanswer, ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, zt_pvt::dialdest, zt_pvt::dialednone, zt_pvt::dialing, zt_pvt::dop, zt_pvt::dsp, zt_pvt::echobreak, zt_pvt::echocanon, zt_pvt::echorest, zt_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, zt_subchannel::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, LOG_WARNING, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, zt_pvt::mohsuggest, zt_pvt::msgstate, zt_subchannel::needanswer, zt_subchannel::needflash, zt_subchannel::needhold, zt_subchannel::needringing, zt_subchannel::needunhold, ast_frame::offset, zt_pvt::onhooktime, zt_pvt::oprmode, zt_pvt::oprpeer, option_debug, option_verbose, zt_pvt::origcid_name, zt_pvt::origcid_num, zt_pvt::outgoing, zt_pvt::outsigmod, zt_pvt::overlapdial, zt_subchannel::owner, zt_pvt::owner, ast_channel::pbx, zt_pvt::polarity, POLARITY_IDLE, POLARITY_REV, zt_pvt::polaritydelaytv, zt_pvt::polarityonanswerdelay, zt_pvt::pulsedial, zt_pvt::radio, restore_conference(), ast_channel::rings, zt_pvt::ringt, zt_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), zt_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ast_frame::src, ss_thread(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, zt_pvt::subs, swap_subs(), ast_channel::tech_pvt, zt_pvt::threewaycalling, zt_pvt::transfer, zt_pvt::transfertobusy, unalloc_sub(), zt_pvt::unknown_alarm, update_conf(), VERBOSE_PREFIX_3, zt_pvt::whichwink, zt_pvt::zaptrcallerid, zt_subchannel::zfd, zt_confmute(), zt_disable_ec(), zt_enable_ec(), ZT_EVENT_DTMFDOWN, ZT_EVENT_DTMFUP, zt_get_event(), zt_get_index(), zt_handle_dtmfup(), zt_new(), zt_ring_phone(), zt_set_hook(), and zt_train_ec().

Referenced by __zt_exception().

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

static int zt_hangup ( struct ast_channel ast  )  [static]

Definition at line 2520 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_DIALING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, 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_subchannel::inthreeway, zt_subchannel::linear, zt_pvt::lock, LOG_DEBUG, LOG_ERROR, 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_GSM, 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().

02521 {
02522    int res;
02523    int index,x, law;
02524    /*static int restore_gains(struct zt_pvt *p);*/
02525    struct zt_pvt *p = ast->tech_pvt;
02526    struct zt_pvt *tmp = NULL;
02527    struct zt_pvt *prev = NULL;
02528    ZT_PARAMS par;
02529 
02530    if (option_debug)
02531       ast_log(LOG_DEBUG, "zt_hangup(%s)\n", ast->name);
02532    if (!ast->tech_pvt) {
02533       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02534       return 0;
02535    }
02536    
02537    ast_mutex_lock(&p->lock);
02538    
02539    index = zt_get_index(ast, p, 1);
02540 
02541    if (p->sig == SIG_PRI) {
02542       x = 1;
02543       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02544    }
02545 
02546    x = 0;
02547    zt_confmute(p, 0);
02548    restore_gains(p);
02549    if (p->origcid_num) {
02550       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02551       free(p->origcid_num);
02552       p->origcid_num = NULL;
02553    }  
02554    if (p->origcid_name) {
02555       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02556       free(p->origcid_name);
02557       p->origcid_name = NULL;
02558    }  
02559    if (p->dsp)
02560       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02561    if (p->exten)
02562       p->exten[0] = '\0';
02563 
02564    if (option_debug)
02565       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02566       p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
02567 
02568    if (index > -1) {
02569       /* Real channel, do some fixup */
02570       p->subs[index].owner = NULL;
02571       p->subs[index].needanswer = 0;
02572       p->subs[index].needflash = 0;
02573       p->subs[index].needringing = 0;
02574       p->subs[index].needbusy = 0;
02575       p->subs[index].needcongestion = 0;
02576       p->subs[index].linear = 0;
02577       p->subs[index].needcallerid = 0;
02578       p->polarity = POLARITY_IDLE;
02579       zt_setlinear(p->subs[index].zfd, 0);
02580       if (index == SUB_REAL) {
02581          if ((p->subs[SUB_CALLWAIT].zfd > -1) && (p->subs[SUB_THREEWAY].zfd > -1)) {
02582             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02583             if (p->subs[SUB_CALLWAIT].inthreeway) {
02584                /* We had flipped over to answer a callwait and now it's gone */
02585                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02586                /* Move to the call-wait, but un-own us until they flip back. */
02587                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02588                unalloc_sub(p, SUB_CALLWAIT);
02589                p->owner = NULL;
02590             } else {
02591                /* The three way hung up, but we still have a call wait */
02592                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
02593                swap_subs(p, SUB_THREEWAY, SUB_REAL);
02594                unalloc_sub(p, SUB_THREEWAY);
02595                if (p->subs[SUB_REAL].inthreeway) {
02596                   /* This was part of a three way call.  Immediately make way for
02597                      another call */
02598                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02599                   p->owner = p->subs[SUB_REAL].owner;
02600                } else {
02601                   /* This call hasn't been completed yet...  Set owner to NULL */
02602                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02603                   p->owner = NULL;
02604                }
02605                p->subs[SUB_REAL].inthreeway = 0;
02606             }
02607          } else if (p->subs[SUB_CALLWAIT].zfd > -1) {
02608             /* Move to the call-wait and switch back to them. */
02609             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02610             unalloc_sub(p, SUB_CALLWAIT);
02611             p->owner = p->subs[SUB_REAL].owner;
02612             if (p->owner->_state != AST_STATE_UP)
02613                p->subs[SUB_REAL].needanswer = 1;
02614             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02615                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02616          } else if (p->subs[SUB_THREEWAY].zfd > -1) {
02617             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02618             unalloc_sub(p, SUB_THREEWAY);
02619             if (p->subs[SUB_REAL].inthreeway) {
02620                /* This was part of a three way call.  Immediately make way for
02621                   another call */
02622                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02623                p->owner = p->subs[SUB_REAL].owner;
02624             } else {
02625                /* This call hasn't been completed yet...  Set owner to NULL */
02626                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02627                p->owner = NULL;
02628             }
02629             p->subs[SUB_REAL].inthreeway = 0;
02630          }
02631       } else if (index == SUB_CALLWAIT) {
02632          /* Ditch the holding callwait call, and immediately make it availabe */
02633          if (p->subs[SUB_CALLWAIT].inthreeway) {
02634             /* This is actually part of a three way, placed on hold.  Place the third part
02635                on music on hold now */
02636             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02637                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
02638                   S_OR(p->mohsuggest, NULL),
02639                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02640             }
02641             p->subs[SUB_THREEWAY].inthreeway = 0;
02642             /* Make it the call wait now */
02643             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02644             unalloc_sub(p, SUB_THREEWAY);
02645          } else
02646             unalloc_sub(p, SUB_CALLWAIT);
02647       } else if (index == SUB_THREEWAY) {
02648          if (p->subs[SUB_CALLWAIT].inthreeway) {
02649             /* The other party of the three way call is currently in a call-wait state.
02650                Start music on hold for them, and take the main guy out of the third call */
02651             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02652                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
02653                   S_OR(p->mohsuggest, NULL),
02654                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02655             }
02656             p->subs[SUB_CALLWAIT].inthreeway = 0;
02657          }
02658          p->subs[SUB_REAL].inthreeway = 0;
02659          /* If this was part of a three way call index, let us make
02660             another three way call */
02661          unalloc_sub(p, SUB_THREEWAY);
02662       } else {
02663          /* This wasn't any sort of call, but how are we an index? */
02664          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02665       }
02666    }
02667 
02668    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02669       int outgoing = p->outgoing;
02670       p->owner = NULL;
02671       p->ringt = 0;
02672       p->distinctivering = 0;
02673       p->confirmanswer = 0;
02674       p->cidrings = 1;
02675       p->outgoing = 0;
02676       p->digital = 0;
02677       p->faxhandled = 0;
02678       p->pulsedial = 0;
02679       p->onhooktime = time(NULL);
02680 #ifdef HAVE_PRI
02681       p->proceeding = 0;
02682       p->progress = 0;
02683       p->alerting = 0;
02684       p->setup_ack = 0;
02685 #endif      
02686       if (p->dsp) {
02687          ast_dsp_free(p->dsp);
02688          p->dsp = NULL;
02689       }
02690 
02691       law = ZT_LAW_DEFAULT;
02692       res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETLAW, &law);
02693       if (res < 0) 
02694          ast_log(LOG_WARNING, "Unable to set law on channel %d to default\n", p->channel);
02695       /* Perform low level hangup if no owner left */
02696 #ifdef HAVE_PRI
02697       if (p->pri) {
02698 #ifdef SUPPORT_USERUSER
02699          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02700 #endif
02701 
02702          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
02703          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02704             if (!pri_grab(p, p->pri)) {
02705                if (p->alreadyhungup) {
02706                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
02707 
02708 #ifdef SUPPORT_USERUSER
02709                   pri_call_set_useruser(p->call, useruser);
02710 #endif
02711 
02712                   pri_hangup(p->pri->pri, p->call, -1, -1);
02713                   p->call = NULL;
02714                   if (p->bearer) 
02715                      p->bearer->call = NULL;
02716                } else {
02717                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
02718                   int icause = ast->hangupcause ? ast->hangupcause : -1;
02719                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
02720 
02721 #ifdef SUPPORT_USERUSER
02722                   pri_call_set_useruser(p->call, useruser);
02723 #endif
02724 
02725                   p->alreadyhungup = 1;
02726                   if (p->bearer)
02727                      p->bearer->alreadyhungup = 1;
02728                   if (cause) {
02729                      if (atoi(cause))
02730                         icause = atoi(cause);
02731                   }
02732 
02733                   pri_hangup(p->pri->pri, p->call, icause, -1);
02734 
02735                   /* if we send a rel9999ease complete we wont ge no hangup event, so clear the call here */
02736                   if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
02737                       if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING) || (ast->_state == AST_STATE_RESERVED)) {
02738                      p->call = NULL;
02739                       } else {
02740                      ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
02741                      icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
02742                       }
02743                   }
02744 
02745                   if (p->pri->nodetype == BRI_NETWORK_PTMP) {
02746                       if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
02747                      if (outgoing) {
02748                          p->call = NULL;
02749                      }
02750                       }
02751                   }
02752 
02753 
02754                }
02755                if (res < 0) 
02756                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
02757                pri_rel(p->pri);        
02758             } else {
02759                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02760                res = -1;
02761             }
02762          } else {
02763             if (p->bearer)
02764                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02765             p->call = NULL;
02766             res = 0;
02767          }
02768       }
02769 #endif
02770 #ifdef HAVE_GSMAT
02771       if (p->gsm.modul) {
02772           if (!p->alreadyhungup)
02773          gsm_hangup(p->gsm.modul);
02774       }
02775 #endif
02776       if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_GSM))
02777          res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
02778       if (res < 0) {
02779          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02780       }
02781       switch (p->sig) {
02782       case SIG_FXOGS:
02783       case SIG_FXOLS:
02784       case SIG_FXOKS:
02785          res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
02786          if (!res) {
02787 #if 0
02788             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02789 #endif
02790             /* If they're off hook, try playing congestion */
02791             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02792                tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
02793             else
02794                tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
02795          }
02796          break;
02797       case SIG_FXSGS:
02798       case SIG_FXSLS:
02799       case SIG_FXSKS:
02800          /* Make sure we're not made available for at least two seconds assuming
02801             we were actually used for an inbound or outbound call. */
02802          if (ast->_state != AST_STATE_RESERVED) {
02803             time(&p->guardtime);
02804             p->guardtime += 2;
02805          }
02806          break;
02807       default:
02808          tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
02809       }
02810       if (p->cidspill)
02811          free(p->cidspill);
02812       if (p->sig)
02813          zt_disable_ec(p);
02814       x = 0;
02815       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02816       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02817       p->didtdd = 0;
02818       p->cidspill = NULL;
02819       p->callwaitcas = 0;
02820       p->callwaiting = p->permcallwaiting;
02821       p->hidecallerid = p->permhidecallerid;
02822       p->dialing = 0;
02823       p->rdnis[0] = '\0';
02824       update_conf(p);
02825       reset_conf(p);
02826       /* Restore data mode */
02827       if (p->sig == SIG_PRI) {
02828          x = 0;
02829          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02830       }
02831 #ifdef HAVE_PRI
02832       if (p->bearer) {
02833          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02834          /* Free up the bearer channel as well, and
02835             don't use its file descriptor anymore */
02836          update_conf(p->bearer);
02837          reset_conf(p->bearer);
02838          p->bearer->owner = NULL;
02839          p->bearer->realcall = NULL;
02840          p->bearer = NULL;
02841          p->subs[SUB_REAL].zfd = -1;
02842          p->pri = NULL;
02843       }
02844 #endif
02845       restart_monitor();
02846    }
02847 
02848    p->callwaitingrepeat = 0;
02849    p->cidcwexpire = 0;
02850    p->oprmode = 0;
02851    ast->tech_pvt = NULL;
02852    ast_mutex_unlock(&p->lock);
02853    ast_module_unref(ast_module_info->self);
02854    if (option_verbose > 2) 
02855       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02856 
02857    ast_mutex_lock(&iflock);
02858    tmp = iflist;
02859    prev = NULL;
02860    if (p->destroy) {
02861       while (tmp) {
02862          if (tmp == p) {
02863             destroy_channel(prev, tmp, 0);
02864             break;
02865          } else {
02866             prev = tmp;
02867             tmp = tmp->next;
02868          }
02869       }
02870    }
02871    ast_mutex_unlock(&iflock);
02872    return 0;
02873 }

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

Definition at line 5184 of file chan_zap.c.

References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, zt_pvt::digital, zt_pvt::dop, errno, func, ast_channel::hangupcause, ISTRUNK, zt_pvt::lock, LOG_DEBUG, LOG_WARNING, zt_pvt::mohinterpret, option_debug, zt_pvt::outgoing, zt_pvt::priindication_oob, zt_pvt::radio, zt_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, zt_pvt::span, SUB_REAL, zt_pvt::subs, ast_channel::tech_pvt, zt_subchannel::zfd, zt_get_index(), and zt_set_hook().

Referenced by zt_fixup().

05185 {
05186    struct zt_pvt *p = chan->tech_pvt;
05187    int res=-1;
05188    int index;
05189    int func = ZT_FLASH;
05190    ast_mutex_lock(&p->lock);
05191    index = zt_get_index(chan, p, 0);
05192    if (option_debug)
05193       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05194    if (index == SUB_REAL) {
05195       switch (condition) {
05196       case AST_CONTROL_BUSY:
05197 #ifdef HAVE_PRI
05198          if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
05199             chan->hangupcause = AST_CAUSE_USER_BUSY;
05200             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05201             res = 0;
05202          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05203             if (p->pri->pri) {      
05204                if (!pri_grab(p, p->pri)) {
05205                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05206                   pri_rel(p->pri);
05207                }
05208                else
05209                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05210             }
05211             p->progress = 1;
05212             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_BUSY);
05213          } else
05214 #endif
05215             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_BUSY);
05216          break;
05217       case AST_CONTROL_RINGING:
05218 #ifdef HAVE_PRI
05219          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05220             if (p->pri->pri) {      
05221                if (!pri_grab(p, p->pri)) {
05222                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05223                   pri_rel(p->pri);
05224                }
05225                else
05226                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05227             }
05228             p->alerting = 1;
05229          }
05230 #endif
05231          res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_RINGTONE);
05232          if (chan->_state != AST_STATE_UP) {
05233             if ((chan->_state != AST_STATE_RING) ||
05234                ((p->sig != SIG_FXSKS) &&
05235                 (p->sig != SIG_FXSLS) &&
05236                 (p->sig != SIG_FXSGS)))
05237                ast_setstate(chan, AST_STATE_RINGING);
05238          }
05239          break;
05240       case AST_CONTROL_PROCEEDING:
05241          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05242 #ifdef HAVE_PRI
05243          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05244             if (p->pri->pri) {      
05245                if (!pri_grab(p, p->pri)) {
05246                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05247                   pri_rel(p->pri);
05248                }
05249                else
05250                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05251             }
05252             p->proceeding = 1;
05253          }
05254 #endif
05255          /* don't continue in ast_indicate */
05256          res = 0;
05257          break;
05258       case AST_CONTROL_PROGRESS:
05259          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05260 #ifdef HAVE_PRI
05261          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
05262          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05263             if (p->pri->pri) {      
05264                if (!pri_grab(p, p->pri)) {
05265                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05266                   pri_rel(p->pri);
05267                }
05268                else
05269                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05270             }
05271             p->progress = 1;
05272          }
05273 #endif
05274          /* don't continue in ast_indicate */
05275          res = 0;
05276          break;
05277       case AST_CONTROL_CONGESTION:
05278          chan->hangupcause = AST_CAUSE_CONGESTION;
05279 #ifdef HAVE_PRI
05280          if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
05281             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05282             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05283             res = 0;
05284          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05285             if (p->pri) {     
05286                if (!pri_grab(p, p->pri)) {
05287                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05288                   pri_rel(p->pri);
05289                } else
05290                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05291             }
05292             p->progress = 1;
05293             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05294          } else
05295 #endif
05296             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05297          break;
05298       case AST_CONTROL_HOLD:
05299 #ifdef HAVE_PRI
05300          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05301             if (!pri_grab(p, p->pri)) {
05302                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05303                pri_rel(p->pri);
05304             } else
05305                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05306          } else
05307 #endif
05308             ast_moh_start(chan, data, p->mohinterpret);
05309          break;
05310       case AST_CONTROL_UNHOLD:
05311 #ifdef HAVE_PRI
05312          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05313             if (!pri_grab(p, p->pri)) {
05314                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05315                pri_rel(p->pri);
05316             } else
05317                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05318          } else
05319 #endif
05320             ast_moh_stop(chan);
05321          break;
05322       case AST_CONTROL_RADIO_KEY:
05323          if (p->radio) 
05324              res =  zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
05325          res = 0;
05326          break;
05327       case AST_CONTROL_RADIO_UNKEY:
05328          if (p->radio)
05329              res =  zt_set_hook(p->subs[index].zfd, ZT_RINGOFF);
05330          res = 0;
05331          break;
05332       case AST_CONTROL_FLASH:
05333          /* flash hookswitch */
05334          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05335             /* Clear out the dial buffer */
05336             p->dop.dialstr[0] = '\0';
05337             if ((ioctl(p->subs[SUB_REAL].zfd,ZT_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05338                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
05339                   chan->name, strerror(errno));
05340             } else
05341                res = 0;
05342          } else
05343             res = 0;
05344          break;
05345       case AST_CONTROL_SRCUPDATE:
05346          res = 0;
05347          break;
05348       case -1:
05349          res = tone_zone_play_tone(p->subs[index].zfd, -1);
05350          break;
05351       }
05352    } else
05353       res = 0;
05354    ast_mutex_unlock(&p->lock);
05355    return res;
05356 }

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

Definition at line 3231 of file chan_zap.c.

References ast_log(), zt_pvt::channel, LOG_DEBUG, LOG_WARNING, zt_pvt::master, MAX_SLAVES, and zt_pvt::slaves.

Referenced by zt_bridge().

03231                                                                  {
03232    int x;
03233    if (!slave || !master) {
03234       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03235       return;
03236    }
03237    for (x = 0; x < MAX_SLAVES; x++) {
03238       if (!master->slaves[x]) {
03239          master->slaves[x] = slave;
03240          break;
03241       }
03242    }
03243    if (x >= MAX_SLAVES) {
03244       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03245       master->slaves[MAX_SLAVES - 1] = slave;
03246    }
03247    if (slave->master) 
03248       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03249    slave->master = master;
03250    
03251    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03252 }

static struct ast_channel * zt_new ( struct zt_pvt i,
int  state,
int  startpbx,
int  index,
int  law,
int  transfercapability 
) [static, read]

> b2 can be freed now, it's been copied into the channel structure

Definition at line 5358 of file chan_zap.c.

References accountcode, zt_pvt::accountcode, zt_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, zt_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), zt_pvt::busy_quietlength, zt_pvt::busy_tonelength, zt_pvt::busycount, zt_pvt::busydetect, zt_pvt::call_forward, zt_pvt::callgroup, ast_channel::callgroup, zt_pvt::callingpres, zt_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, zt_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, zt_pvt::cid_name, zt_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, zt_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, zt_pvt::context, zt_pvt::digital, zt_pvt::dnid, zt_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, zt_pvt::dsp_features, DSP_PROGRESS_TALK, zt_pvt::dtmfrelax, ast_channel::exten, zt_pvt::exten, zt_pvt::fake_event, ast_channel::fds, free, global_jbconf, zt_pvt::hardwaredtmf, language, zt_pvt::language, zt_subchannel::linear, LOG_DEBUG, LOG_WARNING, 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, zt_subchannel::zfd, zt_confmute(), and zt_setlinear().

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

05359 {
05360    struct ast_channel *tmp;
05361    int deflaw;
05362    int res;
05363    int x,y;
05364    int features;
05365    char *b2 = NULL;
05366    ZT_PARAMS ps;
05367    if (i->subs[index].owner) {
05368       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05369       return NULL;
05370    }
05371    y = 1;
05372    do {
05373       if (b2)
05374          free(b2);
05375 #ifdef HAVE_PRI
05376       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05377          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05378       else
05379 #endif
05380       if (i->channel == CHAN_PSEUDO)
05381          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05382       else  
05383          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05384       for (x = 0; x < 3; x++) {
05385          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name))
05386             break;
05387       }
05388       y++;
05389    } while (x < 3);
05390    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "Zap/%s", b2);
05391    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
05392       free(b2);
05393    if (!tmp)
05394       return NULL;
05395    tmp->tech = &zap_tech;
05396    ps.channo = i->channel;
05397    res = ioctl(i->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps);
05398    if (res) {
05399       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW\n");
05400       ps.curlaw = ZT_LAW_MULAW;
05401    }
05402    if (ps.curlaw == ZT_LAW_ALAW)
05403       deflaw = AST_FORMAT_ALAW;
05404    else
05405       deflaw = AST_FORMAT_ULAW;
05406    if (law) {
05407       if (law == ZT_LAW_ALAW)
05408          deflaw = AST_FORMAT_ALAW;
05409       else
05410          deflaw = AST_FORMAT_ULAW;
05411    }
05412    tmp->fds[0] = i->subs[index].zfd;
05413    tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05414    /* Start out assuming ulaw since it's smaller :) */
05415    tmp->rawreadformat = deflaw;
05416    tmp->readformat = deflaw;
05417    tmp->rawwriteformat = deflaw;
05418    tmp->writeformat = deflaw;
05419    i->subs[index].linear = 0;
05420    zt_setlinear(i->subs[index].zfd, i->subs[index].linear);
05421    features = 0;
05422    if (index == SUB_REAL) {
05423       if (i->busydetect && CANBUSYDETECT(i))
05424          features |= DSP_FEATURE_BUSY_DETECT;
05425       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05426          features |= DSP_FEATURE_CALL_PROGRESS;
05427       if ((!i->outgoing && (i->callprogress & 4)) || 
05428           (i->outgoing && (i->callprogress & 2))) {
05429          features |= DSP_FEATURE_FAX_DETECT;
05430       }
05431 #ifdef ZT_TONEDETECT
05432       x = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
05433       if (ioctl(i->subs[index].zfd, ZT_TONEDETECT, &x)) {
05434 #endif      
05435          i->hardwaredtmf = 0;
05436          features |= DSP_FEATURE_DTMF_DETECT;
05437 #ifdef ZT_TONEDETECT
05438       } else if (NEED_MFDETECT(i)) {
05439          i->hardwaredtmf = 1;
05440          features |= DSP_FEATURE_DTMF_DETECT;
05441       }
05442 #endif
05443    }
05444    if (features) {
05445       if (i->dsp) {
05446          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05447       } else {
05448          if (i->channel != CHAN_PSEUDO)
05449             i->dsp = ast_dsp_new();
05450          else
05451             i->dsp = NULL;
05452          if (i->dsp) {
05453             i->dsp_features = features & ~DSP_PROGRESS_TALK;
05454 #ifdef HAVE_PRI
05455             /* We cannot do progress detection until receives PROGRESS message */
05456             if (i->outgoing && (i->sig == SIG_PRI)) {
05457                /* Remember requested DSP features, don't treat
05458                   talking as ANSWER */
05459                features = 0;
05460             }
05461 #endif
05462             ast_dsp_set_features(i->dsp, features);
05463             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05464             if (!ast_strlen_zero(progzone))
05465                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05466             if (i->busydetect && CANBUSYDETECT(i)) {
05467                ast_dsp_set_busy_count(i->dsp, i->busycount);
05468                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
05469             }
05470          }
05471       }
05472    }
05473       
05474    if (state == AST_STATE_RING)
05475       tmp->rings = 1;
05476    tmp->tech_pvt = i;
05477 #ifdef HAVE_PRI
05478    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
05479 #else
05480    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05481 #endif
05482       /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
05483       tmp->callgroup = i->callgroup;
05484       tmp->pickupgroup = i->pickupgroup;
05485    }
05486    if (!ast_strlen_zero(i->language))
05487       ast_string_field_set(tmp, language, i->language);
05488    if (!i->owner)
05489       i->owner = tmp;
05490    if (!ast_strlen_zero(i->accountcode))
05491       ast_string_field_set(tmp, accountcode, i->accountcode);
05492    if (i->amaflags)
05493       tmp->amaflags = i->amaflags;
05494    i->subs[index].owner = tmp;
05495    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05496    ast_string_field_set(tmp, call_forward, i->call_forward);
05497    /* If we've been told "no ADSI" then enforce it */
05498    if (!i->adsi)
05499       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05500    if (!ast_strlen_zero(i->exten))
05501       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05502    if (!ast_strlen_zero(i->rdnis))
05503       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05504    if (!ast_strlen_zero(i->dnid))
05505       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05506 
05507    /* Don't use ast_set_callerid() here because it will
05508     * generate a needless NewCallerID event */
05509 #ifdef PRI_ANI
05510    if (!ast_strlen_zero(i->cid_ani))
05511       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05512    else  
05513       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05514 #else
05515    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05516 #endif
05517    tmp->cid.cid_pres = i->callingpres;
05518    tmp->cid.cid_ton = i->cid_ton;
05519 #ifdef HAVE_PRI
05520    tmp->transfercapability = transfercapability;
05521    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05522    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05523       i->digital = 1;
05524    /* Assume calls are not idle calls unless we're told differently */
05525    i->isidlecall = 0;
05526    i->alreadyhungup = 0;
05527 #endif
05528    /* clear the fake event in case we posted one before we had ast_channel */
05529    i->fake_event = 0;
05530    /* Assure there is no confmute on this channel */
05531    zt_confmute(i, 0);
05532    /* Configure the new channel jb */
05533    ast_jb_configure(tmp, &global_jbconf);
05534    if (startpbx) {
05535       if (ast_pbx_start(tmp)) {
05536          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05537          ast_hangup(tmp);
05538          i->owner = NULL;
05539          return NULL;
05540       }
05541    }
05542 
05543    ast_module_ref(ast_module_info->self);
05544    
05545    return tmp;
05546 }

static int zt_open ( char *  fn  )  [static]

Definition at line 925 of file chan_zap.c.

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

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

00926 {
00927    int fd;
00928    int isnum;
00929    int chan = 0;
00930    int bs;
00931    int x;
00932    isnum = 1;
00933    for (x = 0; x < strlen(fn); x++) {
00934       if (!isdigit(fn[x])) {
00935          isnum = 0;
00936          break;
00937       }
00938    }
00939    if (isnum) {
00940       chan = atoi(fn);
00941       if (chan < 1) {
00942          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
00943          return -1;
00944       }
00945       fn = "/dev/zap/channel";
00946    }
00947    fd = open(fn, O_RDWR | O_NONBLOCK);
00948    if (fd < 0) {
00949       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
00950       return -1;
00951    }
00952    if (chan) {
00953       if (ioctl(fd, ZT_SPECIFY, &chan)) {
00954          x = errno;
00955          close(fd);
00956          errno = x;
00957          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
00958          return -1;
00959       }
00960    }
00961    bs = READ_SIZE;
00962    if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) {
00963       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
00964       x = errno;
00965       close(fd);
00966       errno = x;
00967       return -1;
00968    }
00969    return fd;
00970 }

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

Definition at line 4786 of file chan_zap.c.

References __zt_exception(), ast_channel::_state, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_dsp_process(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_verbose(), zt_subchannel::buffer, zt_pvt::busydetect, zt_pvt::callprogress, zt_pvt::callwaitcas, zt_pvt::callwaitingrepeat, zt_pvt::callwaitrings, zt_pvt::channel, CHECK_BLOCKING, zt_pvt::cidcwexpire, zt_pvt::cidrings, zt_pvt::cidspill, ast_frame::data, ast_frame::datalen, ast_frame::delivery, zt_pvt::dialing, zt_pvt::dsp, errno, zt_subchannel::f, 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, LOG_WARNING, 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().

04787 {
04788    struct zt_pvt *p = ast->tech_pvt;
04789    int res;
04790    int index;
04791    void *readbuf;
04792    struct ast_frame *f;
04793    
04794 
04795    ast_mutex_lock(&p->lock);
04796    
04797    index = zt_get_index(ast, p, 0);
04798    
04799    /* Hang up if we don't really exist */
04800    if (index < 0) {
04801       ast_log(LOG_WARNING, "We dont exist?\n");
04802       ast_mutex_unlock(&p->lock);
04803       return NULL;
04804    }
04805    
04806    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
04807 
04808    p->subs[index].f.frametype = AST_FRAME_NULL;
04809    p->subs[index].f.datalen = 0;
04810    p->subs[index].f.samples = 0;
04811    p->subs[index].f.mallocd = 0;
04812    p->subs[index].f.offset = 0;
04813    p->subs[index].f.subclass = 0;
04814    p->subs[index].f.delivery = ast_tv(0,0);
04815    p->subs[index].f.src = "zt_read";
04816    p->subs[index].f.data = NULL;
04817    
04818    /* make sure it sends initial key state as first frame */
04819    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
04820    {
04821       ZT_PARAMS ps;
04822 
04823       ps.channo = p->channel;
04824       if (ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
04825          ast_mutex_unlock(&p->lock);
04826          return NULL;
04827       }
04828       p->firstradio = 1;
04829       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04830       if (ps.rxisoffhook)
04831       {
04832          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04833       }
04834       else
04835       {
04836          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04837       }
04838       ast_mutex_unlock(&p->lock);
04839       return &p->subs[index].f;
04840    }
04841    if (p->ringt == 1) {
04842       ast_mutex_unlock(&p->lock);
04843       return NULL;
04844    }
04845    else if (p->ringt > 0) 
04846       p->ringt--;
04847 
04848    if (p->subs[index].needringing) {
04849       /* Send ringing frame if requested */
04850       p->subs[index].needringing = 0;
04851       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04852       p->subs[index].f.subclass = AST_CONTROL_RINGING;
04853       ast_setstate(ast, AST_STATE_RINGING);
04854       ast_mutex_unlock(&p->lock);
04855       return &p->subs[index].f;
04856    }
04857 
04858    if (p->subs[index].needbusy) {
04859       /* Send busy frame if requested */
04860       p->subs[index].needbusy = 0;
04861       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04862       p->subs[index].f.subclass = AST_CONTROL_BUSY;
04863       ast_mutex_unlock(&p->lock);
04864       return &p->subs[index].f;
04865    }
04866 
04867    if (p->subs[index].needcongestion) {
04868       /* Send congestion frame if requested */
04869       p->subs[index].needcongestion = 0;
04870       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04871       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
04872       ast_mutex_unlock(&p->lock);
04873       return &p->subs[index].f;
04874    }
04875 
04876    if (p->subs[index].needcallerid) {
04877       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
04878                      S_OR(p->lastcid_name, NULL),
04879                      S_OR(p->lastcid_num, NULL)
04880                      );
04881       p->subs[index].needcallerid = 0;
04882    }
04883    
04884    if (p->subs[index].needanswer) {
04885       /* Send answer frame if requested */
04886       p->subs[index].needanswer = 0;
04887       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04888       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04889       ast_mutex_unlock(&p->lock);
04890       return &p->subs[index].f;
04891    }  
04892    
04893    if (p->subs[index].needflash) {
04894       /* Send answer frame if requested */
04895       p->subs[index].needflash = 0;
04896       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04897       p->subs[index].f.subclass = AST_CONTROL_FLASH;
04898       ast_mutex_unlock(&p->lock);
04899       return &p->subs[index].f;
04900    }  
04901    
04902    if (p->subs[index].needhold) {
04903       /* Send answer frame if requested */
04904       p->subs[index].needhold = 0;
04905       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04906       p->subs[index].f.subclass = AST_CONTROL_HOLD;
04907       ast_mutex_unlock(&p->lock);
04908       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
04909       return &p->subs[index].f;
04910    }  
04911    
04912    if (p->subs[index].needunhold) {
04913       /* Send answer frame if requested */
04914       p->subs[index].needunhold = 0;
04915       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04916       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
04917       ast_mutex_unlock(&p->lock);
04918       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
04919       return &p->subs[index].f;
04920    }  
04921    
04922    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
04923       if (!p->subs[index].linear) {
04924          p->subs[index].linear = 1;
04925          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
04926          if (res) 
04927             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
04928       }
04929    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
04930          (ast->rawreadformat == AST_FORMAT_ALAW)) {
04931       if (p->subs[index].linear) {
04932          p->subs[index].linear = 0;
04933          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
04934          if (res) 
04935             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
04936       }
04937    } else {
04938       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
04939       ast_mutex_unlock(&p->lock);
04940       return NULL;
04941    }
04942    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
04943    CHECK_BLOCKING(ast);
04944    res = read(p->subs[index].zfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04945    ast_clear_flag(ast, AST_FLAG_BLOCKING);
04946    /* Check for hangup */
04947    if (res < 0) {
04948       f = NULL;
04949       if (res == -1)  {
04950          if (errno == EAGAIN) {
04951             /* Return "NULL" frame if there is nobody there */
04952             ast_mutex_unlock(&p->lock);
04953             return &p->subs[index].f;
04954          } else if (errno == ELAST) {
04955             f = __zt_exception(ast);
04956          } else
04957             ast_log(LOG_WARNING, "zt_rec: %s\n", strerror(errno));
04958       }
04959       ast_mutex_unlock(&p->lock);
04960       return f;
04961    }
04962    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
04963       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04964       f = __zt_exception(ast);
04965       ast_mutex_unlock(&p->lock);
04966       return f;
04967    }
04968    if (p->tdd) { /* if in TDD mode, see if we receive that */
04969       int c;
04970 
04971       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
04972       if (c < 0) {
04973          ast_log(LOG_DEBUG,"tdd_feed failed\n");
04974          ast_mutex_unlock(&p->lock);
04975          return NULL;
04976       }
04977       if (c) { /* if a char to return */
04978          p->subs[index].f.subclass = 0;
04979          p->subs[index].f.frametype = AST_FRAME_TEXT;
04980          p->subs[index].f.mallocd = 0;
04981          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04982          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
04983          p->subs[index].f.datalen = 1;
04984          *((char *) p->subs[index].f.data) = c;
04985          ast_mutex_unlock(&p->lock);
04986          return &p->subs[index].f;
04987       }
04988    }
04989    /* Ensure the CW timer decrements only on a single subchannel */
04990    if (p->callwaitingrepeat && zt_get_index(ast, p, 1) == SUB_REAL) {
04991       p->callwaitingrepeat--;
04992    }
04993    if (p->cidcwexpire)
04994       p->cidcwexpire--;
04995    /* Repeat callwaiting */
04996    if (p->callwaitingrepeat == 1) {
04997       p->callwaitrings++;
04998       zt_callwait(ast);
04999    }
05000    /* Expire CID/CW */
05001    if (p->cidcwexpire == 1) {
05002       if (option_verbose > 2)
05003          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
05004       restore_conference(p);
05005    }
05006    if (p->subs[index].linear) {
05007       p->subs[index].f.datalen = READ_SIZE * 2;
05008    } else 
05009       p->subs[index].f.datalen = READ_SIZE;
05010 
05011    /* Handle CallerID Transmission */
05012    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05013       send_callerid(p);
05014    }
05015 
05016    p->subs[index].f.frametype = AST_FRAME_VOICE;
05017    p->subs[index].f.subclass = ast->rawreadformat;
05018    p->subs[index].f.samples = READ_SIZE;
05019    p->subs[index].f.mallocd = 0;
05020    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05021    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
05022 #if 0
05023    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
05024 #endif   
05025    if (p->dialing || /* Transmitting something */
05026       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
05027       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05028       ) {
05029       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05030          don't send anything */
05031       p->subs[index].f.frametype = AST_FRAME_NULL;
05032       p->subs[index].f.subclass = 0;
05033       p->subs[index].f.samples = 0;
05034       p->subs[index].f.mallocd = 0;
05035       p->subs[index].f.offset = 0;
05036       p->subs[index].f.data = NULL;
05037       p->subs[index].f.datalen= 0;
05038    }
05039    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
05040       /* Perform busy detection. etc on the zap line */
05041       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05042       if (f) {
05043          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05044             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05045                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05046                   a busy  */
05047                f = NULL;
05048             }
05049          } else if (f->frametype == AST_FRAME_DTMF) {
05050 #ifdef HAVE_PRI
05051             if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
05052                /* Don't accept in-band DTMF when in overlap dial mode
05053                   or when in non-overlap overlapdialing mode ... */
05054                f->frametype = AST_FRAME_NULL;
05055                f->subclass = 0;
05056             }
05057 #endif            
05058             /* DSP clears us of being pulse */
05059             p->pulsedial = 0;
05060          }
05061       }
05062    } else 
05063       f = &p->subs[index].f; 
05064 
05065    if (f && (f->frametype == AST_FRAME_DTMF))
05066       zt_handle_dtmfup(ast, index, &f);
05067 
05068    /* If we have a fake_event, trigger exception to handle it */
05069    if (p->fake_event)
05070       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05071 
05072    ast_mutex_unlock(&p->lock);
05073    return f;
05074 }

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

Definition at line 8040 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_3_1K_AUDIO, AST_TRANS_CAP_DIGITAL, ast_verbose(), available(), busy, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), zt_pvt::channel, zt_pvt::confirmanswer, zt_pvt::digital, zt_pvt::distinctivering, zt_pvt::faxhandled, iflist, zt_pvt::inalarm, lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, zt_pvt::next, option_debug, zt_pvt::outgoing, zt_pvt::owner, zt_pvt::prev, restart_monitor(), s, zt_pvt::sig, SIG_FXSKS, strsep(), SUB_CALLWAIT, SUB_REAL, zt_pvt::subs, ast_channel::transfercapability, zt_subchannel::zfd, and zt_new().

08041 {
08042    ast_group_t groupmatch = 0;
08043    int channelmatch = -1;
08044    int roundrobin = 0;
08045    int callwait = 0;
08046    int busy = 0;
08047    struct zt_pvt *p;
08048    struct ast_channel *tmp = NULL;
08049    char *dest=NULL;
08050    int x;
08051    char *s;
08052    char opt=0;
08053    int res=0, y=0;
08054    int backwards = 0;
08055 #ifdef HAVE_PRI
08056    int crv;
08057    int bearer = -1;
08058    int trunkgroup;
08059    struct zt_pri *pri=NULL;
08060 #endif   
08061    struct zt_pvt *exit, *start, *end;
08062    ast_mutex_t *lock;
08063    int channelmatched = 0;
08064    int groupmatched = 0;
08065    
08066    /* Assume we're locking the iflock */
08067    lock = &iflock;
08068    start = iflist;
08069    end = ifend;
08070    if (data) {
08071       dest = ast_strdupa((char *)data);
08072    } else {
08073       ast_log(LOG_WARNING, "Channel requested with no data\n");
08074       return NULL;
08075    }
08076    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08077       /* Retrieve the group number */
08078       char *stringp=NULL;
08079       stringp=dest + 1;
08080       s = strsep(&stringp, "/");
08081       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08082          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08083          return NULL;
08084       }
08085       groupmatch = ((ast_group_t) 1 << x);
08086       if (toupper(dest[0]) == 'G') {
08087          if (dest[0] == 'G') {
08088             backwards = 1;
08089             p = ifend;
08090          } else
08091             p = iflist;
08092       } else {
08093          if (dest[0] == 'R') {
08094             backwards = 1;
08095             p = round_robin[x]?round_robin[x]->prev:ifend;
08096             if (!p)
08097                p = ifend;
08098          } else {
08099             p = round_robin[x]?round_robin[x]->next:iflist;
08100             if (!p)
08101                p = iflist;
08102          }
08103          roundrobin = 1;
08104       }
08105    } else {
08106       char *stringp=NULL;
08107       stringp=dest;
08108       s = strsep(&stringp, "/");
08109       p = iflist;
08110       if (!strcasecmp(s, "pseudo")) {
08111          /* Special case for pseudo */
08112          x = CHAN_PSEUDO;
08113          channelmatch = x;
08114       } 
08115 #ifdef HAVE_PRI
08116       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08117          if ((trunkgroup < 1) || (crv < 1)) {
08118             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08119             return NULL;
08120          }
08121          res--;
08122          for (x = 0; x < NUM_SPANS; x++) {
08123             if (pris[x].trunkgroup == trunkgroup) {
08124                pri = pris + x;
08125                lock = &pri->lock;
08126                start = pri->crvs;
08127                end = pri->crvend;
08128                break;
08129             }
08130          }
08131          if (!pri) {
08132             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08133             return NULL;
08134          }
08135          channelmatch = crv;
08136          p = pris[x].crvs;
08137       }
08138 #endif   
08139       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08140          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08141          return NULL;
08142       } else {
08143          channelmatch = x;
08144       }
08145    }
08146    /* Search for an unowned channel */
08147    ast_mutex_lock(lock);
08148    exit = p;
08149    while (p && !tmp) {
08150       if (roundrobin)
08151          round_robin[x] = p;
08152 #if 0
08153       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08154 #endif
08155 
08156       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08157          if (option_debug)
08158             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08159             if (p->inalarm) 
08160                goto next;
08161 
08162          callwait = (p->owner != NULL);
08163 #ifdef HAVE_PRI
08164          if (pri && (p->subs[SUB_REAL].zfd < 0)) {
08165             if (p->sig != SIG_FXSKS) {
08166                /* Gotta find an actual channel to use for this
08167                   CRV if this isn't a callwait */
08168                bearer = pri_find_empty_chan(pri, 0);
08169                if (bearer < 0) {
08170                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08171                   p = NULL;
08172                   break;
08173                }
08174                pri_assign_bearer(p, pri, pri->pvts[bearer]);
08175             } else {
08176                if (alloc_sub(p, 0)) {
08177                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08178                   p = NULL;
08179                   break;
08180                } else
08181                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08182                p->pri = pri;
08183             }
08184          }
08185 #endif         
08186          if (p->channel == CHAN_PSEUDO) {
08187             p = chandup(p);
08188             if (!p) {
08189                break;
08190             }
08191          }
08192          if (p->owner) {
08193             if (alloc_sub(p, SUB_CALLWAIT)) {
08194                p = NULL;
08195                break;
08196             }
08197          }
08198          p->outgoing = 1;
08199          tmp = zt_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08200 #ifdef HAVE_PRI
08201          if (p->bearer) {
08202             /* Log owner to bearer channel, too */
08203             p->bearer->owner = tmp;
08204          }
08205 #endif         
08206          /* Make special notes */
08207          if (res > 1) {
08208             if (opt == 'c') {
08209                /* Confirm answer */
08210                p->confirmanswer = 1;
08211             } else if (opt == 'r') {
08212                /* Distinctive ring */
08213                if (res < 3)
08214                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08215                else
08216                   p->distinctivering = y;
08217             } else if (opt == 'd') {
08218                /* If this is an ISDN call, make it digital */
08219                p->digital = 1;
08220                if (tmp)
08221                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08222             } else if (opt == 'm') {
08223                /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
08224                p->faxhandled = 1;
08225                if (tmp)
08226                    tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
08227             } else {
08228                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08229             }
08230          }
08231          /* Note if the call is a call waiting call */
08232          if (tmp && callwait)
08233             tmp->cdrflags |= AST_CDR_CALLWAIT;
08234          break;
08235       }
08236 next:
08237       if (backwards) {
08238          p = p->prev;
08239          if (!p)
08240             p = end;
08241       } else {
08242          p = p->next;
08243          if (!p)
08244             p = start;
08245       }
08246       /* stop when you roll to the one that we started from */
08247       if (p == exit)
08248          break;
08249    }
08250    ast_mutex_unlock(lock);
08251    restart_monitor();
08252    if (callwait)
08253       *cause = AST_CAUSE_BUSY;
08254    else if (!tmp) {
08255       if (channelmatched) {
08256          if (busy)
08257             *cause = AST_CAUSE_BUSY;
08258       } else if (groupmatched) {
08259          *cause = AST_CAUSE_CONGESTION;
08260       } else {
08261          *cause = AST_CAUSE_CONGESTION;
08262       }
08263    }
08264       
08265    return tmp;
08266 }

static int zt_ring_phone ( struct zt_pvt p  )  [static]

Definition at line 3615 of file chan_zap.c.

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

Referenced by __zt_exception(), and zt_handle_event().

03616 {
03617    int x;
03618    int res;
03619    /* Make sure our transmit state is on hook */
03620    x = 0;
03621    x = ZT_ONHOOK;
03622    res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03623    do {
03624       x = ZT_RING;
03625       res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03626       if (res) {
03627          switch (errno) {
03628          case EBUSY:
03629          case EINTR:
03630             /* Wait just in case */
03631             usleep(10000);
03632             continue;
03633          case EINPROGRESS:
03634             res = 0;
03635             break;
03636          default:
03637             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03638             res = 0;
03639          }
03640       }
03641    } while (res);
03642    return res;
03643 }

static int zt_sendmessage ( struct ast_channel c,
const char *  dest,
const char *  text,
int  ispdu 
) [static]

Definition at line 12848 of file chan_zap.c.

References ast_log(), LOG_WARNING, zt_pvt::sig, SIG_GSM, SIG_PRI, ast_channel::tech_pvt, and zt_tdd_sendtext().

12848                                                                                                 {
12849 struct zt_pvt *p = c->tech_pvt;
12850  if (!p) return -1;
12851  if (p->sig == SIG_PRI) {
12852 #ifdef HAVE_PRI
12853    if (ispdu) {
12854        ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP ISDN channel\n");
12855        return -1;
12856    }
12857    return zt_pri_sendtext(c, text);
12858 #endif
12859  } else if (p->sig == SIG_GSM) {
12860 #ifdef HAVE_GSMAT
12861      return zt_gsm_sendtext(c, dest, text, ispdu);
12862 #endif
12863  } else {
12864    if (ispdu) {
12865        ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP channel\n");
12866        return -1;
12867    }
12868    return zt_tdd_sendtext(c, text);
12869  }
12870  return -1;
12871 }

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

Definition at line 12834 of file chan_zap.c.

References zt_pvt::sig, SIG_GSM, SIG_PRI, ast_channel::tech_pvt, and zt_tdd_sendtext().

12834                                                                 {
12835  struct zt_pvt *p = c->tech_pvt;
12836  if (!p) return -1;
12837  if (p->sig == SIG_PRI) {
12838 #ifdef HAVE_PRI
12839    return zt_pri_sendtext(c, text);
12840 #endif
12841  } else if (p->sig == SIG_GSM) {
12842  } else {
12843    return zt_tdd_sendtext(c, text);
12844  }
12845  return -1;
12846 }

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

Definition at line 1674 of file chan_zap.c.

References ast_log(), errno, and LOG_WARNING.

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

01675 {
01676    int x, res;
01677 
01678    x = hs;
01679    res = ioctl(fd, ZT_HOOK, &x);
01680 
01681    if (res < 0) {
01682       if (errno == EINPROGRESS)
01683          return 0;
01684       ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
01685    }
01686 
01687    return res;
01688 }

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

Definition at line 2510 of file chan_zap.c.

02511 {
02512    int res;
02513    res = ioctl(zfd, ZT_SETLAW, &law);
02514    if (res)
02515       return res;
02516    return 0;
02517 }

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

Definition at line 978 of file chan_zap.c.

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

00979 {
00980    int res;
00981    res = ioctl(zfd, ZT_SETLINEAR, &linear);
00982    if (res)
00983       return res;
00984    return 0;
00985 }

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

Definition at line 2971 of file chan_zap.c.

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

02972 {
02973    char *cp;
02974    signed char *scp;
02975    int x;
02976    int index;
02977    struct zt_pvt *p = chan->tech_pvt, *pp;
02978    struct oprmode *oprmode;
02979    
02980 
02981    /* all supported options require data */
02982    if (!data || (datalen < 1)) {
02983       errno = EINVAL;
02984       return -1;
02985    }
02986 
02987    switch (option) {
02988    case AST_OPTION_TXGAIN:
02989       scp = (signed char *) data;
02990       index = zt_get_index(chan, p, 0);
02991       if (index < 0) {
02992          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
02993          return -1;
02994       }
02995       if (option_debug)
02996          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
02997       return set_actual_txgain(p->subs[index].zfd, 0, p->txgain + (float) *scp, p->law);
02998    case AST_OPTION_RXGAIN:
02999       scp = (signed char *) data;
03000       index = zt_get_index(chan, p, 0);
03001       if (index < 0) {
03002          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03003          return -1;
03004       }
03005       if (option_debug)
03006          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03007       return set_actual_rxgain(p->subs[index].zfd, 0, p->rxgain + (float) *scp, p->law);
03008    case AST_OPTION_TONE_VERIFY:
03009       if (!p->dsp)
03010          break;
03011       cp = (char *) data;
03012       switch (*cp) {
03013       case 1:
03014          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03015          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
03016          break;
03017       case 2:
03018          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03019          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
03020          break;
03021       default:
03022          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03023          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
03024          break;
03025       }
03026       break;
03027    case AST_OPTION_TDD:
03028       /* turn on or off TDD */
03029       cp = (char *) data;
03030       p->mate = 0;
03031       if (!*cp) { /* turn it off */
03032          if (option_debug)
03033             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03034          if (p->tdd)
03035             tdd_free(p->tdd);
03036          p->tdd = 0;
03037          break;
03038       }
03039       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03040          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03041       zt_disable_ec(p);
03042       /* otherwise, turn it on */
03043       if (!p->didtdd) { /* if havent done it yet */
03044          unsigned char mybuf[41000], *buf;
03045          int size, res, fd, len;
03046          struct pollfd fds[1];
03047 
03048          buf = mybuf;
03049          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03050          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03051          len = 40000;
03052          index = zt_get_index(chan, p, 0);
03053          if (index < 0) {
03054             ast_log(LOG_WARNING, "No index in TDD?\n");
03055             return -1;
03056          }
03057          fd = p->subs[index].zfd;
03058          while (len) {
03059             if (ast_check_hangup(chan))
03060                return -1;
03061             size = len;
03062             if (size > READ_SIZE)
03063                size = READ_SIZE;
03064             fds[0].fd = fd;
03065             fds[0].events = POLLPRI | POLLOUT;
03066             fds[0].revents = 0;
03067             res = poll(fds, 1, -1);
03068             if (!res) {
03069                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03070                continue;
03071             }
03072             /* if got exception */
03073             if (fds[0].revents & POLLPRI)
03074                return -1;
03075             if (!(fds[0].revents & POLLOUT)) {
03076                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03077                continue;
03078             }
03079             res = write(fd, buf, size);
03080             if (res != size) {
03081                if (res == -1) return -1;
03082                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03083                break;
03084             }
03085             len -= size;
03086             buf += size;
03087          }
03088          p->didtdd = 1; /* set to have done it now */    
03089       }
03090       if (*cp == 2) { /* Mate mode */
03091          if (p->tdd)
03092             tdd_free(p->tdd);
03093          p->tdd = 0;
03094          p->mate = 1;
03095          break;
03096       }     
03097       if (!p->tdd) { /* if we dont have one yet */
03098          p->tdd = tdd_new(); /* allocate one */
03099       }     
03100       break;
03101    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03102       if (!p->dsp)
03103          break;
03104       cp = (char *) data;
03105       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03106          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03107                 p->dtmfrelax = 0;
03108                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03109                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03110       break;
03111    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03112       cp = (char *) data;
03113       if (!*cp) {    
03114          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03115          x = 0;
03116          zt_disable_ec(p);
03117       } else {    
03118          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03119          x = 1;
03120       }
03121       if (ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x) == -1)
03122          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", p->channel, x);
03123       break;
03124    case AST_OPTION_OPRMODE:  /* Operator services mode */
03125       oprmode = (struct oprmode *) data;
03126       pp = oprmode->peer->tech_pvt;
03127       p->oprmode = pp->oprmode = 0;
03128       /* setup peers */
03129       p->oprpeer = pp;
03130       pp->oprpeer = p;
03131       /* setup modes, if any */
03132       if (oprmode->mode) 
03133       {
03134          pp->oprmode = oprmode->mode;
03135          p->oprmode = -oprmode->mode;
03136       }
03137       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03138          oprmode->mode, chan->name,oprmode->peer->name);;
03139       break;
03140    case AST_OPTION_ECHOCAN:
03141       cp = (char *) data;
03142       if (*cp) {
03143          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03144          zt_enable_ec(p);
03145       } else {
03146          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03147          zt_disable_ec(p);
03148       }
03149       break;
03150    }
03151    errno = 0;
03152 
03153    return 0;
03154 }

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

Definition at line 12873 of file chan_zap.c.

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

Referenced by zt_sendmessage(), and zt_sendtext().

12874 {
12875 #define  END_SILENCE_LEN 400
12876 #define  HEADER_MS 50
12877 #define  TRAILER_MS 5
12878 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
12879 #define  ASCII_BYTES_PER_CHAR 80
12880 
12881    unsigned char *buf,*mybuf;
12882    struct zt_pvt *p = c->tech_pvt;
12883    struct pollfd fds[1];
12884    int size,res,fd,len,x;
12885    int bytes=0;
12886    /* Initial carrier (imaginary) */
12887    float cr = 1.0;
12888    float ci = 0.0;
12889    float scont = 0.0;
12890    int index;
12891 
12892 
12893    index = zt_get_index(c, p, 0);
12894    if (index < 0) {
12895       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
12896       return -1;
12897    }
12898    if (!text[0]) return(0); /* if nothing to send, dont */
12899    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
12900    if (p->mate) 
12901       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
12902    else
12903       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
12904    if (!buf)
12905       return -1;
12906    mybuf = buf;
12907    if (p->mate) {
12908       int codec = AST_LAW(p);
12909       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
12910          PUT_CLID_MARKMS;
12911       }
12912       /* Put actual message */
12913       for (x = 0; text[x]; x++) {
12914          PUT_CLID(text[x]);
12915       }
12916       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
12917          PUT_CLID_MARKMS;
12918       }
12919       len = bytes;
12920       buf = mybuf;
12921    } else {
12922       len = tdd_generate(p->tdd, buf, text);
12923       if (len < 1) {
12924          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
12925          free(mybuf);
12926          return -1;
12927       }
12928    }
12929    memset(buf + len, 0x7f, END_SILENCE_LEN);
12930    len += END_SILENCE_LEN;
12931    fd = p->subs[index].zfd;
12932    while (len) {
12933       if (ast_check_hangup(c)) {
12934          free(mybuf);
12935          return -1;
12936       }
12937       size = len;
12938       if (size > READ_SIZE)
12939          size = READ_SIZE;
12940       fds[0].fd = fd;
12941       fds[0].events = POLLOUT | POLLPRI;
12942       fds[0].revents = 0;
12943       res = poll(fds, 1, -1);
12944       if (!res) {
12945          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
12946          continue;
12947       }
12948         /* if got exception */
12949       if (fds[0].revents & POLLPRI) {
12950          ast_free(mybuf);
12951          return -1;
12952       }
12953       if (!(fds[0].revents & POLLOUT)) {
12954          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12955          continue;
12956       }
12957       res = write(fd, buf, size);
12958       if (res != size) {
12959          if (res == -1) {
12960             free(mybuf);
12961             return -1;
12962          }
12963          if (option_debug)
12964             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12965          break;
12966       }
12967       len -= size;
12968       buf += size;
12969    }
12970    free(mybuf);
12971    return(0);
12972 }

static void zt_train_ec ( struct zt_pvt p  )  [static]

Definition at line 1506 of file chan_zap.c.

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

Referenced by zt_answer(), and zt_handle_event().

01507 {
01508    int x;
01509    int res;
01510    if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
01511       x = p->echotraining;
01512       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
01513       if (res)
01514          ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
01515       else {
01516          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01517       }
01518    } else
01519       ast_log(LOG_DEBUG, "No echo training requested\n");
01520 }

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

Definition at line 3175 of file chan_zap.c.

References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), zt_pvt::channel, conf_del(), DEADLOCK_AVOIDANCE, zt_pvt::inconference, zt_pvt::lock, LOG_DEBUG, zt_pvt::master, MAX_SLAVES, zt_pvt::slaves, SUB_REAL, zt_pvt::subs, and update_conf().

Referenced by zt_bridge(), and zt_fixup().

03176 {
03177    /* Unlink a specific slave or all slaves/masters from a given master */
03178    int x;
03179    int hasslaves;
03180    if (!master)
03181       return;
03182    if (needlock) {
03183       ast_mutex_lock(&master->lock);
03184       if (slave) {
03185          while (ast_mutex_trylock(&slave->lock)) {
03186             DEADLOCK_AVOIDANCE(&master->lock);
03187          }
03188       }
03189    }
03190    hasslaves = 0;
03191    for (x = 0; x < MAX_SLAVES; x++) {
03192       if (master->slaves[x]) {
03193          if (!slave || (master->slaves[x] == slave)) {
03194             /* Take slave out of the conference */
03195             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03196             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03197             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03198             master->slaves[x]->master = NULL;
03199             master->slaves[x] = NULL;
03200          } else
03201             hasslaves = 1;
03202       }
03203       if (!hasslaves)
03204          master->inconference = 0;
03205    }
03206    if (!slave) {
03207       if (master->master) {
03208          /* Take master out of the conference */
03209          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03210          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03211          hasslaves = 0;
03212          for (x = 0; x < MAX_SLAVES; x++) {
03213             if (master->master->slaves[x] == master)
03214                master->master->slaves[x] = NULL;
03215             else if (master->master->slaves[x])
03216                hasslaves = 1;
03217          }
03218          if (!hasslaves)
03219             master->master->inconference = 0;
03220       }
03221       master->master = NULL;
03222    }
03223    update_conf(master);
03224    if (needlock) {
03225       if (slave)
03226          ast_mutex_unlock(&slave->lock);
03227       ast_mutex_unlock(&master->lock);
03228    }
03229 }

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

Avoid the silly zt_waitevent which ignores a bunch of events.

Definition at line 272 of file chan_zap.c.

Referenced by flash_exec(), and ss_thread().

00273 {
00274    int i, j = 0;
00275    i = ZT_IOMUX_SIGEVENT;
00276    if (ioctl(fd, ZT_IOMUX, &i) == -1)
00277       return -1;
00278    if (ioctl(fd, ZT_GETEVENT, &j) == -1)
00279       return -1;
00280    return j;
00281 }

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

Definition at line 5568 of file chan_zap.c.

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

Referenced by ss_thread().

05569 {
05570    int j;
05571    zt_set_hook(p->subs[index].zfd, ZT_WINK);
05572    for (;;)
05573    {
05574          /* set bits of interest */
05575       j = ZT_IOMUX_SIGEVENT;
05576           /* wait for some happening */
05577       if (ioctl(p->subs[index].zfd,ZT_IOMUX,&j) == -1) return(-1);
05578          /* exit loop if we have it */
05579       if (j & ZT_IOMUX_SIGEVENT) break;
05580    }
05581      /* get the event info */
05582    if (ioctl(p->subs[index].zfd,ZT_GETEVENT,&j) == -1) return(-1);
05583    return 0;
05584 }

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

Definition at line 5099 of file chan_zap.c.

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

05100 {
05101    struct zt_pvt *p = ast->tech_pvt;
05102    int res;
05103    int index;
05104    index = zt_get_index(ast, p, 0);
05105    if (index < 0) {
05106       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05107       return -1;
05108    }
05109 
05110 #if 0
05111 #ifdef HAVE_PRI
05112    ast_mutex_lock(&p->lock);
05113    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05114       if (p->pri->pri) {      
05115          if (!pri_grab(p, p->pri)) {
05116                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05117                pri_rel(p->pri);
05118          } else
05119                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05120       }
05121       p->proceeding=1;
05122    }
05123    ast_mutex_unlock(&p->lock);
05124 #endif
05125 #endif
05126    /* Write a frame of (presumably voice) data */
05127    if (frame->frametype != AST_FRAME_VOICE) {
05128       if (frame->frametype == AST_FRAME_TEXT) {
05129          ast_log(LOG_NOTICE, "text\n");
05130       } else if (frame->frametype != AST_FRAME_IMAGE)
05131          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05132       return 0;
05133    }
05134    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
05135        (frame->subclass != AST_FORMAT_ULAW) &&
05136        (frame->subclass != AST_FORMAT_ALAW)) {
05137       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05138       return -1;
05139    }
05140    if (p->dialing) {
05141       if (option_debug)
05142          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05143       return 0;
05144    }
05145    if (!p->owner) {
05146       if (option_debug)
05147          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05148       return 0;
05149    }
05150    if (p->cidspill) {
05151       if (option_debug)
05152          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05153       return 0;
05154    }
05155    /* Return if it's not valid data */
05156    if (!frame->data || !frame->datalen)
05157       return 0;
05158 
05159    if (frame->subclass == AST_FORMAT_SLINEAR) {
05160       if (!p->subs[index].linear) {
05161          p->subs[index].linear = 1;
05162          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
05163          if (res)
05164             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05165       }
05166       res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05167    } else {
05168       /* x-law already */
05169       if (p->subs[index].linear) {
05170          p->subs[index].linear = 0;
05171          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
05172          if (res)
05173             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05174       }
05175       res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05176    }
05177    if (res < 0) {
05178       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05179       return -1;
05180    } 
05181    return 0;
05182 }


Variable Documentation

int alarm

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

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

Definition at line 173 of file chan_zap.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 117 of file chan_zap.c.

char defaultcic[64] = "" [static]

Definition at line 213 of file chan_zap.c.

char defaultozz[64] = "" [static]

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

int distinctiveringaftercid = 0 [static]

Definition at line 218 of file chan_zap.c.

struct zt_distRings drings [static]

Definition at line 402 of file chan_zap.c.

Referenced by mkintf(), and process_zap().

char* events[] [static]

Definition at line 1155 of file chan_zap.c.

Referenced by authenticate().

int firstdigittimeout = 16000 [static]

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

Definition at line 230 of file chan_zap.c.

int gendigittimeout = 8000 [static]

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

Definition at line 233 of file chan_zap.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 124 of file chan_zap.c.

char gsm_modem_exten[AST_MAX_EXTENSION] [static]

Definition at line 242 of file chan_zap.c.

char gsm_modem_pin[20] [static]

Definition at line 241 of file chan_zap.c.

int ifcount = 0 [static]

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

char* name

Definition at line 1179 of file chan_zap.c.

int num_cadence = 4 [static]

Definition at line 794 of file chan_zap.c.

int numbufs = 4 [static]

Definition at line 220 of file chan_zap.c.

char progzone[10] = "" [static]

Definition at line 216 of file chan_zap.c.

int ringt_base = DEFAULT_RINGT [static]

Definition at line 297 of file chan_zap.c.

struct zt_pvt* round_robin[32]

Definition at line 767 of file chan_zap.c.

char show_channel_usage[] [static]

Initial value:

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

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

char* subnames[] [static]

Initial value:

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

Definition at line 415 of file chan_zap.c.

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

Definition at line 167 of file chan_zap.c.

int user_has_defined_cadences = 0 [static]

Definition at line 795 of file chan_zap.c.

struct ast_cli_entry zap_cli[] [static]

Definition at line 11517 of file chan_zap.c.

char zap_restart_usage[] [static]

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

struct ast_channel_tech zap_tech [static]

Definition at line 737 of file chan_zap.c.

char* zapEC_app = "zapEC" [static]

Definition at line 11155 of file chan_zap.c.

char* zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel" [static]

Definition at line 11156 of file chan_zap.c.

char* zapEC_tdesc = "Enable/disable Echo cancelation" [static]

Definition at line 11154 of file chan_zap.c.


Generated on Thu Oct 8 21:56:22 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6