Thu Oct 8 21:57:44 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 11548 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 11912 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 12998 of file chan_zap.c.

#define TRAILER_MS   5

Referenced by zt_tdd_sendtext().

#define TRANSFER   0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 11205 of file chan_zap.c.

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

Referenced by load_module().

11206 {
11207    if (zap_restart() != 0) {
11208       astman_send_error(s, m, "Failed rereading zaptel configuration");
11209       return 1;
11210    }
11211    astman_send_ack(s, m, "ZapRestart: Success");
11212    return 0;
11213 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int check_for_conference ( struct zt_pvt p  )  [static]

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

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

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

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

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

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

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

static void enable_dtmf_detect ( struct zt_pvt p  )  [static]

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

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

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

11567 {
11568    struct zt_pvt *p = iflist;
11569    while (p) {
11570       if (p->channel == channel) {
11571          break;
11572       }
11573       p = p->next;
11574    }
11575    return p;
11576 }

static int get_alarms ( struct zt_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 11410 of file chan_zap.c.

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

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

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

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

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

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

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

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

Definition at line 5550 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

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

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

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

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

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

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

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

static int reload ( void   )  [static]

Definition at line 12979 of file chan_zap.c.

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

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

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

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

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

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

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

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

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

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

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

11811 {
11812 #ifdef HAVE_PRI      
11813    int y;
11814    for (y = 0; y < NUM_SPANS; y++)
11815       ast_mutex_destroy(&pris[y].lock);
11816 #endif
11817    return __unload_module();
11818 }

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

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

11163 {
11164    int channel;
11165    
11166    if (argc != 4)
11167       return RESULT_SHOWUSAGE;
11168    
11169    channel = atoi(argv[3]);
11170 
11171    return zap_destroy_channel_bynum(channel);
11172 }

static int zap_destroy_channel_bynum ( int  channel  )  [static]

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

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

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

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

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

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

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

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

Definition at line 11194 of file chan_zap.c.

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

11195 {
11196    if (argc != 2) {
11197       return RESULT_SHOWUSAGE;
11198    }
11199 
11200    if (zap_restart() != 0)
11201       return RESULT_FAILURE;
11202    return RESULT_SUCCESS;
11203 }

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

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

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

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

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

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

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

Definition at line 11437 of file chan_zap.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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                      /* no-op */
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                       p->call = NULL;
02744                   }
02745 
02746                   if (p->pri->nodetype == BRI_NETWORK_PTMP) {
02747                       if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
02748                      if (outgoing) {
02749                          p->call = NULL;
02750                      }
02751                       }
02752                   }
02753 
02754 
02755                }
02756                if (res < 0) 
02757                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
02758                pri_rel(p->pri);        
02759             } else {
02760                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02761                res = -1;
02762             }
02763          } else {
02764             if (p->bearer)
02765                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02766             p->call = NULL;
02767             res = 0;
02768          }
02769       }
02770 #endif
02771 #ifdef HAVE_GSMAT
02772       if (p->gsm.modul) {
02773           if (!p->alreadyhungup)
02774          gsm_hangup(p->gsm.modul);
02775       }
02776 #endif
02777       if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_GSM))
02778          res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
02779       if (res < 0) {
02780          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02781       }
02782       switch (p->sig) {
02783       case SIG_FXOGS:
02784       case SIG_FXOLS:
02785       case SIG_FXOKS:
02786          res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
02787          if (!res) {
02788 #if 0
02789             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02790 #endif
02791             /* If they're off hook, try playing congestion */
02792             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02793                tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
02794             else
02795                tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
02796          }
02797          break;
02798       case SIG_FXSGS:
02799       case SIG_FXSLS:
02800       case SIG_FXSKS:
02801          /* Make sure we're not made available for at least two seconds assuming
02802             we were actually used for an inbound or outbound call. */
02803          if (ast->_state != AST_STATE_RESERVED) {
02804             time(&p->guardtime);
02805             p->guardtime += 2;
02806          }
02807          break;
02808       default:
02809          tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
02810       }
02811       if (p->cidspill)
02812          free(p->cidspill);
02813       if (p->sig)
02814          zt_disable_ec(p);
02815       x = 0;
02816       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02817       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02818       p->didtdd = 0;
02819       p->cidspill = NULL;
02820       p->callwaitcas = 0;
02821       p->callwaiting = p->permcallwaiting;
02822       p->hidecallerid = p->permhidecallerid;
02823       p->dialing = 0;
02824       p->rdnis[0] = '\0';
02825       update_conf(p);
02826       reset_conf(p);
02827       /* Restore data mode */
02828       if (p->sig == SIG_PRI) {
02829          x = 0;
02830          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02831       }
02832 #ifdef HAVE_PRI
02833       if (p->bearer) {
02834          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02835          /* Free up the bearer channel as well, and
02836             don't use its file descriptor anymore */
02837          update_conf(p->bearer);
02838          reset_conf(p->bearer);
02839          p->bearer->owner = NULL;
02840          p->bearer->realcall = NULL;
02841          p->bearer = NULL;
02842          p->subs[SUB_REAL].zfd = -1;
02843          p->pri = NULL;
02844       }
02845 #endif
02846       restart_monitor();
02847    }
02848 
02849    p->callwaitingrepeat = 0;
02850    p->cidcwexpire = 0;
02851    p->oprmode = 0;
02852    ast->tech_pvt = NULL;
02853    ast_mutex_unlock(&p->lock);
02854    ast_module_unref(ast_module_info->self);
02855    if (option_verbose > 2) 
02856       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02857 
02858    ast_mutex_lock(&iflock);
02859    tmp = iflist;
02860    prev = NULL;
02861    if (p->destroy) {
02862       while (tmp) {
02863          if (tmp == p) {
02864             destroy_channel(prev, tmp, 0);
02865             break;
02866          } else {
02867             prev = tmp;
02868             tmp = tmp->next;
02869          }
02870       }
02871    }
02872    ast_mutex_unlock(&iflock);
02873    return 0;
02874 }

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

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

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

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

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

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

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

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

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

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

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

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

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

static int zt_ring_phone ( struct zt_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 12838 of file chan_zap.c.

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

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

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

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

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

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

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

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

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

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

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

Referenced by ss_thread().

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

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

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

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


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 11510 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 11502 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 11498 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 11521 of file chan_zap.c.

char zap_restart_usage[] [static]

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

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

Definition at line 11160 of file chan_zap.c.

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

Definition at line 11158 of file chan_zap.c.


Generated on Thu Oct 8 21:57:45 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.8