Sat Apr 12 07:12:42 2008

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 "asterisk/devicestate.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   128
#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, int groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct zt_chan_conf conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct zt_pvt *p)
static struct zt_pvtchandup (struct zt_pvt *src)
static int check_for_conference (struct zt_pvt *p)
static int conf_add (struct zt_pvt *p, struct zt_subchannel *c, int index, int slavechannel)
static int conf_del (struct zt_pvt *p, struct zt_subchannel *c, int index)
static int destroy_channel (struct zt_pvt *prev, struct zt_pvt *cur, int now)
static void destroy_zt_pvt (struct zt_pvt **pvt)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct zt_pvt *p)
static void * do_monitor (void *data)
static void enable_dtmf_detect (struct zt_pvt *p)
static char * event2str (int event)
static void fill_rxgain (struct zt_gains *g, float gain, int law)
static void fill_txgain (struct zt_gains *g, float gain, int law)
static struct zt_pvtfind_channel (int channel)
static int get_alarms (struct zt_pvt *p)
static int handle_init_event (struct zt_pvt *i, int event)
static int handle_zap_show_cadences (int fd, int argc, char *argv[])
static int has_voicemail (struct zt_pvt *p)
static int isourconf (struct zt_pvt *p, struct zt_subchannel *c)
static int isslavenative (struct zt_pvt *p, struct zt_pvt **out)
static int load_module (void)
static struct zt_pvtmkintf (int channel, struct zt_chan_conf conf, struct zt_pri *pri, int reloading)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static int my_zt_write (struct zt_pvt *p, unsigned char *buf, int len, int index, int linear)
static int process_zap (struct zt_chan_conf *confp, struct ast_variable *v, int reload, int skipchannels)
static int reload (void)
static int reset_conf (struct zt_pvt *p)
static int restart_monitor (void)
static int restore_conference (struct zt_pvt *p)
static int restore_gains (struct zt_pvt *p)
static int save_conference (struct zt_pvt *p)
static int send_callerid (struct zt_pvt *p)
static int send_cwcidspill (struct zt_pvt *p)
static int set_actual_gain (int fd, int chan, float rxgain, float txgain, int law)
static int set_actual_rxgain (int fd, int chan, float gain, int law)
static int set_actual_txgain (int fd, int chan, float gain, int law)
static int setup_zap (int reload)
static void * ss_thread (void *data)
static void swap_subs (struct zt_pvt *p, int a, int b)
static int unalloc_sub (struct zt_pvt *p, int x)
static int unload_module (void)
static int update_conf (struct zt_pvt *p)
static void wakeup_sub (struct zt_pvt *p, int a, void *pri)
static int zap_destroy_channel (int fd, int argc, char **argv)
static int zap_destroy_channel_bynum (int channel)
static int zap_fake_event (struct zt_pvt *p, int mode)
static void zap_queue_frame (struct zt_pvt *p, struct ast_frame *f, void *pri)
static int zap_restart (void)
static int zap_restart_cmd (int fd, int argc, char **argv)
static int zap_show_channel (int fd, int argc, char **argv)
static int zap_show_channels (int fd, int argc, char **argv)
static int zap_show_status (int fd, int argc, char *argv[])
static char * zap_sig2str (int sig)
static int zt_answer (struct ast_channel *ast)
static enum ast_bridge_result zt_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int zt_call (struct ast_channel *ast, char *rdest, int timeout)
static int zt_callwait (struct ast_channel *ast)
static struct zt_chan_conf zt_chan_conf_default (void)
static void zt_close (int fd)
static int zt_confmute (struct zt_pvt *p, int muted)
static int zt_devicestate (void *data)
static int zt_digit_begin (struct ast_channel *ast, char digit)
static int zt_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void zt_disable_ec (struct zt_pvt *p)
static void zt_enable_ec (struct zt_pvt *p)
static struct ast_framezt_exception (struct ast_channel *ast)
static int zt_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int zt_func_read (struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
static int zt_get_event (int fd)
 Avoid the silly zt_getevent which ignores a bunch of events.
static int zt_get_index (struct ast_channel *ast, struct zt_pvt *p, int nullok)
static void zt_handle_dtmfup (struct ast_channel *ast, int index, struct ast_frame **dest)
static struct ast_framezt_handle_event (struct ast_channel *ast)
static int zt_hangup (struct ast_channel *ast)
static int zt_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void zt_link (struct zt_pvt *slave, struct zt_pvt *master)
static struct ast_channelzt_new (struct zt_pvt *, int, int, int, int, int)
static int zt_open (char *fn)
static struct ast_framezt_read (struct ast_channel *ast)
static struct ast_channelzt_request (const char *type, int format, void *data, int *cause)
static int zt_ring_phone (struct zt_pvt *p)
static int zt_sendtext (struct ast_channel *c, const char *dest, const char *text, int ispdu)
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)

300 ms

Definition at line 291 of file chan_zap.c.

Referenced by zt_callwait().

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

300 ms

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

Referenced by zt_handle_event(), and zt_new().

#define CHAN_PSEUDO   -2

#define CHANNEL_PSEUDO   -12

Definition at line 162 of file chan_zap.c.

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

500 ms

Definition at line 292 of file chan_zap.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 455 of file chan_zap.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 456 of file chan_zap.c.

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 213 of file chan_zap.c.

Referenced by mkintf().

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 210 of file chan_zap.c.

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 209 of file chan_zap.c.

#define DCHAN_UP   (1 << 2)

Definition at line 211 of file chan_zap.c.

Referenced by zt_devicestate().

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

Referenced by zt_chan_conf_default().

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

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

Referenced by update_conf().

#define HANGUP   1

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

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_zap().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 205 of file chan_zap.c.

Referenced by mkintf().

#define MAX_SLAVES   4

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

Referenced by ss_thread(), and zt_new().

#define NUM_CADENCE_MAX   25

Definition at line 808 of file chan_zap.c.

Referenced by process_zap().

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 204 of file chan_zap.c.

Referenced by zt_devicestate().

#define NUM_SPANS   128

"32 spans", muahahaha, us alaws like to have some more...

Definition at line 203 of file chan_zap.c.

#define POLARITY_IDLE   0

Definition at line 412 of file chan_zap.c.

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

#define POLARITY_REV   1

Definition at line 413 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 285 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 200 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 201 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 116 of file chan_zap.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 408 of file chan_zap.c.

#define SUB_REAL   0

Active call

Definition at line 407 of file chan_zap.c.

#define SUB_THREEWAY   2

Three-way call

Definition at line 409 of file chan_zap.c.

#define tdesc   "Zapata Telephony"

Definition at line 13391 of file chan_zap.c.

#define TRAILER_MS   5

Referenced by zt_tdd_sendtext().

#define TRANSFER   0

Definition at line 11959 of file chan_zap.c.

Referenced by action_transfer(), and zap_fake_event().

#define ZT_EVENT_DTMFDOWN   0

Definition at line 134 of file chan_zap.c.

Referenced by zt_handle_event().

#define ZT_EVENT_DTMFUP   0

Definition at line 135 of file chan_zap.c.

Referenced by zt_handle_event().


Function Documentation

static int __unload_module ( void   )  [static]

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

12142 {
12143    int x;
12144    struct zt_pvt *p, *pl;
12145 
12146 #ifdef HAVE_PRI
12147    int i;
12148    for (i = 0; i < NUM_SPANS; i++) {
12149       if (pris[i].master != AST_PTHREADT_NULL) 
12150          pthread_cancel(pris[i].master);
12151    }
12152    ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
12153    ast_unregister_application(zap_send_keypad_facility_app);
12154    ast_unregister_application(zapCD_app);
12155    ast_unregister_application(zapInband_app);
12156 #endif
12157 #ifdef HAVE_GSMAT
12158    ast_cli_unregister_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
12159    ast_cli_unregister(&gsm_send_sms);
12160    ast_cli_unregister(&gsm_send_pdu);
12161    ast_cli_unregister(&gsm_show_status);
12162 #endif
12163    ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
12164    ast_unregister_application(zapEC_app);
12165    ast_manager_unregister( "ZapDialOffhook" );
12166    ast_manager_unregister( "ZapHangup" );
12167    ast_manager_unregister( "ZapTransfer" );
12168    ast_manager_unregister( "ZapDNDoff" );
12169    ast_manager_unregister( "ZapDNDon" );
12170    ast_manager_unregister("ZapShowChannels");
12171    ast_manager_unregister("ZapRestart");
12172    ast_channel_unregister(&zap_tech);
12173    ast_mutex_lock(&iflock);
12174    /* Hangup all interfaces if they have an owner */
12175    p = iflist;
12176    while (p) {
12177       if (p->owner)
12178          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12179       p = p->next;
12180    }
12181    ast_mutex_unlock(&iflock);
12182    ast_mutex_lock(&monlock);
12183    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12184       pthread_cancel(monitor_thread);
12185       pthread_kill(monitor_thread, SIGURG);
12186       pthread_join(monitor_thread, NULL);
12187    }
12188    monitor_thread = AST_PTHREADT_STOP;
12189    ast_mutex_unlock(&monlock);
12190 
12191    ast_mutex_lock(&iflock);
12192    /* Destroy all the interfaces and free their memory */
12193    p = iflist;
12194    while (p) {
12195       /* Free any callerid */
12196       if (p->cidspill)
12197          free(p->cidspill);
12198       /* Close the zapata thingy */
12199       if (p->subs[SUB_REAL].zfd > -1)
12200          zt_close(p->subs[SUB_REAL].zfd);
12201       pl = p;
12202       p = p->next;
12203       x = pl->channel;
12204       /* Free associated memory */
12205       if (pl)
12206          destroy_zt_pvt(&pl);
12207       ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
12208    }
12209    iflist = NULL;
12210    ifcount = 0;
12211    ast_mutex_unlock(&iflock);
12212 #ifdef HAVE_PRI      
12213    for (i = 0; i < NUM_SPANS; i++) {
12214       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12215          pthread_join(pris[i].master, NULL);
12216       zt_close(pris[i].fds[i]);
12217    }
12218 #endif
12219    return 0;
12220 }

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

Definition at line 4779 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_get_event(), zt_get_index(), zt_handle_event(), zt_ring_phone(), and zt_set_hook().

Referenced by zt_exception(), and zt_read().

04780 {
04781    struct zt_pvt *p = ast->tech_pvt;
04782    int res;
04783    int usedindex=-1;
04784    int index;
04785    struct ast_frame *f;
04786 
04787 
04788    index = zt_get_index(ast, p, 1);
04789    
04790    p->subs[index].f.frametype = AST_FRAME_NULL;
04791    p->subs[index].f.datalen = 0;
04792    p->subs[index].f.samples = 0;
04793    p->subs[index].f.mallocd = 0;
04794    p->subs[index].f.offset = 0;
04795    p->subs[index].f.subclass = 0;
04796    p->subs[index].f.delivery = ast_tv(0,0);
04797    p->subs[index].f.src = "zt_exception";
04798    p->subs[index].f.data = NULL;
04799    
04800    
04801    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04802       /* If nobody owns us, absorb the event appropriately, otherwise
04803          we loop indefinitely.  This occurs when, during call waiting, the
04804          other end hangs up our channel so that it no longer exists, but we
04805          have neither FLASH'd nor ONHOOK'd to signify our desire to
04806          change to the other channel. */
04807       if (p->fake_event) {
04808          res = p->fake_event;
04809          p->fake_event = 0;
04810       } else
04811          res = zt_get_event(p->subs[SUB_REAL].zfd);
04812       /* Switch to real if there is one and this isn't something really silly... */
04813       if ((res != ZT_EVENT_RINGEROFF) && (res != ZT_EVENT_RINGERON) &&
04814          (res != ZT_EVENT_HOOKCOMPLETE)) {
04815          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04816          p->owner = p->subs[SUB_REAL].owner;
04817          if (p->owner && ast_bridged_channel(p->owner))
04818             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04819          p->subs[SUB_REAL].needunhold = 1;
04820       }
04821       switch (res) {
04822       case ZT_EVENT_ONHOOK:
04823          zt_disable_ec(p);
04824          if (p->owner) {
04825             if (option_verbose > 2) 
04826                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
04827             zt_ring_phone(p);
04828             p->callwaitingrepeat = 0;
04829             p->cidcwexpire = 0;
04830          } else
04831             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04832          update_conf(p);
04833          break;
04834       case ZT_EVENT_RINGOFFHOOK:
04835          zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
04836          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
04837             p->subs[SUB_REAL].needanswer = 1;
04838             p->dialing = 0;
04839          }
04840          break;
04841       case ZT_EVENT_HOOKCOMPLETE:
04842       case ZT_EVENT_RINGERON:
04843       case ZT_EVENT_RINGEROFF:
04844          /* Do nothing */
04845          break;
04846       case ZT_EVENT_WINKFLASH:
04847          gettimeofday(&p->flashtime, NULL);
04848          if (p->owner) {
04849             if (option_verbose > 2) 
04850                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
04851             if (p->owner->_state != AST_STATE_UP) {
04852                /* Answer if necessary */
04853                usedindex = zt_get_index(p->owner, p, 0);
04854                if (usedindex > -1) {
04855                   p->subs[usedindex].needanswer = 1;
04856                }
04857                ast_setstate(p->owner, AST_STATE_UP);
04858             }
04859             p->callwaitingrepeat = 0;
04860             p->cidcwexpire = 0;
04861             if (ast_bridged_channel(p->owner))
04862                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04863             p->subs[SUB_REAL].needunhold = 1;
04864          } else
04865             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04866          update_conf(p);
04867          break;
04868       default:
04869          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
04870       }
04871       f = &p->subs[index].f;
04872       return f;
04873    }
04874    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
04875       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
04876    /* If it's not us, return NULL immediately */
04877    if (ast != p->owner) {
04878       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
04879       f = &p->subs[index].f;
04880       return f;
04881    }
04882    f = zt_handle_event(ast);
04883    return f;
04884 }

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

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

12029 {
12030    struct zt_pvt *p = NULL;
12031    const char *channel = astman_get_header(m, "ZapChannel");
12032 
12033    if (ast_strlen_zero(channel)) {
12034       astman_send_error(s, m, "No channel specified");
12035       return 0;
12036    }
12037    p = find_channel(atoi(channel));
12038    if (!p) {
12039       astman_send_error(s, m, "No such channel");
12040       return 0;
12041    }
12042    zap_fake_event(p,TRANSFER);
12043    astman_send_ack(s, m, "ZapTransfer");
12044    return 0;
12045 }

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

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

12048 {
12049    struct zt_pvt *p = NULL;
12050    const char *channel = astman_get_header(m, "ZapChannel");
12051 
12052    if (ast_strlen_zero(channel)) {
12053       astman_send_error(s, m, "No channel specified");
12054       return 0;
12055    }
12056    p = find_channel(atoi(channel));
12057    if (!p) {
12058       astman_send_error(s, m, "No such channel");
12059       return 0;
12060    }
12061    zap_fake_event(p,HANGUP);
12062    astman_send_ack(s, m, "ZapHangup");
12063    return 0;
12064 }

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

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

12067 {
12068    struct zt_pvt *p = NULL;
12069    const char *channel = astman_get_header(m, "ZapChannel");
12070    const char *number = astman_get_header(m, "Number");
12071    int i;
12072 
12073    if (ast_strlen_zero(channel)) {
12074       astman_send_error(s, m, "No channel specified");
12075       return 0;
12076    }
12077    if (ast_strlen_zero(number)) {
12078       astman_send_error(s, m, "No number specified");
12079       return 0;
12080    }
12081    p = find_channel(atoi(channel));
12082    if (!p) {
12083       astman_send_error(s, m, "No such channel");
12084       return 0;
12085    }
12086    if (!p->owner) {
12087       astman_send_error(s, m, "Channel does not have it's owner");
12088       return 0;
12089    }
12090    for (i = 0; i < strlen(number); i++) {
12091       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12092       zap_queue_frame(p, &f, NULL); 
12093    }
12094    astman_send_ack(s, m, "ZapDialOffhook");
12095    return 0;
12096 }

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

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

12010 {
12011    struct zt_pvt *p = NULL;
12012    const char *channel = astman_get_header(m, "ZapChannel");
12013 
12014    if (ast_strlen_zero(channel)) {
12015       astman_send_error(s, m, "No channel specified");
12016       return 0;
12017    }
12018    p = find_channel(atoi(channel));
12019    if (!p) {
12020       astman_send_error(s, m, "No such channel");
12021       return 0;
12022    }
12023    p->dnd = 0;
12024    astman_send_ack(s, m, "DND Disabled");
12025    return 0;
12026 }

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

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

11991 {
11992    struct zt_pvt *p = NULL;
11993    const char *channel = astman_get_header(m, "ZapChannel");
11994 
11995    if (ast_strlen_zero(channel)) {
11996       astman_send_error(s, m, "No channel specified");
11997       return 0;
11998    }
11999    p = find_channel(atoi(channel));
12000    if (!p) {
12001       astman_send_error(s, m, "No such channel");
12002       return 0;
12003    }
12004    p->dnd = 1;
12005    astman_send_ack(s, m, "DND Enabled");
12006    return 0;
12007 }

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

Definition at line 11617 of file chan_zap.c.

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

Referenced by load_module().

11618 {
11619    if (zap_restart() != 0) {
11620       astman_send_error(s, m, "Failed rereading zaptel configuration");
11621       return 1;
11622    }
11623    astman_send_ack(s, m, "ZapRestart: Success");
11624    return 0;
11625 }

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

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

12099 {
12100    struct zt_pvt *tmp = NULL;
12101    const char *id = astman_get_header(m, "ActionID");
12102    char idText[256] = "";
12103 
12104    astman_send_ack(s, m, "Zapata channel status will follow");
12105    if (!ast_strlen_zero(id))
12106       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12107 
12108    ast_mutex_lock(&iflock);
12109    
12110    tmp = iflist;
12111    while (tmp) {
12112       if (tmp->channel > 0) {
12113          int alarm = get_alarms(tmp);
12114          astman_append(s,
12115             "Event: ZapShowChannels\r\n"
12116             "Channel: %d\r\n"
12117             "Signalling: %s\r\n"
12118             "Context: %s\r\n"
12119             "DND: %s\r\n"
12120             "Alarm: %s\r\n"
12121             "%s"
12122             "\r\n",
12123             tmp->channel, sig2str(tmp->sig), tmp->context, 
12124             tmp->dnd ? "Enabled" : "Disabled",
12125             alarm2str(alarm), idText);
12126       } 
12127 
12128       tmp = tmp->next;
12129    }
12130 
12131    ast_mutex_unlock(&iflock);
12132    
12133    astman_append(s, 
12134       "Event: ZapShowChannelsComplete\r\n"
12135       "%s"
12136       "\r\n", 
12137       idText);
12138    return 0;
12139 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1315 of file chan_zap.c.

References alarms.

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

01316 {
01317    int x;
01318    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01319       if (alarms[x].alarm & alarm)
01320          return alarms[x].name;
01321    }
01322    return alarm ? "Unknown Alarm" : "No Alarm";
01323 }

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

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

01114 {
01115    ZT_BUFFERINFO bi;
01116    int res;
01117    if (p->subs[x].zfd < 0) {
01118       p->subs[x].zfd = zt_open("/dev/zap/pseudo");
01119       if (p->subs[x].zfd > -1) {
01120          res = ioctl(p->subs[x].zfd, ZT_GET_BUFINFO, &bi);
01121          if (!res) {
01122             bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
01123             bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
01124             bi.numbufs = numbufs;
01125             res = ioctl(p->subs[x].zfd, ZT_SET_BUFINFO, &bi);
01126             if (res < 0) {
01127                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", x);
01128             }
01129          } else 
01130             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", x);
01131          if (ioctl(p->subs[x].zfd, ZT_CHANNO, &p->subs[x].chan) == 1) {
01132             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d\n", p->subs[x].zfd);
01133             zt_close(p->subs[x].zfd);
01134             p->subs[x].zfd = -1;
01135             return -1;
01136          }
01137          if (option_debug)
01138             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
01139          return 0;
01140       } else
01141          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01142       return -1;
01143    }
01144    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01145    return -1;
01146 }

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

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

11537 {
11538  int res=-1;
11539  struct zt_pvt *p = NULL;
11540 
11541  if (!data) {
11542    ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
11543  }
11544  if (chan && !strcasecmp("ZAP",chan->tech->type)) {
11545    p = chan->tech_pvt;
11546    if (!p) return res;
11547    if (!strcasecmp("on",(char *)data)) {
11548        zt_enable_ec(p);
11549        res = 0;
11550        if (option_verbose > 3) {
11551       ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
11552        }
11553    } else if (!strcasecmp("off",(char *)data)) {
11554        zt_disable_ec(p);
11555        res = 0;
11556        if (option_verbose > 3) {
11557       ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
11558        }
11559    } else {
11560        ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
11561    }
11562  } else {
11563   ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
11564   res = 0;
11565  }
11566 
11567  return res;
11568 }

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

03778 {
03779    /* In order to transfer, we need at least one of the channels to
03780       actually be in a call bridge.  We can't conference two applications
03781       together (but then, why would we want to?) */
03782    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03783       /* The three-way person we're about to transfer to could still be in MOH, so
03784          stop if now if appropriate */
03785       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03786          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03787       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03788          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03789       }
03790       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03791          tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, ZT_TONE_RINGTONE);
03792       }
03793       if (p->subs[SUB_REAL].owner->cdr) {
03794          /* Move CDR from second channel to current one */
03795          p->subs[SUB_THREEWAY].owner->cdr =
03796             ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr);
03797          p->subs[SUB_REAL].owner->cdr = NULL;
03798       }
03799       if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) {
03800          /* Move CDR from second channel's bridge to current one */
03801          p->subs[SUB_THREEWAY].owner->cdr =
03802             ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr);
03803          ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL;
03804       }
03805        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03806          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03807                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03808          return -1;
03809       }
03810       /* Orphan the channel after releasing the lock */
03811       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03812       unalloc_sub(p, SUB_THREEWAY);
03813    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03814       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03815       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03816          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03817       }
03818       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03819          tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
03820       }
03821       if (p->subs[SUB_THREEWAY].owner->cdr) {
03822          /* Move CDR from second channel to current one */
03823          p->subs[SUB_REAL].owner->cdr = 
03824             ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr);
03825          p->subs[SUB_THREEWAY].owner->cdr = NULL;
03826       }
03827       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) {
03828          /* Move CDR from second channel's bridge to current one */
03829          p->subs[SUB_REAL].owner->cdr = 
03830             ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr);
03831          ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL;
03832       }
03833       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03834          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03835                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03836          return -1;
03837       }
03838       /* Three-way is now the REAL */
03839       swap_subs(p, SUB_THREEWAY, SUB_REAL);
03840       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03841       unalloc_sub(p, SUB_THREEWAY);
03842       /* Tell the caller not to hangup */
03843       return 1;
03844    } else {
03845       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03846                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03847       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03848       return -1;
03849    }
03850    return 0;
03851 }

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

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

07951 {
07952    int res;
07953    ZT_PARAMS par;
07954 
07955    /* First, check group matching */
07956    if (groupmatch) {
07957       if ((p->group & groupmatch) != groupmatch)
07958          return 0;
07959       *groupmatched = 1;
07960    }
07961    /* Check to see if we have a channel match */
07962    if (channelmatch != -1) {
07963       if (p->channel != channelmatch)
07964          return 0;
07965       *channelmatched = 1;
07966    }
07967    /* We're at least busy at this point */
07968    if (busy) {
07969       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07970          *busy = 1;
07971    }
07972    /* If do not disturb, definitely not */
07973    if (p->dnd)
07974       return 0;
07975    /* If guard time, definitely not */
07976    if (p->guardtime && (time(NULL) < p->guardtime)) 
07977       return 0;
07978       
07979    /* If no owner definitely available */
07980    if (!p->owner) {
07981 #ifdef HAVE_PRI
07982       /* Trust PRI */
07983       if (p->pri) {
07984          if (p->resetting || p->call)
07985             return 0;
07986          else
07987             return 1;
07988       }
07989 #endif
07990 #ifdef HAVE_GSMAT
07991       if (p->gsm.modul) {
07992           return gsm_available(p->gsm.modul);
07993       }
07994 
07995 #endif
07996       if (!(p->radio || (p->oprmode < 0)))
07997       {
07998          if (!p->sig || (p->sig == SIG_FXSLS))
07999             return 1;
08000          /* Check hook state */
08001          if (p->subs[SUB_REAL].zfd > -1)
08002             res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
08003          else {
08004             /* Assume not off hook on CVRS */
08005             res = 0;
08006             par.rxisoffhook = 0;
08007          }
08008          if (res) {
08009             ast_log(LOG_WARNING, "Unable to check hook state on channel %d\n", p->channel);
08010          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
08011             /* When "onhook" that means no battery on the line, and thus
08012               it is out of service..., if it's on a TDM card... If it's a channel
08013               bank, there is no telling... */
08014             if (par.rxbits > -1)
08015                return 1;
08016             if (par.rxisoffhook)
08017                return 1;
08018             else
08019 #ifdef ZAP_CHECK_HOOKSTATE
08020                return 0;
08021 #else
08022                return 1;
08023 #endif
08024          } else if (par.rxisoffhook) {
08025             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
08026             /* Not available when the other end is off hook */
08027             return 0;
08028          }
08029       }
08030       return 1;
08031    }
08032 
08033    /* If it's not an FXO, forget about call wait */
08034    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
08035       return 0;
08036 
08037    if (!p->callwaiting) {
08038       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
08039       return 0;
08040    }
08041 
08042    if (p->subs[SUB_CALLWAIT].zfd > -1) {
08043       /* If there is already a call waiting call, then we can't take a second one */
08044       return 0;
08045    }
08046    
08047    if ((p->owner->_state != AST_STATE_UP) &&
08048        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
08049       /* If the current call is not up, then don't allow the call */
08050       return 0;
08051    }
08052    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
08053       /* Can't take a call wait when the three way calling hasn't been merged yet. */
08054       return 0;
08055    }
08056    /* We're cool */
08057    return 1;
08058 }

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

12233 {
12234    char *c, *chan;
12235    int x, start, finish;
12236    struct zt_pvt *tmp;
12237 #ifdef HAVE_PRI
12238    struct zt_pri *pri;
12239    int trunkgroup, y;
12240 #endif
12241    
12242    if ((reload == 0) && (conf.chan.sig < 0)) {
12243       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12244       return -1;
12245    }
12246 
12247    c = ast_strdupa(value);
12248 
12249 #ifdef HAVE_PRI
12250    pri = NULL;
12251    if (iscrv) {
12252       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
12253          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12254          return -1;
12255       }
12256       if (trunkgroup < 1) {
12257          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12258          return -1;
12259       }
12260       c += y;
12261       for (y = 0; y < NUM_SPANS; y++) {
12262          if (pris[y].trunkgroup == trunkgroup) {
12263             pri = pris + y;
12264             break;
12265          }
12266       }
12267       if (!pri) {
12268          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12269          return -1;
12270       }
12271    }
12272 #endif         
12273 
12274    while ((chan = strsep(&c, ","))) {
12275       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
12276          /* Range */
12277       } else if (sscanf(chan, "%d", &start)) {
12278          /* Just one */
12279          finish = start;
12280       } else if (!strcasecmp(chan, "pseudo")) {
12281          finish = start = CHAN_PSEUDO;
12282          if (found_pseudo)
12283             *found_pseudo = 1;
12284       } else {
12285          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12286          return -1;
12287       }
12288       if (finish < start) {
12289          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12290          x = finish;
12291          finish = start;
12292          start = x;
12293       }
12294 
12295       for (x = start; x <= finish; x++) {
12296 #ifdef HAVE_PRI
12297          tmp = mkintf(x, conf, pri, reload);
12298 #else       
12299          tmp = mkintf(x, conf, NULL, reload);
12300 #endif         
12301 
12302          if (tmp) {
12303             if (option_verbose > 2) {
12304 #ifdef HAVE_PRI
12305                if (pri)
12306                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12307                else
12308 #endif
12309                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12310             }
12311          } else {
12312             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12313                (reload == 1) ? "reconfigure" : "register", value);
12314             return -1;
12315          }
12316       }
12317    }
12318 
12319    return 0;
12320 }

static int bump_gains ( struct zt_pvt p  )  [static]

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

01773 {
01774    int res;
01775 
01776    /* Bump receive gain by 5.0db */
01777    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01778    if (res) {
01779       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01780       return -1;
01781    }
01782 
01783    return 0;
01784 }

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

Definition at line 8060 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, zt_pvt::next, SUB_REAL, zt_pvt::subs, zt_subchannel::zfd, and zt_open().

Referenced by zt_request().

08061 {
08062    struct zt_pvt *p;
08063    ZT_BUFFERINFO bi;
08064    int res;
08065    
08066    if ((p = ast_malloc(sizeof(*p)))) {
08067       memcpy(p, src, sizeof(struct zt_pvt));
08068       ast_mutex_init(&p->lock);
08069       p->subs[SUB_REAL].zfd = zt_open("/dev/zap/pseudo");
08070       /* Allocate a zapata structure */
08071       if (p->subs[SUB_REAL].zfd < 0) {
08072          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
08073          destroy_zt_pvt(&p);
08074          return NULL;
08075       }
08076       res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
08077       if (!res) {
08078          bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
08079          bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
08080          bi.numbufs = numbufs;
08081          res = ioctl(p->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
08082          if (res < 0) {
08083             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel\n");
08084          }
08085       } else
08086          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel\n");
08087    }
08088    p->destroy = 1;
08089    p->next = iflist;
08090    iflist = p;
08091    return p;
08092 }

static int check_for_conference ( struct zt_pvt p  )  [static]

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

03854 {
03855    ZT_CONFINFO ci;
03856    /* Fine if we already have a master, etc */
03857    if (p->master || (p->confno > -1))
03858       return 0;
03859    memset(&ci, 0, sizeof(ci));
03860    if (ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
03861       ast_log(LOG_WARNING, "Failed to get conference info on channel %d\n", p->channel);
03862       return 0;
03863    }
03864    /* If we have no master and don't have a confno, then 
03865       if we're in a conference, it's probably a MeetMe room or
03866       some such, so don't let us 3-way out! */
03867    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03868       if (option_verbose > 2) 
03869          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03870       return 1;
03871    }
03872    return 0;
03873 }

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

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

01409 {
01410    /* If the conference already exists, and we're already in it
01411       don't bother doing anything */
01412    ZT_CONFINFO zi;
01413    
01414    memset(&zi, 0, sizeof(zi));
01415    zi.chan = 0;
01416 
01417    if (slavechannel > 0) {
01418       /* If we have only one slave, do a digital mon */
01419       zi.confmode = ZT_CONF_DIGITALMON;
01420       zi.confno = slavechannel;
01421    } else {
01422       if (!index) {
01423          /* Real-side and pseudo-side both participate in conference */
01424          zi.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER |
01425             ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
01426       } else
01427          zi.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
01428       zi.confno = p->confno;
01429    }
01430    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01431       return 0;
01432    if (c->zfd < 0)
01433       return 0;
01434    if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
01435       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d\n", c->zfd, zi.confmode, zi.confno);
01436       return -1;
01437    }
01438    if (slavechannel < 1) {
01439       p->confno = zi.confno;
01440    }
01441    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01442    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01443    return 0;
01444 }

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

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

01458 {
01459    ZT_CONFINFO zi;
01460    if (/* Can't delete if there's no zfd */
01461       (c->zfd < 0) ||
01462       /* Don't delete from the conference if it's not our conference */
01463       !isourconf(p, c)
01464       /* Don't delete if we don't think it's conferenced at all (implied) */
01465       ) return 0;
01466    memset(&zi, 0, sizeof(zi));
01467    zi.chan = 0;
01468    zi.confno = 0;
01469    zi.confmode = 0;
01470    if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
01471       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01472       return -1;
01473    }
01474    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
01475    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01476    return 0;
01477 }

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

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

02447 {
02448    int owned = 0;
02449    int i = 0;
02450 
02451    if (!now) {
02452       if (cur->owner) {
02453          owned = 1;
02454       }
02455 
02456       for (i = 0; i < 3; i++) {
02457          if (cur->subs[i].owner) {
02458             owned = 1;
02459          }
02460       }
02461       if (!owned) {
02462          if (prev) {
02463             prev->next = cur->next;
02464             if (prev->next)
02465                prev->next->prev = prev;
02466             else
02467                ifend = prev;
02468          } else {
02469             iflist = cur->next;
02470             if (iflist)
02471                iflist->prev = NULL;
02472             else
02473                ifend = NULL;
02474          }
02475          if (cur->subs[SUB_REAL].zfd > -1) {
02476             zt_close(cur->subs[SUB_REAL].zfd);
02477          }
02478          destroy_zt_pvt(&cur);
02479       }
02480    } else {
02481       if (prev) {
02482          prev->next = cur->next;
02483          if (prev->next)
02484             prev->next->prev = prev;
02485          else
02486             ifend = prev;
02487       } else {
02488          iflist = cur->next;
02489          if (iflist)
02490             iflist->prev = NULL;
02491          else
02492             ifend = NULL;
02493       }
02494       if (cur->subs[SUB_REAL].zfd > -1) {
02495          zt_close(cur->subs[SUB_REAL].zfd);
02496       }
02497       destroy_zt_pvt(&cur);
02498    }
02499    return 0;
02500 }

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

Definition at line 2431 of file chan_zap.c.

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

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

02432 {
02433    struct zt_pvt *p = *pvt;
02434    /* Remove channel from the list */
02435    if (p->prev)
02436       p->prev->next = p->next;
02437    if (p->next)
02438       p->next->prev = p->prev;
02439    if (p->use_smdi)
02440       ASTOBJ_UNREF(p->smdi_iface, ast_smdi_interface_destroy);
02441    ast_mutex_destroy(&p->lock);
02442    free(p);
02443    *pvt = NULL;
02444 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1168 of file chan_zap.c.

Referenced by zt_digit_begin().

01169 {
01170    if (isdigit(digit))
01171       return ZT_TONE_DTMF_BASE + (digit - '0');
01172    else if (digit >= 'A' && digit <= 'D')
01173       return ZT_TONE_DTMF_A + (digit - 'A');
01174    else if (digit >= 'a' && digit <= 'd')
01175       return ZT_TONE_DTMF_A + (digit - 'a');
01176    else if (digit == '*')
01177       return ZT_TONE_DTMF_s;
01178    else if (digit == '#')
01179       return ZT_TONE_DTMF_p;
01180    else
01181       return -1;
01182 }

static void disable_dtmf_detect ( struct zt_pvt p  )  [static]

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

03379 {
03380 #ifdef ZT_TONEDETECT
03381    int val;
03382 #endif
03383 
03384    p->ignoredtmf = 1;
03385 
03386 #ifdef ZT_TONEDETECT
03387    val = 0;
03388    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03389 #endif      
03390    if (!p->hardwaredtmf && p->dsp) {
03391       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03392       ast_dsp_set_features(p->dsp, p->dsp_features);
03393    }
03394 }

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

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

07105 {
07106    int count, res, res2, spoint, pollres=0;
07107    struct zt_pvt *i;
07108    struct zt_pvt *last = NULL;
07109    time_t thispass = 0, lastpass = 0;
07110    int found;
07111    char buf[1024];
07112    struct pollfd *pfds=NULL;
07113    int lastalloc = -1;
07114    /* This thread monitors all the frame relay interfaces which are not yet in use
07115       (and thus do not have a separate thread) indefinitely */
07116    /* From here on out, we die whenever asked */
07117 #if 0
07118    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
07119       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
07120       return NULL;
07121    }
07122    ast_log(LOG_DEBUG, "Monitor starting...\n");
07123 #endif
07124    for (;;) {
07125       /* Lock the interface list */
07126       ast_mutex_lock(&iflock);
07127       if (!pfds || (lastalloc != ifcount)) {
07128          if (pfds) {
07129             free(pfds);
07130             pfds = NULL;
07131          }
07132          if (ifcount) {
07133             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
07134                ast_mutex_unlock(&iflock);
07135                return NULL;
07136             }
07137          }
07138          lastalloc = ifcount;
07139       }
07140       /* Build the stuff we're going to poll on, that is the socket of every
07141          zt_pvt that does not have an associated owner channel */
07142       count = 0;
07143       i = iflist;
07144       while (i) {
07145          if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
07146             if (!i->owner && !i->subs[SUB_REAL].owner) {
07147                /* This needs to be watched, as it lacks an owner */
07148                pfds[count].fd = i->subs[SUB_REAL].zfd;
07149                pfds[count].events = POLLPRI;
07150                pfds[count].revents = 0;
07151                /* Message waiting or r2 channels also get watched for reading */
07152                if (i->cidspill)
07153                   pfds[count].events |= POLLIN;
07154                count++;
07155             }
07156          }
07157          i = i->next;
07158       }
07159       /* Okay, now that we know what to do, release the interface lock */
07160       ast_mutex_unlock(&iflock);
07161       
07162       pthread_testcancel();
07163       /* Wait at least a second for something to happen */
07164       res = poll(pfds, count, 1000);
07165       pthread_testcancel();
07166       /* Okay, poll has finished.  Let's see what happened.  */
07167       if (res < 0) {
07168          if ((errno != EAGAIN) && (errno != EINTR))
07169             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07170          continue;
07171       }
07172       /* Alright, lock the interface list again, and let's look and see what has
07173          happened */
07174       ast_mutex_lock(&iflock);
07175       found = 0;
07176       spoint = 0;
07177       lastpass = thispass;
07178       thispass = time(NULL);
07179       i = iflist;
07180       while (i) {
07181          if (thispass != lastpass) {
07182             if (!found && ((i == last) || ((i == iflist) && !last))) {
07183                last = i;
07184                if (last) {
07185                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07186                      (last->sig & __ZT_SIG_FXO)) {
07187                      res = ast_app_has_voicemail(last->mailbox, NULL);
07188                      if (last->msgstate != res) {
07189                         int x;
07190                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07191                         x = ZT_FLUSH_BOTH;
07192                         res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
07193                         if (res2)
07194                            ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
07195                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07196                            /* Turn on on hook transfer for 4 seconds */
07197                            x = 4000;
07198                            ioctl(last->subs[SUB_REAL].zfd, ZT_ONHOOKTRANSFER, &x);
07199                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07200                            last->cidpos = 0;
07201                            last->msgstate = res;
07202                            last->onhooktime = thispass;
07203                         }
07204                         found ++;
07205                      }
07206                   }
07207                   last = last->next;
07208                }
07209             }
07210          }
07211          if ((i->subs[SUB_REAL].zfd > -1) && i->sig) {
07212             if (i->radio && !i->owner)
07213             {
07214                res = zt_get_event(i->subs[SUB_REAL].zfd);
07215                if (res)
07216                {
07217                   if (option_debug)
07218                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07219                   /* Don't hold iflock while handling init events */
07220                   ast_mutex_unlock(&iflock);
07221                   handle_init_event(i, res);
07222                   ast_mutex_lock(&iflock);   
07223                }
07224                i = i->next;
07225                continue;
07226             }              
07227             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint);
07228             if (pollres & POLLIN) {
07229                if (i->owner || i->subs[SUB_REAL].owner) {
07230 #ifdef HAVE_PRI
07231                   if (!i->pri)
07232 #endif                  
07233                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].zfd);
07234                   i = i->next;
07235                   continue;
07236                }
07237                if (!i->cidspill) {
07238                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
07239                   i = i->next;
07240                   continue;
07241                }
07242                res = read(i->subs[SUB_REAL].zfd, buf, sizeof(buf));
07243                if (res > 0) {
07244                   /* We read some number of bytes.  Write an equal amount of data */
07245                   if (res > i->cidlen - i->cidpos) 
07246                      res = i->cidlen - i->cidpos;
07247                   res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
07248                   if (res2 > 0) {
07249                      i->cidpos += res2;
07250                      if (i->cidpos >= i->cidlen) {
07251                         free(i->cidspill);
07252                         i->cidspill = 0;
07253                         i->cidpos = 0;
07254                         i->cidlen = 0;
07255                      }
07256                   } else {
07257                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07258                      i->msgstate = -1;
07259                   }
07260                } else {
07261                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07262                }
07263                if (option_debug)
07264                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07265                /* Don't hold iflock while handling init events -- race with chlock */
07266                ast_mutex_unlock(&iflock);
07267                handle_init_event(i, res);
07268                ast_mutex_lock(&iflock);   
07269             }
07270             if (pollres & POLLPRI) {
07271                if (i->owner || i->subs[SUB_REAL].owner) {
07272 #ifdef HAVE_PRI
07273                   if (!i->pri)
07274 #endif                  
07275                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].zfd);
07276                   i = i->next;
07277                   continue;
07278                }
07279                res = zt_get_event(i->subs[SUB_REAL].zfd);
07280                if (option_debug)
07281                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07282                /* Don't hold iflock while handling init events */
07283                ast_mutex_unlock(&iflock);
07284                handle_init_event(i, res);
07285                ast_mutex_lock(&iflock);   
07286             }
07287          }
07288          i=i->next;
07289       }
07290       ast_mutex_unlock(&iflock);
07291    }
07292    /* Never reached */
07293    return NULL;
07294    
07295 }

static void enable_dtmf_detect ( struct zt_pvt p  )  [static]

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

03397 {
03398 #ifdef ZT_TONEDETECT
03399    int val;
03400 #endif
03401 
03402    if (p->channel == CHAN_PSEUDO)
03403       return;
03404 
03405    p->ignoredtmf = 0;
03406 
03407 #ifdef ZT_TONEDETECT
03408    val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
03409    ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
03410 #endif      
03411    if (!p->hardwaredtmf && p->dsp) {
03412       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03413       ast_dsp_set_features(p->dsp, p->dsp_features);
03414    }
03415 }

static char* event2str ( int  event  )  [static]

Definition at line 1325 of file chan_zap.c.

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

01326 {
01327    static char buf[256];
01328    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01329       return events[event];
01330    sprintf(buf, "Event %d", event); /* safe */
01331    return buf;
01332 }

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

Definition at line 1696 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

01697 {
01698    int j;
01699    int k;
01700    float linear_gain = pow(10.0, gain / 20.0);
01701 
01702    switch (law) {
01703    case ZT_LAW_ALAW:
01704       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01705          if (gain) {
01706             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01707             if (k > 32767) k = 32767;
01708             if (k < -32767) k = -32767;
01709             g->rxgain[j] = AST_LIN2A(k);
01710          } else {
01711             g->rxgain[j] = j;
01712          }
01713       }
01714       break;
01715    case ZT_LAW_MULAW:
01716       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01717          if (gain) {
01718             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01719             if (k > 32767) k = 32767;
01720             if (k < -32767) k = -32767;
01721             g->rxgain[j] = AST_LIN2MU(k);
01722          } else {
01723             g->rxgain[j] = j;
01724          }
01725       }
01726       break;
01727    }
01728 }

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

Definition at line 1662 of file chan_zap.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

01663 {
01664    int j;
01665    int k;
01666    float linear_gain = pow(10.0, gain / 20.0);
01667 
01668    switch (law) {
01669    case ZT_LAW_ALAW:
01670       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01671          if (gain) {
01672             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01673             if (k > 32767) k = 32767;
01674             if (k < -32767) k = -32767;
01675             g->txgain[j] = AST_LIN2A(k);
01676          } else {
01677             g->txgain[j] = j;
01678          }
01679       }
01680       break;
01681    case ZT_LAW_MULAW:
01682       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01683          if (gain) {
01684             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01685             if (k > 32767) k = 32767;
01686             if (k < -32767) k = -32767;
01687             g->txgain[j] = AST_LIN2MU(k);
01688          } else {
01689             g->txgain[j] = j;
01690          }
01691       }
01692       break;
01693    }
01694 }

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

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

11979 {
11980    struct zt_pvt *p = iflist;
11981    while (p) {
11982       if (p->channel == channel) {
11983          break;
11984       }
11985       p = p->next;
11986    }
11987    return p;
11988 }

static int get_alarms ( struct zt_pvt p  )  [static]

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

03876 {
03877    int res;
03878    ZT_SPANINFO zi;
03879    memset(&zi, 0, sizeof(zi));
03880    zi.spanno = p->span;
03881    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SPANSTAT, &zi);
03882    if (res < 0) {
03883       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03884       return 0;
03885    }
03886    return zi.alarms;
03887 }

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

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

06869 {
06870    int res;
06871    pthread_t threadid;
06872    pthread_attr_t attr;
06873    struct ast_channel *chan;
06874    pthread_attr_init(&attr);
06875    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06876    /* Handle an event on a given channel for the monitor thread. */
06877    switch (event) {
06878    case ZT_EVENT_NONE:
06879    case ZT_EVENT_BITSCHANGED:
06880       break;
06881    case ZT_EVENT_WINKFLASH:
06882    case ZT_EVENT_RINGOFFHOOK:
06883       if (i->inalarm) break;
06884       if (i->radio) break;
06885       /* Got a ring/answer.  What kind of channel are we? */
06886       switch (i->sig) {
06887       case SIG_FXOLS:
06888       case SIG_FXOGS:
06889       case SIG_FXOKS:
06890          res = zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
06891          if (res && (errno == EBUSY))
06892             break;
06893          if (i->cidspill) {
06894             /* Cancel VMWI spill */
06895             free(i->cidspill);
06896             i->cidspill = NULL;
06897          }
06898          if (i->immediate) {
06899             zt_enable_ec(i);
06900             /* The channel is immediately up.  Start right away */
06901             res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
06902             chan = zt_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06903             if (!chan) {
06904                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06905                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06906                if (res < 0)
06907                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06908             }
06909          } else {
06910             /* Check for callerid, digits, etc */
06911             chan = zt_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06912             if (chan) {
06913                if (has_voicemail(i))
06914                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_STUTTER);
06915                else
06916                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
06917                if (res < 0) 
06918                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06919                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06920                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06921                   res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06922                   if (res < 0)
06923                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06924                   ast_hangup(chan);
06925                }
06926             } else
06927                ast_log(LOG_WARNING, "Unable to create channel\n");
06928          }
06929          break;
06930       case SIG_FXSLS:
06931       case SIG_FXSGS:
06932       case SIG_FXSKS:
06933             i->ringt = i->ringt_base;
06934             /* Fall through */
06935       case SIG_EMWINK:
06936       case SIG_FEATD:
06937       case SIG_FEATDMF:
06938       case SIG_FEATDMF_TA:
06939       case SIG_E911:
06940       case SIG_FGC_CAMA:
06941       case SIG_FGC_CAMAMF:
06942       case SIG_FEATB:
06943       case SIG_EM:
06944       case SIG_EM_E1:
06945       case SIG_SFWINK:
06946       case SIG_SF_FEATD:
06947       case SIG_SF_FEATDMF:
06948       case SIG_SF_FEATB:
06949       case SIG_SF:
06950             /* Check for callerid, digits, etc */
06951             chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06952             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06953                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06954                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06955                if (res < 0)
06956                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06957                ast_hangup(chan);
06958             } else if (!chan) {
06959                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06960             }
06961             break;
06962       default:
06963          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06964          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
06965          if (res < 0)
06966                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06967          return -1;
06968       }
06969       break;
06970    case ZT_EVENT_NOALARM:
06971       i->inalarm = 0;
06972 #ifdef HAVE_PRI
06973       if (i->pri) {
06974           if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
06975          /* dont annoy BRI TE mode users with layer2layer alarms */
06976           } else {
06977          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06978          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06979                     "Channel: %d\r\n", i->channel);
06980           }
06981       }
06982 #else
06983       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06984       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06985          "Channel: %d\r\n", i->channel);
06986 #endif
06987       break;
06988    case ZT_EVENT_ALARM:
06989       i->inalarm = 1;
06990       res = get_alarms(i);
06991 #ifdef HAVE_PRI
06992       if (i->pri) {
06993           if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
06994          /* dont annoy BRI TE mode users with layer2layer alarms */
06995           } else {
06996          ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
06997          manager_event(EVENT_FLAG_SYSTEM, "Alarm",
06998                     "Alarm: %s\r\n"
06999                     "Channel: %d\r\n",
07000                     alarm2str(res), i->channel);
07001           }
07002       }
07003 #else
07004       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
07005       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07006          "Alarm: %s\r\n"
07007          "Channel: %d\r\n",
07008          alarm2str(res), i->channel);
07009 #endif
07010       /* fall thru intentionally */
07011    case ZT_EVENT_ONHOOK:
07012       if (i->radio)
07013          break;
07014       /* Back on hook.  Hang up. */
07015       switch (i->sig) {
07016       case SIG_FXOLS:
07017       case SIG_FXOGS:
07018       case SIG_FEATD:
07019       case SIG_FEATDMF:
07020       case SIG_FEATDMF_TA:
07021       case SIG_E911:
07022       case SIG_FGC_CAMA:
07023       case SIG_FGC_CAMAMF:
07024       case SIG_FEATB:
07025       case SIG_EM:
07026       case SIG_EM_E1:
07027       case SIG_EMWINK:
07028       case SIG_SF_FEATD:
07029       case SIG_SF_FEATDMF:
07030       case SIG_SF_FEATB:
07031       case SIG_SF:
07032       case SIG_SFWINK:
07033       case SIG_FXSLS:
07034       case SIG_FXSGS:
07035       case SIG_FXSKS:
07036       case SIG_GR303FXSKS:
07037          zt_disable_ec(i);
07038          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
07039          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
07040          break;
07041       case SIG_GR303FXOKS:
07042       case SIG_FXOKS:
07043          zt_disable_ec(i);
07044          /* Diddle the battery for the zhone */
07045 #ifdef ZHONE_HACK
07046          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
07047          usleep(1);
07048 #endif         
07049          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
07050          zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
07051          break;
07052       case SIG_PRI:
07053          if (event != ZT_EVENT_ALARM) {
07054              zt_disable_ec(i);
07055              res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
07056          }
07057          break;
07058       default:
07059          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07060          res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
07061          return -1;
07062       }
07063       break;
07064    case ZT_EVENT_POLARITY:
07065       switch (i->sig) {
07066       case SIG_FXSLS:
07067       case SIG_FXSKS:
07068       case SIG_FXSGS:
07069          /* We have already got a PR before the channel was 
07070             created, but it wasn't handled. We need polarity 
07071             to be REV for remote hangup detection to work. 
07072             At least in Spain */
07073          if (i->hanguponpolarityswitch)
07074             i->polarity = POLARITY_REV;
07075 
07076          if (i->cid_start == CID_START_POLARITY) {
07077             i->polarity = POLARITY_REV;
07078             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
07079                    "CID detection on channel %d\n",
07080                    i->channel);
07081             chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
07082             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07083                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07084             }
07085          }
07086          break;
07087       default:
07088          ast_log(LOG_WARNING, "handle_init_event detected "
07089             "polarity reversal on non-FXO (SIG_FXS) "
07090             "interface %d\n", i->channel);
07091       }
07092       break;
07093    case ZT_EVENT_REMOVED: /* destroy channel */
07094       ast_log(LOG_NOTICE, 
07095             "Got ZT_EVENT_REMOVED. Destroying channel %d\n", 
07096             i->channel);
07097       zap_destroy_channel_bynum(i->channel);
07098       break;
07099    }
07100    pthread_attr_destroy(&attr);
07101    return 0;
07102 }

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

Definition at line 11822 of file chan_zap.c.

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

11823 {
11824    int i, j;
11825    for (i = 0; i < num_cadence; i++) {
11826       char output[1024];
11827       char tmp[16], tmp2[64];
11828       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
11829       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
11830 
11831       for (j = 0; j < 16; j++) {
11832          if (cadences[i].ringcadence[j] == 0)
11833             break;
11834          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
11835          if (cidrings[i] * 2 - 1 == j)
11836             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
11837          else
11838             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
11839          if (j != 0)
11840             strncat(output, ",", sizeof(output) - strlen(output) - 1);
11841          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
11842       }
11843       ast_cli(fd,"%s\n",output);
11844    }
11845    return 0;
11846 }

static int has_voicemail ( struct zt_pvt p  )  [static]

Definition at line 1893 of file chan_zap.c.

References ast_app_has_voicemail(), and zt_pvt::mailbox.

01894 {
01895 
01896    return ast_app_has_voicemail(p->mailbox, NULL);
01897 }

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

Definition at line 1446 of file chan_zap.c.

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

Referenced by conf_del().

01447 {
01448    /* If they're listening to our channel, they're ours */  
01449    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == ZT_CONF_DIGITALMON))
01450       return 1;
01451    /* If they're a talker on our (allocated) conference, they're ours */
01452    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & ZT_CONF_TALKER))
01453       return 1;
01454    return 0;
01455 }

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

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

01480 {
01481    int x;
01482    int useslavenative;
01483    struct zt_pvt *slave = NULL;
01484    /* Start out optimistic */
01485    useslavenative = 1;
01486    /* Update conference state in a stateless fashion */
01487    for (x = 0; x < 3; x++) {
01488       /* Any three-way calling makes slave native mode *definitely* out
01489          of the question */
01490       if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway)
01491          useslavenative = 0;
01492    }
01493    /* If we don't have any 3-way calls, check to see if we have
01494       precisely one slave */
01495    if (useslavenative) {
01496       for (x = 0; x < MAX_SLAVES; x++) {
01497          if (p->slaves[x]) {
01498             if (slave) {
01499                /* Whoops already have a slave!  No 
01500                   slave native and stop right away */
01501                slave = NULL;
01502                useslavenative = 0;
01503                break;
01504             } else {
01505                /* We have one slave so far */
01506                slave = p->slaves[x];
01507             }
01508          }
01509       }
01510    }
01511    /* If no slave, slave native definitely out */
01512    if (!slave)
01513       useslavenative = 0;
01514    else if (slave->law != p->law) {
01515       useslavenative = 0;
01516       slave = NULL;
01517    }
01518    if (out)
01519       *out = slave;
01520    return useslavenative;
01521 }

static int load_module ( void   )  [static]

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

13170 {
13171    int res;
13172 
13173 #ifdef HAVE_PRI
13174    int y,i;
13175    memset(pris, 0, sizeof(pris));
13176    for (y = 0; y < NUM_SPANS; y++) {
13177       ast_mutex_init(&pris[y].lock);
13178       pris[y].offset = -1;
13179       pris[y].master = AST_PTHREADT_NULL;
13180       for (i = 0; i < NUM_DCHANS; i++)
13181          pris[y].fds[i] = -1;
13182    }
13183    pri_set_error(zt_pri_error);
13184    pri_set_message(zt_pri_message);
13185    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13186          zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13187 #endif
13188 #ifdef HAVE_GSMAT
13189    gsm_set_error(zt_gsm_error);
13190    gsm_set_message(zt_gsm_message);
13191 #endif
13192    res = setup_zap(0);
13193    /* Make sure we can register our Zap channel type */
13194    if (res)
13195       return AST_MODULE_LOAD_DECLINE;
13196    if (ast_channel_register(&zap_tech)) {
13197       ast_log(LOG_ERROR, "Unable to register channel class 'Zap'\n");
13198       __unload_module();
13199       return -1;
13200    }
13201 #ifdef HAVE_PRI
13202    ast_string_field_init(&inuse, 16);
13203    ast_string_field_set(&inuse, name, "GR-303InUse");
13204    ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
13205    ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
13206         ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
13207 #endif   
13208    ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
13209    ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
13210 #ifdef HAVE_GSMAT
13211    ast_cli_register(&gsm_send_sms);
13212    ast_cli_register(&gsm_send_pdu);
13213    ast_cli_register(&gsm_show_status);
13214    ast_cli_register_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
13215 #endif
13216    
13217    memset(round_robin, 0, sizeof(round_robin));
13218    ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
13219    ast_manager_register( "ZapHangup", 0, action_transferhangup, "Hangup Zap Channel" );
13220    ast_manager_register( "ZapDialOffhook", 0, action_zapdialoffhook, "Dial over Zap channel while offhook" );
13221    ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
13222    ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
13223    ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
13224    ast_manager_register("ZapRestart", 0, action_zaprestart, "Fully Restart zaptel channels (terminates calls)");
13225 
13226    return res;
13227 }

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

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

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

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

Definition at line 5654 of file chan_zap.c.

References ast_waitfordigit().

Referenced by ss_thread().

05655 {
05656    char c;
05657 
05658    *str = 0; /* start with empty output buffer */
05659    for (;;)
05660    {
05661       /* Wait for the first digit (up to specified ms). */
05662       c = ast_waitfordigit(chan, ms);
05663       /* if timeout, hangup or error, return as such */
05664       if (c < 1)
05665          return c;
05666       *str++ = c;
05667       *str = 0;
05668       if (strchr(term, c))
05669          return 1;
05670    }
05671 }

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

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

05185 {
05186    int sent=0;
05187    int size;
05188    int res;
05189    int fd;
05190    fd = p->subs[index].zfd;
05191    while (len) {
05192       size = len;
05193       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05194          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05195       res = write(fd, buf, size);
05196       if (res != size) {
05197          if (option_debug)
05198             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05199          return sent;
05200       }
05201       len -= size;
05202       buf += size;
05203    }
05204    return sent;
05205 }

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

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

12326 {
12327    struct zt_pvt *tmp;
12328    char *ringc; /* temporary string for parsing the dring number. */
12329    int y;
12330    int found_pseudo = 0;
12331         char zapchan[MAX_CHANLIST_LEN] = {};
12332 
12333    for (; v; v = v->next) {
12334       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12335          continue;
12336 
12337       /* Create the interface list */
12338       if (!strcasecmp(v->name, "channel")
12339 #ifdef HAVE_PRI
12340           || !strcasecmp(v->name, "crv")
12341 #endif         
12342          ) {
12343          int iscrv;
12344          if (skipchannels)
12345             continue;
12346          iscrv = !strcasecmp(v->name, "crv");
12347          if (build_channels(*confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
12348                return -1;
12349       } else if (!strcasecmp(v->name, "zapchan")) {
12350          ast_copy_string(zapchan, v->value, sizeof(zapchan));
12351       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
12352          if (ast_true(v->value))
12353             confp->chan.usedistinctiveringdetection = 1;
12354       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
12355          if (ast_true(v->value))
12356             distinctiveringaftercid = 1;
12357       } else if (!strcasecmp(v->name, "dring1context")) {
12358          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
12359       } else if (!strcasecmp(v->name, "dring2context")) {
12360          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
12361       } else if (!strcasecmp(v->name, "dring3context")) {
12362          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
12363       } else if (!strcasecmp(v->name, "dring1")) {
12364          ringc = v->value;
12365          sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
12366       } else if (!strcasecmp(v->name, "dring2")) {
12367          ringc = v->value;
12368          sscanf(ringc, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
12369       } else if (!strcasecmp(v->name, "dring3")) {
12370          ringc = v->value;
12371          sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
12372       } else if (!strcasecmp(v->name, "usecallerid")) {
12373          confp->chan.use_callerid = ast_true(v->value);
12374       } else if (!strcasecmp(v->name, "cidsignalling")) {
12375          if (!strcasecmp(v->value, "bell"))
12376             confp->chan.cid_signalling = CID_SIG_BELL;
12377          else if (!strcasecmp(v->value, "v23"))
12378             confp->chan.cid_signalling = CID_SIG_V23;
12379          else if (!strcasecmp(v->value, "dtmf"))
12380             confp->chan.cid_signalling = CID_SIG_DTMF;
12381          else if (!strcasecmp(v->value, "smdi"))
12382             confp->chan.cid_signalling = CID_SIG_SMDI;
12383          else if (!strcasecmp(v->value, "v23_jp"))
12384             confp->chan.cid_signalling = CID_SIG_V23_JP;
12385          else if (ast_true(v->value))
12386             confp->chan.cid_signalling = CID_SIG_BELL;
12387       } else if (!strcasecmp(v->name, "cidstart")) {
12388          if (!strcasecmp(v->value, "ring"))
12389             confp->chan.cid_start = CID_START_RING;
12390          else if (!strcasecmp(v->value, "polarity"))
12391             confp->chan.cid_start = CID_START_POLARITY;
12392          else if (ast_true(v->value))
12393             confp->chan.cid_start = CID_START_RING;
12394       } else if (!strcasecmp(v->name, "threewaycalling")) {
12395          confp->chan.threewaycalling = ast_true(v->value);
12396       } else if (!strcasecmp(v->name, "cancallforward")) {
12397          confp->chan.cancallforward = ast_true(v->value);
12398       } else if (!strcasecmp(v->name, "relaxdtmf")) {
12399          if (ast_true(v->value)) 
12400             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
12401          else
12402             confp->chan.dtmfrelax = 0;
12403       } else if (!strcasecmp(v->name, "mailbox")) {
12404          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
12405       } else if (!strcasecmp(v->name, "adsi")) {
12406          confp->chan.adsi = ast_true(v->value);
12407       } else if (!strcasecmp(v->name, "usesmdi")) {
12408          confp->chan.use_smdi = ast_true(v->value);
12409       } else if (!strcasecmp(v->name, "smdiport")) {
12410          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
12411       } else if (!strcasecmp(v->name, "transfer")) {
12412          confp->chan.transfer = ast_true(v->value);
12413       } else if (!strcasecmp(v->name, "canpark")) {
12414          confp->chan.canpark = ast_true(v->value);
12415       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
12416          confp->chan.echocanbridged = ast_true(v->value);
12417       } else if (!strcasecmp(v->name, "busydetect")) {
12418          confp->chan.busydetect = ast_true(v->value);
12419       } else if (!strcasecmp(v->name, "busycount")) {
12420          confp->chan.busycount = atoi(v->value);
12421       } else if (!strcasecmp(v->name, "busypattern")) {
12422          if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
12423             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
12424          }
12425       } else if (!strcasecmp(v->name, "callprogress")) {
12426          if (ast_true(v->value))
12427             confp->chan.callprogress |= 1;
12428          else
12429             confp->chan.callprogress &= ~1;
12430       } else if (!strcasecmp(v->name, "faxdetect")) {
12431          if (!strcasecmp(v->value, "incoming")) {
12432             confp->chan.callprogress |= 4;
12433             confp->chan.callprogress &= ~2;
12434          } else if (!strcasecmp(v->value, "outgoing")) {
12435             confp->chan.callprogress &= ~4;
12436             confp->chan.callprogress |= 2;
12437          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
12438             confp->chan.callprogress |= 6;
12439          else
12440             confp->chan.callprogress &= ~6;
12441       } else if (!strcasecmp(v->name, "echocancel")) {
12442          if (!ast_strlen_zero(v->value)) {
12443             y = atoi(v->value);
12444          } else
12445             y = 0;
12446          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
12447             confp->chan.echocancel = y;
12448          else {
12449             confp->chan.echocancel = ast_true(v->value);
12450             if (confp->chan.echocancel)
12451                confp->chan.echocancel=128;
12452          }
12453       } else if (!strcasecmp(v->name, "echotraining")) {
12454          if (sscanf(v->value, "%d", &y) == 1) {
12455             if ((y < 10) || (y > 4000)) {
12456                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
12457             } else {
12458                confp->chan.echotraining = y;
12459             }
12460          } else if (ast_true(v->value)) {
12461             confp->chan.echotraining = 400;
12462          } else
12463             confp->chan.echotraining = 0;
12464       } else if (!strcasecmp(v->name, "hidecallerid")) {
12465          confp->chan.hidecallerid = ast_true(v->value);
12466       } else if (!strcasecmp(v->name, "hidecalleridname")) {
12467          confp->chan.hidecalleridname = ast_true(v->value);
12468       } else if (!strcasecmp(v->name, "pulsedial")) {
12469          confp->chan.pulse = ast_true(v->value);
12470       } else if (!strcasecmp(v->name, "callreturn")) {
12471          confp->chan.callreturn = ast_true(v->value);
12472       } else if (!strcasecmp(v->name, "callwaiting")) {
12473          confp->chan.callwaiting = ast_true(v->value);
12474       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
12475          confp->chan.callwaitingcallerid = ast_true(v->value);
12476       } else if (!strcasecmp(v->name, "context")) {
12477          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
12478       } else if (!strcasecmp(v->name, "language")) {
12479          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
12480       } else if (!strcasecmp(v->name, "progzone")) {
12481          ast_copy_string(progzone, v->value, sizeof(progzone));
12482       } else if (!strcasecmp(v->name, "mohinterpret") 
12483          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
12484          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
12485       } else if (!strcasecmp(v->name, "mohsuggest")) {
12486          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
12487       } else if (!strcasecmp(v->name, "stripmsd")) {
12488          confp->chan.stripmsd = atoi(v->value);
12489       } else if (!strcasecmp(v->name, "jitterbuffers")) {
12490          numbufs = atoi(v->value);
12491       } else if (!strcasecmp(v->name, "group")) {
12492          confp->chan.group = ast_get_group(v->value);
12493       } else if (!strcasecmp(v->name, "callgroup")) {
12494          confp->chan.callgroup = ast_get_group(v->value);
12495       } else if (!strcasecmp(v->name, "pickupgroup")) {
12496          confp->chan.pickupgroup = ast_get_group(v->value);
12497       } else if (!strcasecmp(v->name, "immediate")) {
12498          confp->chan.immediate = ast_true(v->value);
12499       } else if (!strcasecmp(v->name, "transfertobusy")) {
12500          confp->chan.transfertobusy = ast_true(v->value);
12501       } else if (!strcasecmp(v->name, "rxgain")) {
12502          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
12503             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
12504          }
12505       } else if (!strcasecmp(v->name, "txgain")) {
12506          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
12507             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
12508          }
12509       } else if (!strcasecmp(v->name, "tonezone")) {
12510          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
12511             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
12512          }
12513       } else if (!strcasecmp(v->name, "callerid")) {
12514          if (!strcasecmp(v->value, "asreceived")) {
12515             confp->chan.cid_num[0] = '\0';
12516             confp->chan.cid_name[0] = '\0';
12517          } else {
12518             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
12519          } 
12520       } else if (!strcasecmp(v->name, "fullname")) {
12521          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
12522       } else if (!strcasecmp(v->name, "cid_number")) {
12523          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
12524       } else if (!strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
12525          confp->chan.zaptrcallerid = ast_true(v->value);
12526       } else if (!strcasecmp(v->name, "restrictcid")) {
12527          confp->chan.restrictcid = ast_true(v->value);
12528       } else if (!strcasecmp(v->name, "usecallingpres")) {
12529          confp->chan.use_callingpres = ast_true(v->value);
12530       } else if (!strcasecmp(v->name, "accountcode")) {
12531          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
12532       } else if (!strcasecmp(v->name, "amaflags")) {
12533          y = ast_cdr_amaflags2int(v->value);
12534          if (y < 0) 
12535             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
12536          else
12537             confp->chan.amaflags = y;
12538       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
12539          confp->chan.polarityonanswerdelay = atoi(v->value);
12540       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
12541          confp->chan.answeronpolarityswitch = ast_true(v->value);
12542       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
12543          confp->chan.hanguponpolarityswitch = ast_true(v->value);
12544       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
12545          confp->chan.sendcalleridafter = atoi(v->value);
12546       } else if (!reload){ 
12547           if (!strcasecmp(v->name, "signalling")) {
12548             confp->chan.outsigmod = -1;
12549             if (!strcasecmp(v->value, "em")) {
12550                confp->chan.sig = SIG_EM;
12551             } else if (!strcasecmp(v->value, "em_e1")) {
12552                confp->chan.sig = SIG_EM_E1;
12553             } else if (!strcasecmp(v->value, "em_w")) {
12554                confp->chan.sig = SIG_EMWINK;
12555                confp->chan.radio = 0;
12556             } else if (!strcasecmp(v->value, "fxs_ls")) {
12557                confp->chan.sig = SIG_FXSLS;
12558                confp->chan.radio = 0;
12559             } else if (!strcasecmp(v->value, "fxs_gs")) {
12560                confp->chan.sig = SIG_FXSGS;
12561                confp->chan.radio = 0;
12562             } else if (!strcasecmp(v->value, "fxs_ks")) {
12563                confp->chan.sig = SIG_FXSKS;
12564                confp->chan.radio = 0;
12565             } else if (!strcasecmp(v->value, "fxo_ls")) {
12566                confp->chan.sig = SIG_FXOLS;
12567                confp->chan.radio = 0;
12568             } else if (!strcasecmp(v->value, "fxo_gs")) {
12569                confp->chan.sig = SIG_FXOGS;
12570                confp->chan.radio = 0;
12571             } else if (!strcasecmp(v->value, "fxo_ks")) {
12572                confp->chan.sig = SIG_FXOKS;
12573                confp->chan.radio = 0;
12574             } else if (!strcasecmp(v->value, "fxs_rx")) {
12575                confp->chan.sig = SIG_FXSKS;
12576                confp->chan.radio = 1;
12577             } else if (!strcasecmp(v->value, "fxo_rx")) {
12578                confp->chan.sig = SIG_FXOLS;
12579                confp->chan.radio = 1;
12580             } else if (!strcasecmp(v->value, "fxs_tx")) {
12581                confp->chan.sig = SIG_FXSLS;
12582                confp->chan.radio = 1;
12583             } else if (!strcasecmp(v->value, "fxo_tx")) {
12584                confp->chan.sig = SIG_FXOGS;
12585                confp->chan.radio = 1;
12586             } else if (!strcasecmp(v->value, "em_rx")) {
12587                confp->chan.sig = SIG_EM;
12588                confp->chan.radio = 1;
12589             } else if (!strcasecmp(v->value, "em_tx")) {
12590                confp->chan.sig = SIG_EM;
12591                confp->chan.radio = 1;
12592             } else if (!strcasecmp(v->value, "em_rxtx")) {
12593                confp->chan.sig = SIG_EM;
12594                confp->chan.radio = 2;
12595             } else if (!strcasecmp(v->value, "em_txrx")) {
12596                confp->chan.sig = SIG_EM;
12597                confp->chan.radio = 2;
12598             } else if (!strcasecmp(v->value, "sf")) {
12599                confp->chan.sig = SIG_SF;
12600                confp->chan.radio = 0;
12601             } else if (!strcasecmp(v->value, "sf_w")) {
12602                confp->chan.sig = SIG_SFWINK;
12603                confp->chan.radio = 0;
12604             } else if (!strcasecmp(v->value, "sf_featd")) {
12605                confp->chan.sig = SIG_FEATD;
12606                confp->chan.radio = 0;
12607             } else if (!strcasecmp(v->value, "sf_featdmf")) {
12608                confp->chan.sig = SIG_FEATDMF;
12609                confp->chan.radio = 0;
12610             } else if (!strcasecmp(v->value, "sf_featb")) {
12611                confp->chan.sig = SIG_SF_FEATB;
12612                confp->chan.radio = 0;
12613             } else if (!strcasecmp(v->value, "sf")) {
12614                confp->chan.sig = SIG_SF;
12615                confp->chan.radio = 0;
12616             } else if (!strcasecmp(v->value, "sf_rx")) {
12617                confp->chan.sig = SIG_SF;
12618                confp->chan.radio = 1;
12619             } else if (!strcasecmp(v->value, "sf_tx")) {
12620                confp->chan.sig = SIG_SF;
12621                confp->chan.radio = 1;
12622             } else if (!strcasecmp(v->value, "sf_rxtx")) {
12623                confp->chan.sig = SIG_SF;
12624                confp->chan.radio = 2;
12625             } else if (!strcasecmp(v->value, "sf_txrx")) {
12626                confp->chan.sig = SIG_SF;
12627                confp->chan.radio = 2;
12628             } else if (!strcasecmp(v->value, "featd")) {
12629                confp->chan.sig = SIG_FEATD;
12630                confp->chan.radio = 0;
12631             } else if (!strcasecmp(v->value, "featdmf")) {
12632                confp->chan.sig = SIG_FEATDMF;
12633                confp->chan.radio = 0;
12634             } else if (!strcasecmp(v->value, "featdmf_ta")) {
12635                confp->chan.sig = SIG_FEATDMF_TA;
12636                confp->chan.radio = 0;
12637             } else if (!strcasecmp(v->value, "e911")) {
12638                confp->chan.sig = SIG_E911;
12639                confp->chan.radio = 0;
12640             } else if (!strcasecmp(v->value, "fgccama")) {
12641                confp->chan.sig = SIG_FGC_CAMA;
12642                confp->chan.radio = 0;
12643             } else if (!strcasecmp(v->value, "fgccamamf")) {
12644                confp->chan.sig = SIG_FGC_CAMAMF;
12645                confp->chan.radio = 0;
12646             } else if (!strcasecmp(v->value, "featb")) {
12647                confp->chan.sig = SIG_FEATB;
12648                confp->chan.radio = 0;
12649 #ifdef HAVE_PRI
12650             } else if (!strcasecmp(v->value, "pri_net")) {
12651                confp->chan.radio = 0;
12652                confp->chan.sig = SIG_PRI;
12653                confp->pri.nodetype = PRI_NETWORK;
12654             } else if (!strcasecmp(v->value, "pri_cpe")) {
12655                confp->chan.sig = SIG_PRI;
12656                confp->chan.radio = 0;
12657                confp->pri.nodetype = PRI_CPE;
12658             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
12659                confp->chan.sig = SIG_GR303FXOKS;
12660                confp->chan.radio = 0;
12661                confp->pri.nodetype = PRI_NETWORK;
12662             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
12663                confp->chan.sig = SIG_GR303FXSKS;
12664                confp->chan.radio = 0;
12665                confp->pri.nodetype = PRI_CPE;
12666             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
12667                confp->chan.radio = 0;
12668                confp->chan.sig = SIG_PRI;
12669                confp->pri.nodetype = BRI_NETWORK_PTMP;
12670             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
12671                confp->chan.sig = SIG_PRI;
12672                confp->chan.radio = 0;
12673                confp->pri.nodetype = BRI_CPE_PTMP;
12674             } else if (!strcasecmp(v->value, "bri_net")) {
12675                confp->chan.radio = 0;
12676                confp->chan.sig = SIG_PRI;
12677                confp->pri.nodetype = BRI_NETWORK;
12678             } else if (!strcasecmp(v->value, "bri_cpe")) {
12679                confp->chan.sig = SIG_PRI;
12680                confp->chan.radio = 0;
12681                confp->pri.nodetype = BRI_CPE;
12682 #endif
12683 #ifdef HAVE_GSMAT
12684             } else if (!strcasecmp(v->value, "gsm")) {
12685                confp->chan.sig = SIG_GSM;
12686                confp->chan.radio = 0;
12687 #endif            
12688             } else {
12689                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
12690             }
12691           } else if (!strcasecmp(v->name, "outsignalling")) {
12692             if (!strcasecmp(v->value, "em")) {
12693                confp->chan.outsigmod = SIG_EM;
12694             } else if (!strcasecmp(v->value, "em_e1")) {
12695                confp->chan.outsigmod = SIG_EM_E1;
12696             } else if (!strcasecmp(v->value, "em_w")) {
12697                confp->chan.outsigmod = SIG_EMWINK;
12698             } else if (!strcasecmp(v->value, "sf")) {
12699                confp->chan.outsigmod = SIG_SF;
12700             } else if (!strcasecmp(v->value, "sf_w")) {
12701                confp->chan.outsigmod = SIG_SFWINK;
12702             } else if (!strcasecmp(v->value, "sf_featd")) {
12703                confp->chan.outsigmod = SIG_FEATD;
12704             } else if (!strcasecmp(v->value, "sf_featdmf")) {
12705                confp->chan.outsigmod = SIG_FEATDMF;
12706             } else if (!strcasecmp(v->value, "sf_featb")) {
12707                confp->chan.outsigmod = SIG_SF_FEATB;
12708             } else if (!strcasecmp(v->value, "sf")) {
12709                confp->chan.outsigmod = SIG_SF;
12710             } else if (!strcasecmp(v->value, "featd")) {
12711                confp->chan.outsigmod = SIG_FEATD;
12712             } else if (!strcasecmp(v->value, "featdmf")) {
12713                confp->chan.outsigmod = SIG_FEATDMF;
12714             } else if (!strcasecmp(v->value, "featdmf_ta")) {
12715                confp->chan.outsigmod = SIG_FEATDMF_TA;
12716             } else if (!strcasecmp(v->value, "e911")) {
12717                confp->chan.outsigmod = SIG_E911;
12718             } else if (!strcasecmp(v->value, "fgccama")) {
12719                confp->chan.outsigmod = SIG_FGC_CAMA;
12720             } else if (!strcasecmp(v->value, "fgccamamf")) {
12721                confp->chan.outsigmod = SIG_FGC_CAMAMF;
12722             } else if (!strcasecmp(v->value, "featb")) {
12723                confp->chan.outsigmod = SIG_FEATB;
12724             } else {
12725                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
12726             }
12727 #ifdef HAVE_PRI
12728          } else if (!strcasecmp(v->name, "pridialplan")) {
12729             if (!strcasecmp(v->value, "national")) {
12730                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
12731             } else if (!strcasecmp(v->value, "unknown")) {
12732                confp->pri.dialplan = PRI_UNKNOWN + 1;
12733             } else if (!strcasecmp(v->value, "private")) {
12734                confp->pri.dialplan = PRI_PRIVATE + 1;
12735             } else if (!strcasecmp(v->value, "international")) {
12736                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
12737             } else if (!strcasecmp(v->value, "local")) {
12738                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
12739             } else if (!strcasecmp(v->value, "dynamic")) {
12740                confp->pri.dialplan = -1;
12741             } else {
12742                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
12743             }
12744          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
12745             if (!strcasecmp(v->value, "national")) {
12746                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
12747             } else if (!strcasecmp(v->value, "unknown")) {
12748                confp->pri.localdialplan = PRI_UNKNOWN + 1;
12749             } else if (!strcasecmp(v->value, "private")) {
12750                confp->pri.localdialplan = PRI_PRIVATE + 1;
12751             } else if (!strcasecmp(v->value, "international")) {
12752                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
12753             } else if (!strcasecmp(v->value, "local")) {
12754                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
12755             } else if (!strcasecmp(v->value, "dynamic")) {
12756                confp->pri.localdialplan = -1;
12757             } else {
12758                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
12759             }
12760          } else if (!strcasecmp(v->name, "switchtype")) {
12761             if (!strcasecmp(v->value, "national")) 
12762                confp->pri.switchtype = PRI_SWITCH_NI2;
12763             else if (!strcasecmp(v->value, "ni1"))
12764                confp->pri.switchtype = PRI_SWITCH_NI1;
12765             else if (!strcasecmp(v->value, "dms100"))
12766                confp->pri.switchtype = PRI_SWITCH_DMS100;
12767             else if (!strcasecmp(v->value, "4ess"))
12768                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
12769             else if (!strcasecmp(v->value, "5ess"))
12770                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
12771             else if (!strcasecmp(v->value, "euroisdn"))
12772                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
12773             else if (!strcasecmp(v->value, "qsig"))
12774                confp->pri.switchtype = PRI_SWITCH_QSIG;
12775             else {
12776                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
12777                return -1;
12778             }
12779          } else if (!strcasecmp(v->name, "nsf")) {
12780             if (!strcasecmp(v->value, "sdn"))
12781                confp->pri.nsf = PRI_NSF_SDN;
12782             else if (!strcasecmp(v->value, "megacom"))
12783                confp->pri.nsf = PRI_NSF_MEGACOM;
12784             else if (!strcasecmp(v->value, "tollfreemegacom"))
12785                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
12786             else if (!strcasecmp(v->value, "accunet"))
12787                confp->pri.nsf = PRI_NSF_ACCUNET;
12788             else if (!strcasecmp(v->value, "none"))
12789                confp->pri.nsf = PRI_NSF_NONE;
12790             else {
12791                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
12792                confp->pri.nsf = PRI_NSF_NONE;
12793             }
12794          } else if (!strcasecmp(v->name, "priindication")) {
12795             if (!strcasecmp(v->value, "outofband"))
12796                confp->chan.priindication_oob = 1;
12797             else if (!strcasecmp(v->value, "inband"))
12798                confp->chan.priindication_oob = 0;
12799             else if (!strcasecmp(v->value, "passthrough"))
12800                confp->chan.priindication_oob = 2;
12801             else
12802                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband', 'outofband' or 'passthrough' at line %d\n",
12803                   v->value, v->lineno);
12804          } else if (!strcasecmp(v->name, "pritransfer")) {
12805             if (!strcasecmp(v->value, "no"))
12806                confp->chan.pritransfer = 0;
12807             else if (!strcasecmp(v->value, "ect"))
12808                confp->chan.pritransfer = 1;
12809             else if (!strcasecmp(v->value, "hangup"))
12810                confp->chan.pritransfer = 2;
12811             else
12812                ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
12813                   v->value, v->lineno);
12814          } else if (!strcasecmp(v->name, "priexclusive")) {
12815             confp->chan.priexclusive = ast_true(v->value);
12816          } else if (!strcasecmp(v->name, "internationalprefix")) {
12817             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
12818          } else if (!strcasecmp(v->name, "nationalprefix")) {
12819             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
12820          } else if (!strcasecmp(v->name, "localprefix")) {
12821             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
12822          } else if (!strcasecmp(v->name, "privateprefix")) {
12823             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
12824          } else if (!strcasecmp(v->name, "unknownprefix")) {
12825             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
12826          } else if (!strcasecmp(v->name, "nocid")) {
12827             ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
12828          } else if (!strcasecmp(v->name, "withheldcid")) {
12829             ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
12830          } else if (!strcasecmp(v->name, "pin")) {
12831             ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
12832          } else if (!strcasecmp(v->name, "exten")) {
12833             ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
12834          } else if (!strcasecmp(v->name, "resetinterval")) {
12835             if (!strcasecmp(v->value, "never"))
12836                confp->pri.resetinterval = -1;
12837             else if (atoi(v->value) >= 60)
12838                confp->pri.resetinterval = atoi(v->value);
12839             else
12840                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
12841                   v->value, v->lineno);
12842          } else if (!strcasecmp(v->name, "minunused")) {
12843             confp->pri.minunused = atoi(v->value);
12844          } else if (!strcasecmp(v->name, "minidle")) {
12845             confp->pri.minidle = atoi(v->value); 
12846          } else if (!strcasecmp(v->name, "idleext")) {
12847             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
12848          } else if (!strcasecmp(v->name, "idledial")) {
12849             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
12850          } else if (!strcasecmp(v->name, "pritrustusercid")) {
12851             confp->pri.usercid = ast_true(v->value);
12852          } else if (!strcasecmp(v->name, "overlapdial")) {
12853             confp->pri.overlapdial = ast_true(v->value);
12854          } else if (!strcasecmp(v->name, "pritimer")) {
12855 #ifdef PRI_GETSET_TIMERS
12856             char *timerc, *c;
12857             int timer, timeridx;
12858             c = v->value;
12859             timerc = strsep(&c, ",");
12860             if (timerc) {
12861                timer = atoi(c);
12862                if (!timer)
12863                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
12864                else {
12865                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
12866                      pritimers[timeridx] = timer;
12867                   else
12868                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
12869                }
12870             } else
12871                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
12872 
12873          } else if (!strcasecmp(v->name, "facilityenable")) {
12874             confp->pri.facilityenable = ast_true(v->value);
12875 #endif /* PRI_GETSET_TIMERS */
12876 #endif /* HAVE_PRI */
12877          } else if (!strcasecmp(v->name, "cadence")) {
12878             /* setup to scan our argument */
12879             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
12880             int i;
12881             struct zt_ring_cadence new_cadence;
12882             int cid_location = -1;
12883             int firstcadencepos = 0;
12884             char original_args[80];
12885             int cadence_is_ok = 1;
12886 
12887             ast_copy_string(original_args, v->value, sizeof(original_args));
12888             /* 16 cadences allowed (8 pairs) */
12889             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]);
12890    
12891             /* Cadence must be even (on/off) */
12892             if (element_count % 2 == 1) {
12893                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
12894                cadence_is_ok = 0;
12895             }
12896    
12897             /* Ring cadences cannot be negative */
12898             for (i = 0; i < element_count; i++) {
12899                if (c[i] == 0) {
12900                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
12901                   cadence_is_ok = 0;
12902                   break;
12903                } else if (c[i] < 0) {
12904                   if (i % 2 == 1) {
12905                      /* Silence duration, negative possibly okay */
12906                      if (cid_location == -1) {
12907                         cid_location = i;
12908                         c[i] *= -1;
12909                      } else {
12910                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
12911                         cadence_is_ok = 0;
12912                         break;
12913                      }
12914                   } else {
12915                      if (firstcadencepos == 0) {
12916                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
12917                                  /* duration will be passed negative to the zaptel driver */
12918                      } else {
12919                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
12920                         cadence_is_ok = 0;
12921                         break;
12922                      }
12923                   }
12924                }
12925             }
12926    
12927             /* Substitute our scanned cadence */
12928             for (i = 0; i < 16; i++) {
12929                new_cadence.ringcadence[i] = c[i];
12930             }
12931    
12932             if (cadence_is_ok) {
12933                /* ---we scanned it without getting annoyed; now some sanity checks--- */
12934                if (element_count < 2) {
12935                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
12936                } else {
12937                   if (cid_location == -1) {
12938                      /* user didn't say; default to first pause */
12939                      cid_location = 1;
12940                   } else {
12941                      /* convert element_index to cidrings value */
12942                      cid_location = (cid_location + 1) / 2;
12943                   }
12944                   /* ---we like their cadence; try to install it--- */
12945                   if (!user_has_defined_cadences++)
12946                      /* this is the first user-defined cadence; clear the default user cadences */
12947                      num_cadence = 0;
12948                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
12949                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
12950                   else {
12951                      cadences[num_cadence] = new_cadence;
12952                      cidrings[num_cadence++] = cid_location;
12953                      if (option_verbose > 2)
12954                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
12955                   }
12956                }
12957             }
12958          } else if (!strcasecmp(v->name, "ringtimeout")) {
12959             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
12960          } else if (!strcasecmp(v->name, "prewink")) {
12961             confp->timing.prewinktime = atoi(v->value);
12962          } else if (!strcasecmp(v->name, "preflash")) {
12963             confp->timing.preflashtime = atoi(v->value);
12964          } else if (!strcasecmp(v->name, "wink")) {
12965             confp->timing.winktime = atoi(v->value);
12966          } else if (!strcasecmp(v->name, "flash")) {
12967             confp->timing.flashtime = atoi(v->value);
12968          } else if (!strcasecmp(v->name, "start")) {
12969             confp->timing.starttime = atoi(v->value);
12970          } else if (!strcasecmp(v->name, "rxwink")) {
12971             confp->timing.rxwinktime = atoi(v->value);
12972          } else if (!strcasecmp(v->name, "rxflash")) {
12973             confp->timing.rxflashtime = atoi(v->value);
12974          } else if (!strcasecmp(v->name, "debounce")) {
12975             confp->timing.debouncetime = atoi(v->value);
12976          } else if (!strcasecmp(v->name, "toneduration")) {
12977             int toneduration;
12978             int ctlfd;
12979             int res;
12980             struct zt_dialparams dps;
12981 
12982             ctlfd = open("/dev/zap/ctl", O_RDWR);
12983             if (ctlfd == -1) {
12984                ast_log(LOG_ERROR, "Unable to open /dev/zap/ctl to set toneduration\n");
12985                return -1;
12986             }
12987 
12988             toneduration = atoi(v->value);
12989             if (toneduration > -1) {
12990                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
12991                res = ioctl(ctlfd, ZT_SET_DIALPARAMS, &dps);
12992                if (res < 0) {
12993                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms\n", toneduration);
12994                   return -1;
12995                }
12996             }
12997             close(ctlfd);
12998          } else if (!strcasecmp(v->name, "defaultcic")) {
12999             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13000          } else if (!strcasecmp(v->name, "defaultozz")) {
13001             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13002          } 
13003       } else if (!skipchannels)
13004          ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
13005    }
13006    if (zapchan[0]) { 
13007       /* The user has set 'zapchan' */
13008       /*< \todo pass proper line number instead of 0 */
13009       if (build_channels(*confp, 0, zapchan, reload, 0, &found_pseudo)) {
13010          return -1;
13011       }
13012    }
13013    /*< \todo why check for the pseudo in the per-channel section.
13014     * Any actual use for manual setup of the pseudo channel? */
13015    if (!found_pseudo && reload == 0) {
13016       /* Make sure pseudo isn't a member of any groups if
13017          we're automatically making it. */   
13018       
13019       confp->chan.group = 0;
13020       confp->chan.callgroup = 0;
13021       confp->chan.pickupgroup = 0;
13022 
13023       tmp = mkintf(CHAN_PSEUDO, *confp, NULL, reload);
13024 
13025       if (tmp) {
13026          if (option_verbose > 2)
13027             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13028       } else {
13029          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13030       }
13031    }
13032    return 0;
13033 }

static int reload ( void   )  [static]

Definition at line 13372 of file chan_zap.c.

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

13373 {
13374    int res = 0;
13375 
13376    res = setup_zap(1);
13377    if (res) {
13378       ast_log(LOG_WARNING, "Reload of chan_zap.so is unsuccessful!\n");
13379       return -1;
13380    }
13381    return 0;
13382 }

static int reset_conf ( struct zt_pvt p  )  [static]

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

01524 {
01525    ZT_CONFINFO zi;
01526    memset(&zi, 0, sizeof(zi));
01527    p->confno = -1;
01528    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01529    if (p->subs[SUB_REAL].zfd > -1) {
01530       if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &zi))
01531          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d!\n", p->channel);
01532    }
01533    return 0;
01534 }

static int restart_monitor ( void   )  [static]

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

07298 {
07299    pthread_attr_t attr;
07300    pthread_attr_init(&attr);
07301    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07302    /* If we're supposed to be stopped -- stay stopped */
07303    if (monitor_thread == AST_PTHREADT_STOP)
07304       return 0;
07305    ast_mutex_lock(&monlock);
07306    if (monitor_thread == pthread_self()) {
07307       ast_mutex_unlock(&monlock);
07308       ast_log(LOG_WARNING, "Cannot kill myself\n");
07309       return -1;
07310    }
07311    if (monitor_thread != AST_PTHREADT_NULL) {
07312       /* Wake up the thread */
07313       pthread_kill(monitor_thread, SIGURG);
07314    } else {
07315       /* Start a new monitor */
07316       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07317          ast_mutex_unlock(&monlock);
07318          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07319          pthread_attr_destroy(&attr);
07320          return -1;
07321       }
07322    }
07323    ast_mutex_unlock(&monlock);
07324    pthread_attr_destroy(&attr);
07325    return 0;
07326 }

static int restore_conference ( struct zt_pvt p  )  [static]

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

01860 {
01861    int res;
01862    if (p->saveconf.confmode) {
01863       res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &p->saveconf);
01864       p->saveconf.confmode = 0;
01865       if (res) {
01866          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01867          return -1;
01868       }
01869    }
01870    if (option_debug)
01871       ast_log(LOG_DEBUG, "Restored conferencing\n");
01872    return 0;
01873 }

static int restore_gains ( struct zt_pvt p  )  [static]

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

01787 {
01788    int res;
01789 
01790    res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
01791    if (res) {
01792       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01793       return -1;
01794    }
01795 
01796    return 0;
01797 }

static int save_conference ( struct zt_pvt p  )  [static]

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

01832 {
01833    struct zt_confinfo c;
01834    int res;
01835    if (p->saveconf.confmode) {
01836       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01837       return -1;
01838    }
01839    p->saveconf.chan = 0;
01840    res = ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &p->saveconf);
01841    if (res) {
01842       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01843       p->saveconf.confmode = 0;
01844       return -1;
01845    }
01846    c.chan = 0;
01847    c.confno = 0;
01848    c.confmode = ZT_CONF_NORMAL;
01849    res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &c);
01850    if (res) {
01851       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01852       return -1;
01853    }
01854    if (option_debug)
01855       ast_log(LOG_DEBUG, "Disabled conferencing\n");
01856    return 0;
01857 }

static int send_callerid ( struct zt_pvt p  )  [static]

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

01900 {
01901    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
01902    int res;
01903    /* Take out of linear mode if necessary */
01904    if (p->subs[SUB_REAL].linear) {
01905       p->subs[SUB_REAL].linear = 0;
01906       zt_setlinear(p->subs[SUB_REAL].zfd, 0);
01907    }
01908    while (p->cidpos < p->cidlen) {
01909       res = write(p->subs[SUB_REAL].zfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01910       if (res < 0) {
01911          if (errno == EAGAIN)
01912             return 0;
01913          else {
01914             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01915             return -1;
01916          }
01917       }
01918       if (!res)
01919          return 0;
01920       p->cidpos += res;
01921    }
01922    free(p->cidspill);
01923    p->cidspill = NULL;
01924    if (p->callwaitcas) {
01925       /* Wait for CID/CW to expire */
01926       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01927    } else
01928       restore_conference(p);
01929    return 0;
01930 }

static int send_cwcidspill ( struct zt_pvt p  )  [static]

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

01878 {
01879    p->callwaitcas = 0;
01880    p->cidcwexpire = 0;
01881    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01882       return -1;
01883    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01884    /* Make sure we account for the end */
01885    p->cidlen += READ_SIZE * 4;
01886    p->cidpos = 0;
01887    send_callerid(p);
01888    if (option_verbose > 2)
01889       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01890    return 0;
01891 }

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

Definition at line 1767 of file chan_zap.c.

References set_actual_rxgain(), and set_actual_txgain().

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

01768 {
01769    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01770 }

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

Definition at line 1749 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

01750 {
01751    struct zt_gains g;
01752    int res;
01753 
01754    memset(&g, 0, sizeof(g));
01755    g.chan = chan;
01756    res = ioctl(fd, ZT_GETGAINS, &g);
01757    if (res) {
01758       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01759       return res;
01760    }
01761 
01762    fill_rxgain(&g, gain, law);
01763 
01764    return ioctl(fd, ZT_SETGAINS, &g);
01765 }

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

Definition at line 1730 of file chan_zap.c.

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

Referenced by set_actual_gain(), and zt_setoption().

01731 {
01732    struct zt_gains g;
01733    int res;
01734 
01735    memset(&g, 0, sizeof(g));
01736    g.chan = chan;
01737    res = ioctl(fd, ZT_GETGAINS, &g);
01738    if (res) {
01739       if (option_debug)
01740          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01741       return res;
01742    }
01743 
01744    fill_txgain(&g, gain, law);
01745 
01746    return ioctl(fd, ZT_SETGAINS, &g);
01747 }

static int setup_zap ( int  reload  )  [static]

Todo:
At this point we should probably duplicate conf, and pass a copy, to prevent one section from affecting another

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

13036 {
13037    struct ast_config *cfg;
13038    struct ast_variable *v;
13039    struct zt_chan_conf conf = zt_chan_conf_default();
13040    int res;
13041 
13042 #ifdef HAVE_PRI
13043    char *c;
13044    int spanno;
13045    int i, x;
13046    int logicalspan;
13047    int trunkgroup;
13048    int dchannels[NUM_DCHANS];
13049 #endif
13050 
13051    cfg = ast_config_load(config);
13052 
13053    /* Error if we have no config file */
13054    if (!cfg) {
13055       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
13056       return 0;
13057    }
13058 
13059    /* It's a little silly to lock it, but we mind as well just to be sure */
13060    ast_mutex_lock(&iflock);
13061 #ifdef HAVE_PRI
13062    if (!reload) {
13063       /* Process trunkgroups first */
13064       v = ast_variable_browse(cfg, "trunkgroups");
13065       while (v) {
13066          if (!strcasecmp(v->name, "trunkgroup")) {
13067             trunkgroup = atoi(v->value);
13068             if (trunkgroup > 0) {
13069                if ((c = strchr(v->value, ','))) {
13070                   i = 0;
13071                   memset(dchannels, 0, sizeof(dchannels));
13072                   while (c && (i < NUM_DCHANS)) {
13073                      dchannels[i] = atoi(c + 1);
13074                      if (dchannels[i] < 0) {
13075                         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);
13076                      } else
13077                         i++;
13078                      c = strchr(c + 1, ',');
13079                   }
13080                   if (i) {
13081                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13082                         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);
13083                      } else if (option_verbose > 1)
13084                         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");
13085                   } else
13086                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
13087                } else
13088                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
13089             } else
13090                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
13091          } else if (!strcasecmp(v->name, "spanmap")) {
13092             spanno = atoi(v->value);
13093             if (spanno > 0) {
13094                if ((c = strchr(v->value, ','))) {
13095                   trunkgroup = atoi(c + 1);
13096                   if (trunkgroup > 0) {
13097                      if ((c = strchr(c + 1, ','))) 
13098                         logicalspan = atoi(c + 1);
13099                      else
13100                         logicalspan = 0;
13101                      if (logicalspan >= 0) {
13102                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13103                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13104                         } else if (option_verbose > 1) 
13105                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13106                      } else
13107                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
13108                   } else
13109                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
13110                } else
13111                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
13112             } else
13113                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
13114          } else {
13115             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13116          }
13117          v = v->next;
13118       }
13119    }
13120 #endif
13121    
13122    /* Copy the default jb config over global_jbconf */
13123    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13124 
13125    v = ast_variable_browse(cfg, "channels");
13126    res = process_zap(&conf, v, reload, 0);
13127    ast_mutex_unlock(&iflock);
13128    ast_config_destroy(cfg);
13129    if (res)
13130       return res;
13131    cfg = ast_config_load("users.conf");
13132    if (cfg) {
13133       char *cat;
13134       const char *chans;
13135       process_zap(&conf, ast_variable_browse(cfg, "general"), 1, 1);
13136       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13137          if (!strcasecmp(cat, "general"))
13138             continue;
13139          chans = ast_variable_retrieve(cfg, cat, "zapchan");
13140          if (!ast_strlen_zero(chans)) {
13141             /** \todo At this point we should probably 
13142              * duplicate conf, and pass a copy, to prevent 
13143              * one section from affecting another
13144              */
13145             process_zap(&conf, ast_variable_browse(cfg, cat), reload, 0);
13146          }
13147       }
13148       ast_config_destroy(cfg);
13149    }
13150 #ifdef HAVE_PRI
13151    if (!reload) {
13152       for (x = 0; x < NUM_SPANS; x++) {
13153          pris[x].debugfd = -1;
13154          if (pris[x].pvts[0]) {
13155             if (start_pri(pris + x)) {
13156                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13157                return -1;
13158             } else if (option_verbose > 1)
13159                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13160          }
13161       }
13162    }
13163 #endif
13164    /* And start the monitor for the first time */
13165    restart_monitor();
13166    return 0;
13167 }

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

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

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

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

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

01023 {
01024    int tchan;
01025    int tinthreeway;
01026    struct ast_channel *towner;
01027 
01028    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01029 
01030    tchan = p->subs[a].chan;
01031    towner = p->subs[a].owner;
01032    tinthreeway = p->subs[a].inthreeway;
01033 
01034    p->subs[a].chan = p->subs[b].chan;
01035    p->subs[a].owner = p->subs[b].owner;
01036    p->subs[a].inthreeway = p->subs[b].inthreeway;
01037 
01038    p->subs[b].chan = tchan;
01039    p->subs[b].owner = towner;
01040    p->subs[b].inthreeway = tinthreeway;
01041 
01042    if (p->subs[a].owner) 
01043       p->subs[a].owner->fds[0] = p->subs[a].zfd;
01044    if (p->subs[b].owner) 
01045       p->subs[b].owner->fds[0] = p->subs[b].zfd;
01046    wakeup_sub(p, a, NULL);
01047    wakeup_sub(p, b, NULL);
01048 }

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

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

01149 {
01150    if (!x) {
01151       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01152       return -1;
01153    }
01154    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01155    if (p->subs[x].zfd > -1) {
01156       zt_close(p->subs[x].zfd);
01157    }
01158    p->subs[x].zfd = -1;
01159    p->subs[x].linear = 0;
01160    p->subs[x].chan = 0;
01161    p->subs[x].owner = NULL;
01162    p->subs[x].inthreeway = 0;
01163    p->polarity = POLARITY_IDLE;
01164    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01165    return 0;
01166 }

static int unload_module ( void   )  [static]

Definition at line 12222 of file chan_zap.c.

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

12223 {
12224 #ifdef HAVE_PRI      
12225    int y;
12226    for (y = 0; y < NUM_SPANS; y++)
12227       ast_mutex_destroy(&pris[y].lock);
12228 #endif
12229    return __unload_module();
12230 }

static int update_conf ( struct zt_pvt p  )  [static]

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

01537 {
01538    int needconf = 0;
01539    int x;
01540    int useslavenative;
01541    struct zt_pvt *slave = NULL;
01542 
01543    useslavenative = isslavenative(p, &slave);
01544    /* Start with the obvious, general stuff */
01545    for (x = 0; x < 3; x++) {
01546       /* Look for three way calls */
01547       if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway) {
01548          conf_add(p, &p->subs[x], x, 0);
01549          needconf++;
01550       } else {
01551          conf_del(p, &p->subs[x], x);
01552       }
01553    }
01554    /* If we have a slave, add him to our conference now. or DAX
01555       if this is slave native */
01556    for (x = 0; x < MAX_SLAVES; x++) {
01557       if (p->slaves[x]) {
01558          if (useslavenative)
01559             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01560          else {
01561             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01562             needconf++;
01563          }
01564       }
01565    }
01566    /* If we're supposed to be in there, do so now */
01567    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01568       if (useslavenative)
01569          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01570       else {
01571          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01572          needconf++;
01573       }
01574    }
01575    /* If we have a master, add ourselves to his conference */
01576    if (p->master) {
01577       if (isslavenative(p->master, NULL)) {
01578          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01579       } else {
01580          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01581       }
01582    }
01583    if (!needconf) {
01584       /* Nobody is left (or should be left) in our conference.
01585          Kill it. */
01586       p->confno = -1;
01587    }
01588    if (option_debug)
01589       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01590    return 0;
01591 }

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

Definition at line 962 of file chan_zap.c.

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

Referenced by swap_subs().

00964 {
00965 #ifdef HAVE_PRI
00966    if (pri)
00967       ast_mutex_unlock(&pri->lock);
00968 #endif         
00969    for (;;) {
00970       if (p->subs[a].owner) {
00971          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00972             ast_mutex_unlock(&p->lock);
00973             usleep(1);
00974             ast_mutex_lock(&p->lock);
00975          } else {
00976             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
00977             ast_mutex_unlock(&p->subs[a].owner->lock);
00978             break;
00979          }
00980       } else
00981          break;
00982    }
00983 #ifdef HAVE_PRI
00984    if (pri)
00985       ast_mutex_lock(&pri->lock);
00986 #endif         
00987 }

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

Definition at line 11574 of file chan_zap.c.

References RESULT_SHOWUSAGE, and zap_destroy_channel_bynum().

11575 {
11576    int channel;
11577    
11578    if (argc != 4)
11579       return RESULT_SHOWUSAGE;
11580    
11581    channel = atoi(argv[3]);
11582 
11583    return zap_destroy_channel_bynum(channel);
11584 }

static int zap_destroy_channel_bynum ( int  channel  )  [static]

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

06852 {
06853    struct zt_pvt *tmp = NULL;
06854    struct zt_pvt *prev = NULL;
06855 
06856    tmp = iflist;
06857    while (tmp) {
06858       if (tmp->channel == channel) {
06859          destroy_channel(prev, tmp, 1);
06860          return RESULT_SUCCESS;
06861       }
06862       prev = tmp;
06863       tmp = tmp->next;
06864    }
06865    return RESULT_FAILURE;
06866 }

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

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

11963 {
11964    if (p) {
11965       switch (mode) {
11966          case TRANSFER:
11967             p->fake_event = ZT_EVENT_WINKFLASH;
11968             break;
11969          case HANGUP:
11970             p->fake_event = ZT_EVENT_ONHOOK;
11971             break;
11972          default:
11973             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
11974       }
11975    }
11976    return 0;
11977 }

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

Definition at line 992 of file chan_zap.c.

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

Referenced by action_zapdialoffhook().

00994 {
00995    /* We must unlock the PRI to avoid the possibility of a deadlock */
00996 #ifdef HAVE_PRI
00997    if (pri)
00998       ast_mutex_unlock(&pri->lock);
00999 #endif      
01000    for (;;) {
01001       if (p->owner) {
01002          if (ast_mutex_trylock(&p->owner->lock)) {
01003             ast_mutex_unlock(&p->lock);
01004             usleep(1);
01005             ast_mutex_lock(&p->lock);
01006          } else {
01007             ast_queue_frame(p->owner, f);
01008             ast_mutex_unlock(&p->owner->lock);
01009             break;
01010          }
01011       } else
01012          break;
01013    }
01014 #ifdef HAVE_PRI
01015    if (pri)
01016       ast_mutex_lock(&pri->lock);
01017 #endif      
01018 }

static int zap_restart ( void   )  [static]

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

11588 {
11589    if (option_verbose > 0)
11590       ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
11591    while (iflist) {
11592       if (option_debug)
11593          ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
11594       /* Also updates iflist: */
11595       destroy_channel(NULL, iflist, 1);
11596    }
11597    if (option_debug)
11598       ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
11599    if (setup_zap(0) != 0) {
11600       ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
11601       return 1;
11602    }
11603    return 0;
11604 }

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

Definition at line 11606 of file chan_zap.c.

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

11607 {
11608    if (argc != 2) {
11609       return RESULT_SHOWUSAGE;
11610    }
11611 
11612    if (zap_restart() != 0)
11613       return RESULT_FAILURE;
11614    return RESULT_SUCCESS;
11615 }

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

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

11689 {
11690    int channel;
11691    struct zt_pvt *tmp = NULL;
11692    ZT_CONFINFO ci;
11693    ZT_PARAMS ps;
11694    int x;
11695    ast_mutex_t *lock;
11696    struct zt_pvt *start;
11697 #ifdef HAVE_PRI
11698    char *c;
11699    int trunkgroup;
11700    struct zt_pri *pri=NULL;
11701 #endif
11702 
11703    lock = &iflock;
11704    start = iflist;
11705 
11706    if (argc != 4)
11707       return RESULT_SHOWUSAGE;
11708 #ifdef HAVE_PRI
11709    if ((c = strchr(argv[3], ':'))) {
11710       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
11711          return RESULT_SHOWUSAGE;
11712       if ((trunkgroup < 1) || (channel < 1))
11713          return RESULT_SHOWUSAGE;
11714       for (x = 0; x < NUM_SPANS; x++) {
11715          if (pris[x].trunkgroup == trunkgroup) {
11716             pri = pris + x;
11717             break;
11718          }
11719       }
11720       if (pri) {
11721          start = pri->crvs;
11722          lock = &pri->lock;
11723       } else {
11724          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
11725          return RESULT_FAILURE;
11726       }
11727    } else
11728 #endif
11729       channel = atoi(argv[3]);
11730 
11731    ast_mutex_lock(lock);
11732    tmp = start;
11733    while (tmp) {
11734       if (tmp->channel == channel) {
11735 #ifdef HAVE_PRI
11736          if (pri) 
11737             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
11738          else
11739 #endif         
11740          ast_cli(fd, "Channel: %d\n", tmp->channel);
11741          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
11742          ast_cli(fd, "Span: %d\n", tmp->span);
11743          ast_cli(fd, "Extension: %s\n", tmp->exten);
11744          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
11745          ast_cli(fd, "Context: %s\n", tmp->context);
11746          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
11747          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
11748          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
11749          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
11750          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
11751          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
11752          ast_cli(fd, "Radio: %d\n", tmp->radio);
11753          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
11754          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)" : "");
11755          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)" : "");
11756          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)" : "");
11757          ast_cli(fd, "Confno: %d\n", tmp->confno);
11758          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
11759          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
11760          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
11761          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
11762          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
11763          ast_cli(fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
11764          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
11765          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
11766          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
11767          if (tmp->master)
11768             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
11769          for (x = 0; x < MAX_SLAVES; x++) {
11770             if (tmp->slaves[x])
11771                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
11772          }
11773 #ifdef HAVE_PRI
11774          if (tmp->pri) {
11775             ast_cli(fd, "PRI Flags: ");
11776             if (tmp->resetting)
11777                ast_cli(fd, "Resetting ");
11778             if (tmp->call)
11779                ast_cli(fd, "Call ");
11780             if (tmp->bearer)
11781                ast_cli(fd, "Bearer ");
11782             ast_cli(fd, "\n");
11783             if (tmp->logicalspan) 
11784                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
11785             else
11786                ast_cli(fd, "PRI Logical Span: Implicit\n");
11787          }
11788             
11789 #endif
11790          memset(&ci, 0, sizeof(ci));
11791          ps.channo = tmp->channel;
11792          if (tmp->subs[SUB_REAL].zfd > -1) {
11793             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
11794                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
11795             }
11796 #ifdef ZT_GETCONFMUTE
11797             if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) {
11798                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
11799             }
11800 #endif
11801             if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
11802                ast_log(LOG_WARNING, "Failed to get parameters on channel %d\n", tmp->channel);
11803             } else {
11804                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
11805             }
11806          }
11807          ast_mutex_unlock(lock);
11808          return RESULT_SUCCESS;
11809       }
11810       tmp = tmp->next;
11811    }
11812    
11813    ast_cli(fd, "Unable to find given channel %d\n", channel);
11814    ast_mutex_unlock(lock);
11815    return RESULT_FAILURE;
11816 }

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

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

11628 {
11629 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
11630 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
11631    struct zt_pvt *tmp = NULL;
11632    char tmps[20] = "";
11633    ast_mutex_t *lock;
11634    struct zt_pvt *start;
11635 #ifdef HAVE_PRI
11636    int trunkgroup;
11637    struct zt_pri *pri = NULL;
11638    int x;
11639 #endif
11640 
11641    lock = &iflock;
11642    start = iflist;
11643 
11644 #ifdef HAVE_PRI
11645    if (argc == 4) {
11646       if ((trunkgroup = atoi(argv[3])) < 1)
11647          return RESULT_SHOWUSAGE;
11648       for (x = 0; x < NUM_SPANS; x++) {
11649          if (pris[x].trunkgroup == trunkgroup) {
11650             pri = pris + x;
11651             break;
11652          }
11653       }
11654       if (pri) {
11655          start = pri->crvs;
11656          lock = &pri->lock;
11657       } else {
11658          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
11659          return RESULT_FAILURE;
11660       }
11661    } else
11662 #endif
11663    if (argc != 3)
11664       return RESULT_SHOWUSAGE;
11665 
11666    ast_mutex_lock(lock);
11667 #ifdef HAVE_PRI
11668    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
11669 #else
11670    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
11671 #endif   
11672    
11673    tmp = start;
11674    while (tmp) {
11675       if (tmp->channel > 0) {
11676          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
11677       } else
11678          ast_copy_string(tmps, "pseudo", sizeof(tmps));
11679       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
11680       tmp = tmp->next;
11681    }
11682    ast_mutex_unlock(lock);
11683    return RESULT_SUCCESS;
11684 #undef FORMAT
11685 #undef FORMAT2
11686 }

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

Definition at line 11849 of file chan_zap.c.

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

11849                                                            {
11850    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
11851    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
11852 
11853    int span;
11854    int res;
11855    char alarms[50];
11856 
11857    int ctl;
11858    ZT_SPANINFO s;
11859 
11860    ctl = open("/dev/zap/ctl", O_RDWR);
11861    if (ctl < 0) {
11862       ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
11863       ast_cli(fd, "No Zaptel interface found.\n");
11864       return RESULT_FAILURE;
11865    }
11866    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
11867 
11868    for (span = 1; span < ZT_MAX_SPANS; ++span) {
11869       s.spanno = span;
11870       res = ioctl(ctl, ZT_SPANSTAT, &s);
11871       if (res) {
11872          continue;
11873       }
11874       alarms[0] = '\0';
11875       if (s.alarms > 0) {
11876          if (s.alarms & ZT_ALARM_BLUE)
11877             strcat(alarms, "BLU/");
11878          if (s.alarms & ZT_ALARM_YELLOW)
11879             strcat(alarms, "YEL/");
11880          if (s.alarms & ZT_ALARM_RED)
11881             strcat(alarms, "RED/");
11882          if (s.alarms & ZT_ALARM_LOOPBACK)
11883             strcat(alarms, "LB/");
11884          if (s.alarms & ZT_ALARM_RECOVER)
11885             strcat(alarms, "REC/");
11886          if (s.alarms & ZT_ALARM_NOTOPEN)
11887             strcat(alarms, "NOP/");
11888          if (!strlen(alarms))
11889             strcat(alarms, "UUU/");
11890          if (strlen(alarms)) {
11891             /* Strip trailing / */
11892             alarms[strlen(alarms) - 1] = '\0';
11893          }
11894       } else {
11895          if (s.numchans)
11896             strcpy(alarms, "OK");
11897          else
11898             strcpy(alarms, "UNCONFIGURED");
11899       }
11900 
11901       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
11902    }
11903    close(ctl);
11904 
11905    return RESULT_SUCCESS;
11906 #undef FORMAT
11907 #undef FORMAT2
11908 }

static char* zap_sig2str ( int  sig  )  [static]

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

01345 {
01346    static char buf[256];
01347    switch (sig) {
01348    case SIG_EM:
01349       return "E & M Immediate";
01350    case SIG_EMWINK:
01351       return "E & M Wink";
01352    case SIG_EM_E1:
01353       return "E & M E1";
01354    case SIG_FEATD:
01355       return "Feature Group D (DTMF)";
01356    case SIG_FEATDMF:
01357       return "Feature Group D (MF)";
01358    case SIG_FEATDMF_TA:
01359       return "Feature Groud D (MF) Tandem Access";
01360    case SIG_FEATB:
01361       return "Feature Group B (MF)";
01362    case SIG_E911:
01363       return "E911 (MF)";
01364    case SIG_FGC_CAMA:
01365       return "FGC/CAMA (Dialpulse)";
01366    case SIG_FGC_CAMAMF:
01367       return "FGC/CAMA (MF)";
01368    case SIG_FXSLS:
01369       return "FXS Loopstart";
01370    case SIG_FXSGS:
01371       return "FXS Groundstart";
01372    case SIG_FXSKS:
01373       return "FXS Kewlstart";
01374    case SIG_FXOLS:
01375       return "FXO Loopstart";
01376    case SIG_FXOGS:
01377       return "FXO Groundstart";
01378    case SIG_FXOKS:
01379       return "FXO Kewlstart";
01380    case SIG_PRI:
01381       return "ISDN PRI";
01382    case SIG_SF:
01383       return "SF (Tone) Immediate";
01384    case SIG_SFWINK:
01385       return "SF (Tone) Wink";
01386    case SIG_SF_FEATD:
01387       return "SF (Tone) with Feature Group D (DTMF)";
01388    case SIG_SF_FEATDMF:
01389       return "SF (Tone) with Feature Group D (MF)";
01390    case SIG_SF_FEATB:
01391       return "SF (Tone) with Feature Group B (MF)";
01392    case SIG_GR303FXOKS:
01393       return "GR-303 with FXOKS";
01394    case SIG_GR303FXSKS:
01395       return "GR-303 with FXSKS";
01396    case SIG_GSM:
01397       return "GSM";
01398    case 0:
01399       return "Pseudo";
01400    default:
01401       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01402       return buf;
01403    }
01404 }

static int zt_answer ( struct ast_channel ast  )  [static]

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

02998 {
02999    struct zt_pvt *p = ast->tech_pvt;
03000    int res = 0;
03001    int index;
03002    int oldstate = ast->_state;
03003    ast_setstate(ast, AST_STATE_UP);
03004    ast_mutex_lock(&p->lock);
03005    index = zt_get_index(ast, p, 0);
03006    if (index < 0)
03007       index = SUB_REAL;
03008    /* nothing to do if a radio channel */
03009    if ((p->radio || (p->oprmode < 0))) {
03010       ast_mutex_unlock(&p->lock);
03011       return 0;
03012    }
03013    switch (p->sig) {
03014    case SIG_FXSLS:
03015    case SIG_FXSGS:
03016    case SIG_FXSKS:
03017       p->ringt = 0;
03018       /* Fall through */
03019    case SIG_EM:
03020    case SIG_EM_E1:
03021    case SIG_EMWINK:
03022    case SIG_FEATD:
03023    case SIG_FEATDMF:
03024    case SIG_FEATDMF_TA:
03025    case SIG_E911:
03026    case SIG_FGC_CAMA:
03027    case SIG_FGC_CAMAMF:
03028    case SIG_FEATB:
03029    case SIG_SF:
03030    case SIG_SFWINK:
03031    case SIG_SF_FEATD:
03032    case SIG_SF_FEATDMF:
03033    case SIG_SF_FEATB:
03034    case SIG_FXOLS:
03035    case SIG_FXOGS:
03036    case SIG_FXOKS:
03037       /* Pick up the line */
03038       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03039       if (p->hanguponpolarityswitch) {
03040          gettimeofday(&p->polaritydelaytv, NULL);
03041       }
03042       res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
03043       tone_zone_play_tone(p->subs[index].zfd, -1);
03044       p->dialing = 0;
03045       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03046          if (oldstate == AST_STATE_RINGING) {
03047             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03048             tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, -1);
03049             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03050             p->owner = p->subs[SUB_REAL].owner;
03051          }
03052       }
03053       if (p->sig & __ZT_SIG_FXS) {
03054          zt_enable_ec(p);
03055          zt_train_ec(p);
03056       }
03057       break;
03058 #ifdef HAVE_PRI
03059    case SIG_PRI:
03060       /* Send a pri acknowledge */
03061       if (!pri_grab(p, p->pri)) {
03062          p->proceeding = 1;
03063          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03064          pri_rel(p->pri);
03065          /* stop ignoring inband dtmf */
03066          enable_dtmf_detect(p);
03067       } else {
03068          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03069          res = -1;
03070       }
03071       /* the audio path is complete now, train the echo canceler */
03072       zt_train_ec(p);
03073       break;
03074 #endif
03075 #ifdef HAVE_GSMAT
03076    case SIG_GSM:
03077       if (p->gsm.modul) {
03078           gsm_answer(p->gsm.modul);
03079       }
03080       break;
03081 #endif
03082    case 0:
03083       ast_mutex_unlock(&p->lock);
03084       return 0;
03085    default:
03086       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03087       res = -1;
03088    }
03089    ast_mutex_unlock(&p->lock);
03090    return res;
03091 }

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

References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verbose(), ast_waitfor_n(), ast_write(), zt_pvt::channel, disable_dtmf_detect(), zt_pvt::echocanbridged, enable_dtmf_detect(), 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().

03418 {
03419    struct ast_channel *who;
03420    struct zt_pvt *p0, *p1, *op0, *op1;
03421    struct zt_pvt *master = NULL, *slave = NULL;
03422    struct ast_frame *f;
03423    int inconf = 0;
03424    int nothingok = 1;
03425    int ofd0, ofd1;
03426    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03427    int os0 = -1, os1 = -1;
03428    int priority = 0;
03429    struct ast_channel *oc0, *oc1;
03430    enum ast_bridge_result res;
03431 
03432 #ifdef PRI_2BCT
03433    int triedtopribridge = 0;
03434    q931_call *q931c0 = NULL, *q931c1 = NULL;
03435 #endif
03436 
03437    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
03438       There is code below to handle it properly until DTMF is actually seen,
03439       but due to currently unresolved issues it's ignored...
03440    */
03441 
03442    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03443       return AST_BRIDGE_FAILED_NOWARN;
03444 
03445    ast_mutex_lock(&c0->lock);
03446    while (ast_mutex_trylock(&c1->lock)) {
03447       ast_mutex_unlock(&c0->lock);
03448       usleep(1);
03449       ast_mutex_lock(&c0->lock);
03450    }
03451 
03452    p0 = c0->tech_pvt;
03453    p1 = c1->tech_pvt;
03454    /* cant do pseudo-channels here */
03455    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03456       ast_mutex_unlock(&c0->lock);
03457       ast_mutex_unlock(&c1->lock);
03458       return AST_BRIDGE_FAILED_NOWARN;
03459    }
03460 
03461    oi0 = zt_get_index(c0, p0, 0);
03462    oi1 = zt_get_index(c1, p1, 0);
03463    if ((oi0 < 0) || (oi1 < 0)) {
03464       ast_mutex_unlock(&c0->lock);
03465       ast_mutex_unlock(&c1->lock);
03466       return AST_BRIDGE_FAILED;
03467    }
03468 
03469    op0 = p0 = c0->tech_pvt;
03470    op1 = p1 = c1->tech_pvt;
03471    ofd0 = c0->fds[0];
03472    ofd1 = c1->fds[0];
03473    oc0 = p0->owner;
03474    oc1 = p1->owner;
03475 
03476    if (ast_mutex_trylock(&p0->lock)) {
03477       /* Don't block, due to potential for deadlock */
03478       ast_mutex_unlock(&c0->lock);
03479       ast_mutex_unlock(&c1->lock);
03480       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03481       return AST_BRIDGE_RETRY;
03482    }
03483    if (ast_mutex_trylock(&p1->lock)) {
03484       /* Don't block, due to potential for deadlock */
03485       ast_mutex_unlock(&p0->lock);
03486       ast_mutex_unlock(&c0->lock);
03487       ast_mutex_unlock(&c1->lock);
03488       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03489       return AST_BRIDGE_RETRY;
03490    }
03491 
03492    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03493       if (p0->owner && p1->owner) {
03494          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
03495          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03496             master = p0;
03497             slave = p1;
03498             inconf = 1;
03499          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03500             master = p1;
03501             slave = p0;
03502             inconf = 1;
03503          } else {
03504             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
03505             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03506                p0->channel,
03507                oi0, (p0->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
03508                p0->subs[SUB_REAL].inthreeway, p0->channel,
03509                oi0, (p1->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
03510                p1->subs[SUB_REAL].inthreeway);
03511          }
03512          nothingok = 0;
03513       }
03514    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03515       if (p1->subs[SUB_THREEWAY].inthreeway) {
03516          master = p1;
03517          slave = p0;
03518          nothingok = 0;
03519       }
03520    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03521       if (p0->subs[SUB_THREEWAY].inthreeway) {
03522          master = p0;
03523          slave = p1;
03524          nothingok = 0;
03525       }
03526    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03527       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
03528          don't put us in anything */
03529       if (p1->subs[SUB_CALLWAIT].inthreeway) {
03530          master = p1;
03531          slave = p0;
03532          nothingok = 0;
03533       }
03534    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03535       /* Same as previous */
03536       if (p0->subs[SUB_CALLWAIT].inthreeway) {
03537          master = p0;
03538          slave = p1;
03539          nothingok = 0;
03540       }
03541    }
03542    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03543       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03544    if (master && slave) {
03545       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
03546          in an active threeway call with a channel that is ringing, we should
03547          indicate ringing. */
03548       if ((oi1 == SUB_THREEWAY) && 
03549           p1->subs[SUB_THREEWAY].inthreeway && 
03550           p1->subs[SUB_REAL].owner && 
03551           p1->subs[SUB_REAL].inthreeway && 
03552           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03553          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03554          tone_zone_play_tone(p0->subs[oi0].zfd, ZT_TONE_RINGTONE);
03555          os1 = p1->subs[SUB_REAL].owner->_state;
03556       } else {
03557          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03558          tone_zone_play_tone(p0->subs[oi0].zfd, -1);
03559       }
03560       if ((oi0 == SUB_THREEWAY) && 
03561           p0->subs[SUB_THREEWAY].inthreeway && 
03562           p0->subs[SUB_REAL].owner && 
03563           p0->subs[SUB_REAL].inthreeway && 
03564           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03565          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03566          tone_zone_play_tone(p1->subs[oi1].zfd, ZT_TONE_RINGTONE);
03567          os0 = p0->subs[SUB_REAL].owner->_state;
03568       } else {
03569          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03570          tone_zone_play_tone(p1->subs[oi0].zfd, -1);
03571       }
03572       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03573          if (!p0->echocanbridged || !p1->echocanbridged) {
03574             /* Disable echo cancellation if appropriate */
03575             zt_disable_ec(p0);
03576             zt_disable_ec(p1);
03577          }
03578       }
03579       zt_link(slave, master);
03580       master->inconference = inconf;
03581    } else if (!nothingok)
03582       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03583 
03584    update_conf(p0);
03585    update_conf(p1);
03586    t0 = p0->subs[SUB_REAL].inthreeway;
03587    t1 = p1->subs[SUB_REAL].inthreeway;
03588 
03589    ast_mutex_unlock(&p0->lock);
03590    ast_mutex_unlock(&p1->lock);
03591 
03592    ast_mutex_unlock(&c0->lock);
03593    ast_mutex_unlock(&c1->lock);
03594 
03595    /* Native bridge failed */
03596    if ((!master || !slave) && !nothingok) {
03597       zt_enable_ec(p0);
03598       zt_enable_ec(p1);
03599       return AST_BRIDGE_FAILED;
03600    }
03601    
03602    if (option_verbose > 2) 
03603       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03604 
03605    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03606       disable_dtmf_detect(op0);
03607 
03608    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03609       disable_dtmf_detect(op1);
03610 
03611    for (;;) {
03612       struct ast_channel *c0_priority[2] = {c0, c1};
03613       struct ast_channel *c1_priority[2] = {c1, c0};
03614 
03615       /* Here's our main loop...  Start by locking things, looking for private parts, 
03616          and then balking if anything is wrong */
03617       ast_mutex_lock(&c0->lock);
03618       while (ast_mutex_trylock(&c1->lock)) {
03619          ast_mutex_unlock(&c0->lock);
03620          usleep(1);
03621          ast_mutex_lock(&c0->lock);
03622       }
03623 
03624       p0 = c0->tech_pvt;
03625       p1 = c1->tech_pvt;
03626 
03627       if (op0 == p0)
03628          i0 = zt_get_index(c0, p0, 1);
03629       if (op1 == p1)
03630          i1 = zt_get_index(c1, p1, 1);
03631       ast_mutex_unlock(&c0->lock);
03632       ast_mutex_unlock(&c1->lock);
03633 
03634       if (!timeoutms || 
03635           (op0 != p0) ||
03636           (op1 != p1) || 
03637           (ofd0 != c0->fds[0]) || 
03638           (ofd1 != c1->fds[0]) ||
03639           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
03640           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
03641           (oc0 != p0->owner) || 
03642           (oc1 != p1->owner) ||
03643           (t0 != p0->subs[SUB_REAL].inthreeway) ||
03644           (t1 != p1->subs[SUB_REAL].inthreeway) ||
03645           (oi0 != i0) ||
03646           (oi1 != i1)) {
03647          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03648             op0->channel, oi0, op1->channel, oi1);
03649          res = AST_BRIDGE_RETRY;
03650          goto return_from_bridge;
03651       }
03652 
03653 #ifdef PRI_2BCT
03654       q931c0 = p0->call;
03655       q931c1 = p1->call;
03656       if (p0->transfer && p1->transfer 
03657           && q931c0 && q931c1 
03658           && !triedtopribridge) {
03659          pri_channel_bridge(q931c0, q931c1);
03660          triedtopribridge = 1;
03661       }
03662 #endif
03663 
03664       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03665       if (!who) {
03666          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03667          continue;
03668       }
03669       f = ast_read(who);
03670       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03671          *fo = f;
03672          *rc = who;
03673          res = AST_BRIDGE_COMPLETE;
03674          goto return_from_bridge;
03675       }
03676       if (f->frametype == AST_FRAME_DTMF) {
03677          if ((who == c0) && p0->pulsedial) {
03678             ast_write(c1, f);
03679          } else if ((who == c1) && p1->pulsedial) {
03680             ast_write(c0, f);
03681          } else {
03682             *fo = f;
03683             *rc = who;
03684             res = AST_BRIDGE_COMPLETE;
03685             goto return_from_bridge;
03686          }
03687       }
03688       ast_frfree(f);
03689       
03690       /* Swap who gets priority */
03691       priority = !priority;
03692    }
03693 
03694 return_from_bridge:
03695    if (op0 == p0)
03696       zt_enable_ec(p0);
03697 
03698    if (op1 == p1)
03699       zt_enable_ec(p1);
03700 
03701    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03702       enable_dtmf_detect(op0);
03703 
03704    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03705       enable_dtmf_detect(op1);
03706 
03707    zt_unlink(slave, master, 1);
03708 
03709    return res;
03710 }

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

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

01961 {
01962    struct zt_pvt *p = ast->tech_pvt;
01963    int x, res, index,mysig;
01964    char *c, *n, *l;
01965 #ifdef HAVE_PRI
01966    char *s = NULL;
01967 #endif
01968    char dest[256]; /* must be same length as p->dialdest */
01969    ast_mutex_lock(&p->lock);
01970    ast_copy_string(dest, rdest, sizeof(dest));
01971    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
01972    if ((ast->_state == AST_STATE_BUSY)) {
01973       p->subs[SUB_REAL].needbusy = 1;
01974       ast_mutex_unlock(&p->lock);
01975       return 0;
01976    }
01977    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01978       ast_log(LOG_WARNING, "zt_call called on %s, neither down nor reserved\n", ast->name);
01979       ast_mutex_unlock(&p->lock);
01980       return -1;
01981    }
01982    p->dialednone = 0;
01983    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
01984    {
01985       /* Special pseudo -- automatically up */
01986       ast_setstate(ast, AST_STATE_UP); 
01987       ast_mutex_unlock(&p->lock);
01988       return 0;
01989    }
01990    x = ZT_FLUSH_READ | ZT_FLUSH_WRITE;
01991    res = ioctl(p->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
01992    if (res)
01993       ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
01994    p->outgoing = 1;
01995 
01996    if (IS_DIGITAL(ast->transfercapability)) {
01997        set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
01998    } else {
01999        set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
02000    }
02001 
02002 
02003    mysig = p->sig;
02004    if (p->outsigmod > -1)
02005       mysig = p->outsigmod;
02006 
02007    switch (mysig) {
02008    case SIG_FXOLS:
02009    case SIG_FXOGS:
02010    case SIG_FXOKS:
02011       if (p->owner == ast) {
02012          /* Normal ring, on hook */
02013          
02014          /* Don't send audio while on hook, until the call is answered */
02015          p->dialing = 1;
02016          if (p->use_callerid) {
02017             /* Generate the Caller-ID spill if desired */
02018             if (p->cidspill) {
02019                ast_log(LOG_WARNING, "cidspill already exists??\n");
02020                free(p->cidspill);
02021             }
02022             p->callwaitcas = 0;
02023             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02024                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02025                p->cidpos = 0;
02026                send_callerid(p);
02027             }
02028          }
02029          /* Choose proper cadence */
02030          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02031             if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCADENCE, &cadences[p->distinctivering - 1]))
02032                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s'\n", p->distinctivering, ast->name);
02033             p->cidrings = cidrings[p->distinctivering - 1];
02034          } else {
02035             if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCADENCE, NULL))
02036                ast_log(LOG_WARNING, "Unable to reset default ring on '%s'\n", ast->name);
02037             p->cidrings = p->sendcalleridafter;
02038          }
02039 
02040          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02041          c = strchr(dest, '/');
02042          if (c)
02043             c++;
02044          if (c && (strlen(c) < p->stripmsd)) {
02045             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02046             c = NULL;
02047          }
02048          if (c) {
02049             p->dop.op = ZT_DIAL_OP_REPLACE;
02050             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02051             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02052          } else {
02053             p->dop.dialstr[0] = '\0';
02054          }
02055          x = ZT_RING;
02056          if (ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x) && (errno != EINPROGRESS)) {
02057             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02058             ast_mutex_unlock(&p->lock);
02059             return -1;
02060          }
02061          p->dialing = 1;
02062       } else {
02063          /* Call waiting call */
02064          p->callwaitrings = 0;
02065          if (ast->cid.cid_num)
02066             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02067          else
02068             p->callwait_num[0] = '\0';
02069          if (ast->cid.cid_name)
02070             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02071          else
02072             p->callwait_name[0] = '\0';
02073          /* Call waiting tone instead */
02074          if (zt_callwait(ast)) {
02075             ast_mutex_unlock(&p->lock);
02076             return -1;
02077          }
02078          /* Make ring-back */
02079          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].zfd, ZT_TONE_RINGTONE))
02080             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02081             
02082       }
02083       n = ast->cid.cid_name;
02084       l = ast->cid.cid_num;
02085       if (l)
02086          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02087       else
02088          p->lastcid_num[0] = '\0';
02089       if (n)
02090          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02091       else
02092          p->lastcid_name[0] = '\0';
02093       ast_setstate(ast, AST_STATE_RINGING);
02094       index = zt_get_index(ast, p, 0);
02095       if (index > -1) {
02096          p->subs[index].needringing = 1;
02097       }
02098       break;
02099    case SIG_FXSLS:
02100    case SIG_FXSGS:
02101    case SIG_FXSKS:
02102    case SIG_EMWINK:
02103    case SIG_EM:
02104    case SIG_EM_E1:
02105    case SIG_FEATD:
02106    case SIG_FEATDMF:
02107    case SIG_E911:
02108    case SIG_FGC_CAMA:
02109    case SIG_FGC_CAMAMF:
02110    case SIG_FEATB:
02111    case SIG_SFWINK:
02112    case SIG_SF:
02113    case SIG_SF_FEATD:
02114    case SIG_SF_FEATDMF:
02115    case SIG_FEATDMF_TA:
02116    case SIG_SF_FEATB:
02117       c = strchr(dest, '/');
02118       if (c)
02119          c++;
02120       else
02121          c = "";
02122       if (strlen(c) < p->stripmsd) {
02123          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02124          ast_mutex_unlock(&p->lock);
02125          return -1;
02126       }
02127 #ifdef HAVE_PRI
02128       /* Start the trunk, if not GR-303 */
02129       if (!p->pri) {
02130 #endif
02131          x = ZT_START;
02132          res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
02133          if (res < 0) {
02134             if (errno != EINPROGRESS) {
02135                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02136                ast_mutex_unlock(&p->lock);
02137                return -1;
02138             }
02139          }
02140 #ifdef HAVE_PRI
02141       }
02142 #endif
02143       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02144       p->dop.op = ZT_DIAL_OP_REPLACE;
02145 
02146       c += p->stripmsd;
02147 
02148       switch (mysig) {
02149       case SIG_FEATD:
02150          l = ast->cid.cid_num;
02151          if (l) 
02152             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02153          else
02154             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02155          break;
02156       case SIG_FEATDMF:
02157          l = ast->cid.cid_num;
02158          if (l) 
02159             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02160          else
02161             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02162          break;
02163       case SIG_FEATDMF_TA:
02164       {
02165          const char *cic, *ozz;
02166 
02167          /* If you have to go through a Tandem Access point you need to use this */
02168          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02169          if (!ozz)
02170             ozz = defaultozz;
02171          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02172          if (!cic)
02173             cic = defaultcic;
02174          if (!ozz || !cic) {
02175             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02176             ast_mutex_unlock(&p->lock);
02177             return -1;
02178          }
02179          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02180          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02181          p->whichwink = 0;
02182       }
02183          break;
02184       case SIG_E911:
02185          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02186          break;
02187       case SIG_FGC_CAMA:
02188          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02189          break;
02190       case SIG_FGC_CAMAMF:
02191       case SIG_FEATB:
02192          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02193          break;
02194       default:
02195          if (p->pulse)
02196             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02197          else
02198             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02199          break;
02200       }
02201 
02202       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02203          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02204          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02205          p->echorest[sizeof(p->echorest) - 1] = '\0';
02206          p->echobreak = 1;
02207          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02208       } else
02209          p->echobreak = 0;
02210       if (!res) {
02211          if (ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop)) {
02212             x = ZT_ONHOOK;
02213             ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
02214             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno));
02215             ast_mutex_unlock(&p->lock);
02216             return -1;
02217          }
02218       } else
02219          ast_log(LOG_DEBUG, "Deferring dialing...\n");
02220       p->dialing = 1;
02221       if (ast_strlen_zero(c))
02222          p->dialednone = 1;
02223       ast_setstate(ast, AST_STATE_DIALING);
02224       break;
02225    case 0:
02226       /* Special pseudo -- automatically up*/
02227       ast_setstate(ast, AST_STATE_UP);
02228       break;      
02229    case SIG_PRI:
02230       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02231       p->dialdest[0] = '\0';
02232       disable_dtmf_detect(p);
02233       break;
02234    case SIG_GSM:
02235 #ifdef HAVE_GSMAT
02236       if (p->gsm.modul) {
02237           c = strchr(dest, '/');
02238           if (c)
02239          c++;
02240           else
02241          c = dest;
02242           ast_mutex_lock(&p->gsm.lock);
02243           if (gsm_dial(p->gsm.modul, p->use_callingpres ? ast->cid.cid_pres : 0, c)) {
02244          ast_log(LOG_WARNING, "dialing failed on channel %d\n", p->channel);
02245          ast_mutex_unlock(&p->gsm.lock);
02246          ast_mutex_unlock(&p->lock);
02247          return -1;
02248           }
02249           ast_mutex_unlock(&p->gsm.lock);
02250       }
02251 #endif
02252       break;
02253    default:
02254       ast_log(LOG_DEBUG, "not yet implemented\n");
02255       ast_mutex_unlock(&p->lock);
02256       return -1;
02257    }
02258 #ifdef HAVE_PRI
02259    if (p->pri) {
02260       struct pri_sr *sr;
02261 #ifdef SUPPORT_USERUSER
02262       const char *useruser;
02263 #endif
02264       int pridialplan;
02265       int dp_strip;
02266       int prilocaldialplan;
02267       int ldp_strip;
02268       int exclusive;
02269       const char *rr_str;
02270       int redirect_reason;
02271 
02272       if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
02273           // pass NO audio when ringing an isdn phone
02274           p->dialing = 1;
02275           // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
02276       }
02277 
02278       c = strchr(dest, '/');
02279       if (c)
02280          c++;
02281       else
02282          c = dest;
02283 
02284       l = NULL;
02285       n = NULL;
02286 
02287       if (!p->hidecallerid) {
02288          l = ast->cid.cid_num;
02289          if (!p->hidecalleridname) {
02290             n = ast->cid.cid_name;
02291          }
02292       }
02293 
02294 
02295       if (strlen(c) < p->stripmsd) {
02296          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02297          ast_mutex_unlock(&p->lock);
02298          return -1;
02299       }
02300       strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
02301       if (mysig != SIG_FXSKS) {
02302          p->dop.op = ZT_DIAL_OP_REPLACE;
02303          s = strchr(c + p->stripmsd, 'w');
02304          if (s) {
02305             if (strlen(s) > 1)
02306                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02307             else
02308                p->dop.dialstr[0] = '\0';
02309             *s = '\0';
02310          } else {
02311             p->dop.dialstr[0] = '\0';
02312          }
02313       }
02314       if (pri_grab(p, p->pri)) {
02315          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02316          ast_mutex_unlock(&p->lock);
02317          return -1;
02318       }
02319       if (!(p->call = pri_new_call(p->pri->pri))) {
02320          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02321          pri_rel(p->pri);
02322          ast_mutex_unlock(&p->lock);
02323          return -1;
02324       } else {
02325       // ast_log(LOG_NOTICE, "call %d\n", p->call);
02326       }
02327       if (!(sr = pri_sr_new())) {
02328          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02329          pri_rel(p->pri);
02330          ast_mutex_unlock(&p->lock);
02331       }
02332       if (p->bearer || (mysig == SIG_FXSKS)) {
02333          if (p->bearer) {
02334             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);
02335             p->bearer->call = p->call;
02336          } else
02337             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02338          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02339       }
02340       p->digital = IS_DIGITAL(ast->transfercapability);
02341       /* Add support for exclusive override */
02342       if (p->priexclusive)
02343          exclusive = 1;
02344       else {
02345       /* otherwise, traditional behavior */
02346          if (p->pri->nodetype == PRI_NETWORK)
02347             exclusive = 0;
02348          else
02349             exclusive = 1;
02350       }
02351       
02352       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02353       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02354                (p->digital ? -1 : 
02355                   ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
02356       if (p->pri->facilityenable)
02357          pri_facility_enable(p->pri->pri);
02358 
02359       if (option_verbose > 2)
02360          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02361       dp_strip = 0;
02362       pridialplan = p->pri->dialplan - 1;
02363       if (pridialplan == -2) { /* compute dynamically */
02364          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02365             dp_strip = strlen(p->pri->internationalprefix);
02366             pridialplan = PRI_INTERNATIONAL_ISDN;
02367          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02368             dp_strip = strlen(p->pri->nationalprefix);
02369             pridialplan = PRI_NATIONAL_ISDN;
02370          } else {
02371             pridialplan = PRI_LOCAL_ISDN;
02372          }
02373       }
02374       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02375 
02376       ldp_strip = 0;
02377       prilocaldialplan = p->pri->localdialplan - 1;
02378       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
02379          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02380             ldp_strip = strlen(p->pri->internationalprefix);
02381             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02382          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02383             ldp_strip = strlen(p->pri->nationalprefix);
02384             prilocaldialplan = PRI_NATIONAL_ISDN;
02385          } else {
02386             prilocaldialplan = PRI_LOCAL_ISDN;
02387          }
02388       }
02389       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02390          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02391       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02392          if (!strcasecmp(rr_str, "UNKNOWN"))
02393             redirect_reason = 0;
02394          else if (!strcasecmp(rr_str, "BUSY"))
02395             redirect_reason = 1;
02396          else if (!strcasecmp(rr_str, "NO_REPLY"))
02397             redirect_reason = 2;
02398          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02399             redirect_reason = 15;
02400          else
02401             redirect_reason = PRI_REDIR_UNCONDITIONAL;
02402       } else
02403          redirect_reason = PRI_REDIR_UNCONDITIONAL;
02404       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02405 
02406 #ifdef SUPPORT_USERUSER
02407       /* User-user info */
02408       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02409 
02410       if (useruser)
02411          pri_sr_set_useruser(sr, useruser);
02412 #endif
02413 
02414       if (pri_setup(p->pri->pri, p->call, sr)) {
02415          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
02416             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02417          pri_rel(p->pri);
02418          ast_mutex_unlock(&p->lock);
02419          pri_sr_free(sr);
02420          return -1;
02421       }
02422       pri_sr_free(sr);
02423       ast_setstate(ast, AST_STATE_DIALING);
02424       pri_rel(p->pri);
02425    }
02426 #endif      
02427    ast_mutex_unlock(&p->lock);
02428    return 0;
02429 }

static int zt_callwait ( struct ast_channel ast  )  [static]

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

01933 {
01934    struct zt_pvt *p = ast->tech_pvt;
01935    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01936    if (p->cidspill) {
01937       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01938       free(p->cidspill);
01939    }
01940    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01941       return -1;
01942    save_conference(p);
01943    /* Silence */
01944    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01945    if (!p->callwaitrings && p->callwaitingcallerid) {
01946       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01947       p->callwaitcas = 1;
01948       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01949    } else {
01950       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01951       p->callwaitcas = 0;
01952       p->cidlen = 2400 + READ_SIZE * 4;
01953    }
01954    p->cidpos = 0;
01955    send_callerid(p);
01956    
01957    return 0;
01958 }

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

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

static void zt_close ( int  fd  )  [static]

Definition at line 1097 of file chan_zap.c.

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

01098 {
01099    if (fd > 0)
01100       close(fd);
01101 }

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

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

01816 {
01817    int x, y, res;
01818    x = muted;
01819    if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
01820       y = 1;
01821       res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
01822       if (res)
01823          ast_log(LOG_WARNING, "Unable to set audio mode on '%d'\n", p->channel);
01824    }
01825    res = ioctl(p->subs[SUB_REAL].zfd, ZT_CONFMUTE, &x);
01826    if (res < 0)
01827       ast_log(LOG_WARNING, "zt confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01828    return res;
01829 }

static int zt_devicestate ( void *  data  )  [static]

Definition at line 836 of file chan_zap.c.

References ast_channel::_state, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), CHAN_PSEUDO, zt_pvt::channel, zt_pvt::cid_num, DCHAN_UP, zt_pvt::dnid, zt_pvt::group, iflist, zt_pvt::lock, lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, zt_pvt::next, NUM_DCHANS, zt_pvt::outgoing, zt_pvt::owner, s, and strsep().

00837 {
00838    int groupmatch = 0;
00839    int channelmatch = 0;
00840    struct zt_pvt *p;
00841    char *dest=NULL;
00842    int x;
00843    char *s;
00844    char opt=0;
00845    int res, y=0;
00846    struct zt_pvt *exit, *start, *end;
00847    ast_mutex_t *lock;
00848 
00849 // ast_log(LOG_NOTICE, "data = %s\n", (char *)data);
00850    return AST_DEVICE_UNKNOWN;
00851    
00852    /* Assume we're locking the iflock */
00853    lock = &iflock;
00854    start = iflist;
00855    end = ifend;
00856 
00857    if (data) {
00858       dest = ast_strdupa((char *)data);
00859    } else {
00860       ast_log(LOG_WARNING, "Channel requested with no data\n");
00861       return AST_DEVICE_INVALID;
00862    }
00863    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
00864       /* Retrieve the group number */
00865       char *stringp=NULL;
00866       stringp=dest + 1;
00867       s = strsep(&stringp, "/");
00868       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
00869          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
00870          return AST_DEVICE_INVALID;
00871       }
00872       groupmatch = 1 << x;
00873    } else {
00874       char *stringp=NULL;
00875       stringp=dest;
00876       s = strsep(&stringp, "/");
00877       p = iflist;
00878       if (!strcasecmp(s, "pseudo")) {
00879          /* Special case for pseudo */
00880          x = CHAN_PSEUDO;
00881          channelmatch = x;
00882          /* bail out */
00883          return AST_DEVICE_INVALID;
00884       } 
00885 
00886       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
00887          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
00888          return AST_DEVICE_INVALID;
00889       } else {
00890          channelmatch = x;
00891          ast_log(LOG_NOTICE, "channelmatch = %d\n", channelmatch);
00892       }
00893    }
00894    /* Search for an unowned channel */
00895    if (ast_mutex_lock(lock)) {
00896       ast_log(LOG_ERROR, "Unable to lock interface list???\n");
00897       return AST_DEVICE_INVALID;
00898    }
00899    p = iflist;
00900    exit = iflist;
00901    res = AST_DEVICE_INVALID; /* start pessimistic */
00902    while(p) {
00903       if (p) {
00904           ast_mutex_lock(&p->lock);
00905           if ((groupmatch && ((p->group & groupmatch) != 0)) || (channelmatch && (p->channel == channelmatch))) {
00906 #ifdef ZAPATA_PRI
00907          if (p->pri) {
00908              for(d=0;d<NUM_DCHANS;d++) {
00909             if (p->pri->dchanavail[d] & DCHAN_UP) {
00910                    res = AST_DEVICE_UNKNOWN;
00911             }
00912              }
00913          }
00914 #endif
00915          if ((!ast_strlen_zero(p->cid_num) && (strncasecmp(p->cid_num, dest, strlen(p->cid_num)))) || (!ast_strlen_zero(p->dnid) && (strncasecmp(p->dnid, dest, strlen(p->dnid))))) {
00916              res = AST_DEVICE_UNKNOWN;
00917              if (p->owner) {
00918                 if ((p->owner->_state == AST_STATE_RINGING) && (p->outgoing)) {
00919                   res = AST_DEVICE_RINGING;
00920                 }
00921                 if (((p->owner->_state == AST_STATE_RINGING) && (!p->outgoing)) || (p->owner->_state == AST_STATE_UP) || (p->owner->_state == AST_STATE_DIALING) || (p->owner->_state == AST_STATE_RESERVED) || (p->owner->_state == AST_STATE_RING)){
00922                   res = AST_DEVICE_INUSE;
00923                 }
00924              }
00925              if ((res == AST_DEVICE_INUSE) || (res == AST_DEVICE_RINGING)) {
00926             /* stop searching now, one non-idle channel is sufficient */
00927             ast_mutex_unlock(&p->lock);
00928             break;
00929              }
00930          }
00931           }
00932           ast_mutex_unlock(&p->lock);
00933       }  
00934       p = p->next;
00935    }
00936    ast_mutex_unlock(lock);
00937 
00938    return res;
00939 
00940 }

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

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

01185 {
01186    struct zt_pvt *pvt;
01187    int index;
01188    int dtmf = -1;
01189    
01190    pvt = chan->tech_pvt;
01191 
01192    ast_mutex_lock(&pvt->lock);
01193 
01194    index = zt_get_index(chan, pvt, 0);
01195 
01196    if ((index != SUB_REAL) || !pvt->owner)
01197       goto out;
01198 
01199 #ifdef HAVE_PRI
01200    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01201       if (pvt->setup_ack) {
01202          if (!pri_grab(pvt, pvt->pri)) {
01203             pri_information(pvt->pri->pri, pvt->call, digit);
01204             pri_rel(pvt->pri);
01205          } else
01206             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01207       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01208          int res;
01209          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01210          res = strlen(pvt->dialdest);
01211          pvt->dialdest[res++] = digit;
01212          pvt->dialdest[res] = '\0';
01213       }
01214       goto out;
01215    }
01216 #endif
01217    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01218       goto out;
01219 
01220    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &dtmf)) {
01221       int res;
01222       ZT_DIAL_OPERATION zo = {
01223          .op = ZT_DIAL_OP_APPEND,
01224          .dialstr[0] = 'T',
01225          .dialstr[1] = digit,
01226          .dialstr[2] = 0,
01227       };
01228       if ((res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_DIAL, &zo)))
01229          ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
01230       else
01231          pvt->dialing = 1;
01232    } else {
01233       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01234       pvt->dialing = 1;
01235       pvt->begindigit = digit;
01236    }
01237 
01238 out:
01239    ast_mutex_unlock(&pvt->lock);
01240 
01241    return 0;
01242 }

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

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

01245 {
01246    struct zt_pvt *pvt;
01247    int res = 0;
01248    int index;
01249    int x;
01250    
01251    pvt = chan->tech_pvt;
01252 
01253    ast_mutex_lock(&pvt->lock);
01254    
01255    index = zt_get_index(chan, pvt, 0);
01256 
01257    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01258       goto out;
01259 
01260 #ifdef HAVE_PRI
01261    /* This means that the digit was already sent via PRI signalling */
01262    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01263       goto out;
01264 #endif
01265 
01266    if (pvt->begindigit) {
01267       x = -1;
01268       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01269       res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &x);
01270       pvt->dialing = 0;
01271       pvt->begindigit = 0;
01272    }
01273 
01274 out:
01275    ast_mutex_unlock(&pvt->lock);
01276 
01277    return res;
01278 }

static void zt_disable_ec ( struct zt_pvt p  )  [static]

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

01648 {
01649    int x;
01650    int res;
01651    if (p->echocancel) {
01652       x = 0;
01653       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01654       if (res)
01655          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
01656       else if (option_debug)
01657          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01658    }
01659    p->echocanon = 0;
01660 }

static void zt_enable_ec ( struct zt_pvt p  )  [static]

Definition at line 1593 of file chan_zap.c.

References ast_log(), zt_pvt::channel, zt_pvt::digital, zt_pvt::echocancel, zt_pvt::echocanon, 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 app_zapEC(), handle_init_event(), ss_thread(), zt_answer(), zt_bridge(), zt_handle_event(), and zt_setoption().

01594 {
01595    int x;
01596    int res;
01597    if (!p)
01598       return;
01599    if (p->faxhandled)  {
01600       ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
01601       return;
01602    }
01603    if (p->echocanon) {
01604       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01605       return;
01606    }
01607    if (p->digital) {
01608       ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
01609       return;
01610    }
01611    if (p->echocancel) {
01612       if (p->sig == SIG_PRI) {
01613          x = 1;
01614          res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x);
01615          if (res)
01616             ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d\n", p->channel);
01617       }
01618       x = p->echocancel;
01619       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
01620       if (res) 
01621          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d\n", p->channel);
01622       else {
01623          p->echocanon = 1;
01624          if (option_debug)
01625             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01626       }
01627    } else if (option_debug)
01628       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01629 }

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

Definition at line 4886 of file chan_zap.c.

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

04887 {
04888    struct zt_pvt *p = ast->tech_pvt;
04889    struct ast_frame *f;
04890    ast_mutex_lock(&p->lock);
04891    f = __zt_exception(ast);
04892    ast_mutex_unlock(&p->lock);
04893    return f;
04894 }

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

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

03713 {
03714    struct zt_pvt *p = newchan->tech_pvt;
03715    int x;
03716    if (newchan && newchan->tech_pvt) {
03717        p = newchan->tech_pvt;
03718    }
03719    if (!p) {
03720        if (newchan) {
03721       ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
03722        }
03723        return 0;
03724    }
03725    ast_mutex_lock(&p->lock);
03726    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03727    if (p->owner == oldchan) {
03728       p->owner = newchan;
03729    }
03730    for (x = 0; x < 3; x++)
03731       if (p->subs[x].owner == oldchan) {
03732          if (!x)
03733             zt_unlink(NULL, p, 0);
03734          p->subs[x].owner = newchan;
03735       }
03736    if (newchan->_state == AST_STATE_RINGING) 
03737       zt_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03738    update_conf(p);
03739    ast_mutex_unlock(&p->lock);
03740    return 0;
03741 }

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

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

03279 {
03280    struct zt_pvt *p = chan->tech_pvt;
03281    
03282    if (!strcasecmp(data, "rxgain")) {
03283       ast_mutex_lock(&p->lock);
03284       snprintf(buf, len, "%f", p->rxgain);
03285       ast_mutex_unlock(&p->lock);   
03286    } else if (!strcasecmp(data, "txgain")) {
03287       ast_mutex_lock(&p->lock);
03288       snprintf(buf, len, "%f", p->txgain);
03289       ast_mutex_unlock(&p->lock);   
03290    } else {
03291       ast_copy_string(buf, "", len);
03292    }
03293    return 0;
03294 }

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

Avoid the silly zt_getevent which ignores a bunch of events.

Definition at line 264 of file chan_zap.c.

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

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

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

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

00943 {
00944    int res;
00945    if (p->subs[0].owner == ast)
00946       res = 0;
00947    else if (p->subs[1].owner == ast)
00948       res = 1;
00949    else if (p->subs[2].owner == ast)
00950       res = 2;
00951    else {
00952       res = -1;
00953       if (!nullok)
00954          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
00955    }
00956    return res;
00957 }

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

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

03890 {
03891    struct zt_pvt *p = ast->tech_pvt;
03892    struct ast_frame *f = *dest;
03893 
03894    if (option_debug)
03895       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
03896 
03897    if (p->confirmanswer) {
03898       if (option_debug)
03899          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
03900       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
03901          of a DTMF digit */
03902       p->subs[index].f.frametype = AST_FRAME_CONTROL;
03903       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03904       *dest = &p->subs[index].f;
03905       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
03906       p->confirmanswer = 0;
03907    } else if (p->callwaitcas) {
03908       if ((f->subclass == 'A') || (f->subclass == 'D')) {
03909          if (option_debug)
03910             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
03911          if (p->cidspill)
03912             free(p->cidspill);
03913          send_cwcidspill(p);
03914       }
03915       if ((f->subclass != 'm') && (f->subclass != 'u')) 
03916          p->callwaitcas = 0;
03917       p->subs[index].f.frametype = AST_FRAME_NULL;
03918       p->subs[index].f.subclass = 0;
03919       *dest = &p->subs[index].f;
03920    } else if (f->subclass == 'f') {
03921       /* Fax tone -- Handle and return NULL */
03922       if ((p->callprogress & 0x6) && !p->faxhandled) {
03923          p->faxhandled++;
03924          if (strcmp(ast->exten, "fax")) {
03925             const char *target_context = S_OR(ast->macrocontext, ast->context);
03926 
03927             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
03928                if (option_verbose > 2)
03929                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
03930                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
03931                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
03932                if (ast_async_goto(ast, target_context, "fax", 1))
03933                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
03934             } else {
03935                 if (option_verbose > 2)
03936                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
03937             }
03938          } else if (option_debug)
03939             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
03940       } else if (option_debug)
03941             ast_log(LOG_DEBUG, "Fax already handled\n");
03942       zt_confmute(p, 0);
03943       p->subs[index].f.frametype = AST_FRAME_NULL;
03944       p->subs[index].f.subclass = 0;
03945       *dest = &p->subs[index].f;
03946    } else if (f->subclass == 'm') {
03947       /* Confmute request */
03948       zt_confmute(p, 1);
03949       p->subs[index].f.frametype = AST_FRAME_NULL;
03950       p->subs[index].f.subclass = 0;
03951       *dest = &p->subs[index].f;    
03952    } else if (f->subclass == 'u') {
03953       /* Unmute */
03954       zt_confmute(p, 0);
03955       p->subs[index].f.frametype = AST_FRAME_NULL;
03956       p->subs[index].f.subclass = 0;
03957       *dest = &p->subs[index].f;    
03958    } else
03959       zt_confmute(p, 0);
03960 }

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

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

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

static int zt_hangup ( struct ast_channel ast  )  [static]

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

02643 {
02644    int res;
02645    int index,x, law;
02646    /*static int restore_gains(struct zt_pvt *p);*/
02647    struct zt_pvt *p = ast->tech_pvt;
02648    struct zt_pvt *tmp = NULL;
02649    struct zt_pvt *prev = NULL;
02650    ZT_PARAMS par;
02651 
02652    if (option_debug)
02653       ast_log(LOG_DEBUG, "zt_hangup(%s)\n", ast->name);
02654    if (!ast->tech_pvt) {
02655       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02656       return 0;
02657    }
02658    
02659    ast_mutex_lock(&p->lock);
02660    
02661    index = zt_get_index(ast, p, 1);
02662 
02663    if (p->sig == SIG_PRI) {
02664       x = 1;
02665       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02666    }
02667 
02668    x = 0;
02669    zt_confmute(p, 0);
02670    restore_gains(p);
02671    if (p->origcid_num) {
02672       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02673       free(p->origcid_num);
02674       p->origcid_num = NULL;
02675    }  
02676    if (p->origcid_name) {
02677       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02678       free(p->origcid_name);
02679       p->origcid_name = NULL;
02680    }  
02681    if (p->dsp)
02682       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02683    if (p->exten)
02684       p->exten[0] = '\0';
02685 
02686    if (option_debug)
02687       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02688       p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
02689 
02690    if (index > -1) {
02691       /* Real channel, do some fixup */
02692       p->subs[index].owner = NULL;
02693       p->subs[index].needanswer = 0;
02694       p->subs[index].needflash = 0;
02695       p->subs[index].needringing = 0;
02696       p->subs[index].needbusy = 0;
02697       p->subs[index].needcongestion = 0;
02698       p->subs[index].linear = 0;
02699       p->subs[index].needcallerid = 0;
02700       p->polarity = POLARITY_IDLE;
02701       zt_setlinear(p->subs[index].zfd, 0);
02702       if (index == SUB_REAL) {
02703          if ((p->subs[SUB_CALLWAIT].zfd > -1) && (p->subs[SUB_THREEWAY].zfd > -1)) {
02704             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02705             if (p->subs[SUB_CALLWAIT].inthreeway) {
02706                /* We had flipped over to answer a callwait and now it's gone */
02707                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02708                /* Move to the call-wait, but un-own us until they flip back. */
02709                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02710                unalloc_sub(p, SUB_CALLWAIT);
02711                p->owner = NULL;
02712             } else {
02713                /* The three way hung up, but we still have a call wait */
02714                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
02715                swap_subs(p, SUB_THREEWAY, SUB_REAL);
02716                unalloc_sub(p, SUB_THREEWAY);
02717                if (p->subs[SUB_REAL].inthreeway) {
02718                   /* This was part of a three way call.  Immediately make way for
02719                      another call */
02720                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02721                   p->owner = p->subs[SUB_REAL].owner;
02722                } else {
02723                   /* This call hasn't been completed yet...  Set owner to NULL */
02724                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02725                   p->owner = NULL;
02726                }
02727                p->subs[SUB_REAL].inthreeway = 0;
02728             }
02729          } else if (p->subs[SUB_CALLWAIT].zfd > -1) {
02730             /* Move to the call-wait and switch back to them. */
02731             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02732             unalloc_sub(p, SUB_CALLWAIT);
02733             p->owner = p->subs[SUB_REAL].owner;
02734             if (p->owner->_state != AST_STATE_UP)
02735                p->subs[SUB_REAL].needanswer = 1;
02736             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02737                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02738          } else if (p->subs[SUB_THREEWAY].zfd > -1) {
02739             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02740             unalloc_sub(p, SUB_THREEWAY);
02741             if (p->subs[SUB_REAL].inthreeway) {
02742                /* This was part of a three way call.  Immediately make way for
02743                   another call */
02744                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02745                p->owner = p->subs[SUB_REAL].owner;
02746             } else {
02747                /* This call hasn't been completed yet...  Set owner to NULL */
02748                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02749                p->owner = NULL;
02750             }
02751             p->subs[SUB_REAL].inthreeway = 0;
02752          }
02753       } else if (index == SUB_CALLWAIT) {
02754          /* Ditch the holding callwait call, and immediately make it availabe */
02755          if (p->subs[SUB_CALLWAIT].inthreeway) {
02756             /* This is actually part of a three way, placed on hold.  Place the third part
02757                on music on hold now */
02758             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02759                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
02760                   S_OR(p->mohsuggest, NULL),
02761                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02762             }
02763             p->subs[SUB_THREEWAY].inthreeway = 0;
02764             /* Make it the call wait now */
02765             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02766             unalloc_sub(p, SUB_THREEWAY);
02767          } else
02768             unalloc_sub(p, SUB_CALLWAIT);
02769       } else if (index == SUB_THREEWAY) {
02770          if (p->subs[SUB_CALLWAIT].inthreeway) {
02771             /* The other party of the three way call is currently in a call-wait state.
02772                Start music on hold for them, and take the main guy out of the third call */
02773             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02774                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
02775                   S_OR(p->mohsuggest, NULL),
02776                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02777             }
02778             p->subs[SUB_CALLWAIT].inthreeway = 0;
02779          }
02780          p->subs[SUB_REAL].inthreeway = 0;
02781          /* If this was part of a three way call index, let us make
02782             another three way call */
02783          unalloc_sub(p, SUB_THREEWAY);
02784       } else {
02785          /* This wasn't any sort of call, but how are we an index? */
02786          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02787       }
02788    }
02789 
02790    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02791       int outgoing = p->outgoing;
02792       p->owner = NULL;
02793       p->ringt = 0;
02794       p->distinctivering = 0;
02795       p->confirmanswer = 0;
02796       p->cidrings = 1;
02797       p->outgoing = 0;
02798       p->digital = 0;
02799       p->faxhandled = 0;
02800       p->pulsedial = 0;
02801       p->onhooktime = time(NULL);
02802 #ifdef HAVE_PRI
02803       p->proceeding = 0;
02804       p->progress = 0;
02805       p->alerting = 0;
02806       p->setup_ack = 0;
02807 #endif      
02808       if (p->dsp) {
02809          ast_dsp_free(p->dsp);
02810          p->dsp = NULL;
02811       }
02812 
02813       law = ZT_LAW_DEFAULT;
02814       res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETLAW, &law);
02815       if (res < 0) 
02816          ast_log(LOG_WARNING, "Unable to set law on channel %d to default\n", p->channel);
02817       /* Perform low level hangup if no owner left */
02818 #ifdef HAVE_PRI
02819       if (p->pri) {
02820 #ifdef SUPPORT_USERUSER
02821          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02822 #endif
02823 
02824          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
02825          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02826             if (!pri_grab(p, p->pri)) {
02827                if (p->alreadyhungup) {
02828                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
02829 
02830 #ifdef SUPPORT_USERUSER
02831                   pri_call_set_useruser(p->call, useruser);
02832 #endif
02833 
02834                   pri_hangup(p->pri->pri, p->call, -1, -1);
02835                   p->call = NULL;
02836                   if (p->bearer) 
02837                      p->bearer->call = NULL;
02838                } else {
02839                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
02840                   int icause = ast->hangupcause ? ast->hangupcause : -1;
02841                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
02842 
02843 #ifdef SUPPORT_USERUSER
02844                   pri_call_set_useruser(p->call, useruser);
02845 #endif
02846 
02847                   p->alreadyhungup = 1;
02848                   if (p->bearer)
02849                      p->bearer->alreadyhungup = 1;
02850                   if (cause) {
02851                      if (atoi(cause))
02852                         icause = atoi(cause);
02853                   }
02854 
02855                   pri_hangup(p->pri->pri, p->call, icause, -1);
02856 
02857                   /* if we send a rel9999ease complete we wont ge no hangup event, so clear the call here */
02858                   if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
02859                       if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING) || (ast->_state == AST_STATE_RESERVED)) {
02860                      p->call = NULL;
02861                       } else {
02862                      ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
02863                      icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
02864                       }
02865                   } 
02866                   
02867                   if (p->pri->nodetype == BRI_NETWORK_PTMP) {
02868                       if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
02869                      if (outgoing) {
02870                          p->call = NULL;
02871                      }
02872                       }
02873                   }
02874                   
02875                   
02876                }
02877                if (res < 0) 
02878                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
02879                pri_rel(p->pri);        
02880             } else {
02881                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02882                res = -1;
02883             }
02884          } else {
02885             if (p->bearer)
02886                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02887             p->call = NULL;
02888             res = 0;
02889          }
02890       }
02891 #endif
02892 #ifdef HAVE_GSMAT
02893       if (p->gsm.modul) {
02894           if (!p->alreadyhungup)
02895          gsm_hangup(p->gsm.modul);
02896       }
02897 #endif
02898       if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_GSM))
02899          res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
02900       if (res < 0) {
02901          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02902       }
02903       switch (p->sig) {
02904       case SIG_FXOGS:
02905       case SIG_FXOLS:
02906       case SIG_FXOKS:
02907          res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
02908          if (!res) {
02909 #if 0
02910             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02911 #endif
02912             /* If they're off hook, try playing congestion */
02913             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02914                tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
02915             else
02916                tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
02917          }
02918          break;
02919       case SIG_FXSGS:
02920       case SIG_FXSLS:
02921       case SIG_FXSKS:
02922          /* Make sure we're not made available for at least two seconds assuming
02923             we were actually used for an inbound or outbound call. */
02924          if (ast->_state != AST_STATE_RESERVED) {
02925             time(&p->guardtime);
02926             p->guardtime += 2;
02927          }
02928          break;
02929       default:
02930          tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
02931       }
02932       if (p->cidspill)
02933          free(p->cidspill);
02934       if (p->sig)
02935          zt_disable_ec(p);
02936       x = 0;
02937       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02938       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02939       p->didtdd = 0;
02940       p->cidspill = NULL;
02941       p->callwaitcas = 0;
02942       p->callwaiting = p->permcallwaiting;
02943       p->hidecallerid = p->permhidecallerid;
02944       p->dialing = 0;
02945       p->rdnis[0] = '\0';
02946       update_conf(p);
02947       reset_conf(p);
02948       /* Restore data mode */
02949       if (p->sig == SIG_PRI) {
02950          x = 0;
02951          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02952       }
02953 #ifdef HAVE_PRI
02954       if (p->bearer) {
02955          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02956          /* Free up the bearer channel as well, and
02957             don't use its file descriptor anymore */
02958          update_conf(p->bearer);
02959          reset_conf(p->bearer);
02960          p->bearer->owner = NULL;
02961          p->bearer->realcall = NULL;
02962          p->bearer = NULL;
02963          p->subs[SUB_REAL].zfd = -1;
02964          p->pri = NULL;
02965       }
02966 #endif
02967       restart_monitor();
02968    }
02969 
02970    p->callwaitingrepeat = 0;
02971    p->cidcwexpire = 0;
02972    p->oprmode = 0;
02973    ast->tech_pvt = NULL;
02974    ast_mutex_unlock(&p->lock);
02975    ast_module_unref(ast_module_info->self);
02976    if (option_verbose > 2) 
02977       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02978 
02979    ast_mutex_lock(&iflock);
02980    tmp = iflist;
02981    prev = NULL;
02982    if (p->destroy) {
02983       while (tmp) {
02984          if (tmp == p) {
02985             destroy_channel(prev, tmp, 0);
02986             break;
02987          } else {
02988             prev = tmp;
02989             tmp = tmp->next;
02990          }
02991       }
02992    }
02993    ast_mutex_unlock(&iflock);
02994    return 0;
02995 }

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

Definition at line 5292 of file chan_zap.c.

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

05293 {
05294    struct zt_pvt *p = chan->tech_pvt;
05295    int res=-1;
05296    int index;
05297    int func = ZT_FLASH;
05298    ast_mutex_lock(&p->lock);
05299    index = zt_get_index(chan, p, 0);
05300    if (option_debug)
05301       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05302    if (index == SUB_REAL) {
05303       switch (condition) {
05304       case AST_CONTROL_BUSY:
05305 #ifdef HAVE_PRI
05306          if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
05307             chan->hangupcause = AST_CAUSE_USER_BUSY;
05308             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05309             res = 0;
05310          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05311             if (p->pri->pri) {      
05312                if (!pri_grab(p, p->pri)) {
05313                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05314                   pri_rel(p->pri);
05315                }
05316                else
05317                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05318             }
05319             p->progress = 1;
05320             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_BUSY);
05321          } else
05322 #endif
05323             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_BUSY);
05324          break;
05325       case AST_CONTROL_RINGING:
05326 #ifdef HAVE_PRI
05327          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05328             if (p->pri->pri) {      
05329                if (!pri_grab(p, p->pri)) {
05330                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05331                   pri_rel(p->pri);
05332                }
05333                else
05334                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05335             }
05336             p->alerting = 1;
05337          }
05338 #endif
05339          res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_RINGTONE);
05340          if (chan->_state != AST_STATE_UP) {
05341             if ((chan->_state != AST_STATE_RING) ||
05342                ((p->sig != SIG_FXSKS) &&
05343                 (p->sig != SIG_FXSLS) &&
05344                 (p->sig != SIG_FXSGS)))
05345                ast_setstate(chan, AST_STATE_RINGING);
05346          }
05347          break;
05348       case AST_CONTROL_PROCEEDING:
05349          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05350 #ifdef HAVE_PRI
05351          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05352             if (p->pri->pri) {      
05353                if (!pri_grab(p, p->pri)) {
05354                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05355                   pri_rel(p->pri);
05356                }
05357                else
05358                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05359             }
05360             p->proceeding = 1;
05361          }
05362 #endif
05363          /* don't continue in ast_indicate */
05364          res = 0;
05365          break;
05366       case AST_CONTROL_PROGRESS:
05367          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05368 #ifdef HAVE_PRI
05369          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
05370          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05371             if (p->pri->pri) {      
05372                if (!pri_grab(p, p->pri)) {
05373                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05374                   pri_rel(p->pri);
05375                }
05376                else
05377                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05378             }
05379             p->progress = 1;
05380          }
05381 #endif
05382          /* don't continue in ast_indicate */
05383          res = 0;
05384          break;
05385       case AST_CONTROL_CONGESTION:
05386          chan->hangupcause = AST_CAUSE_CONGESTION;
05387 #ifdef HAVE_PRI
05388          if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
05389             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05390             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05391             res = 0;
05392          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05393             if (p->pri) {     
05394                if (!pri_grab(p, p->pri)) {
05395                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05396                   pri_rel(p->pri);
05397                } else
05398                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05399             }
05400             p->progress = 1;
05401             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05402          } else
05403 #endif
05404             res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
05405          break;
05406       case AST_CONTROL_HOLD:
05407 #ifdef HAVE_PRI
05408          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05409             if (!pri_grab(p, p->pri)) {
05410                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05411                pri_rel(p->pri);
05412             } else
05413                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05414          } else
05415 #endif
05416             ast_moh_start(chan, data, p->mohinterpret);
05417          break;
05418       case AST_CONTROL_UNHOLD:
05419 #ifdef HAVE_PRI
05420          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05421             if (!pri_grab(p, p->pri)) {
05422                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05423                pri_rel(p->pri);
05424             } else
05425                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05426          } else
05427 #endif
05428             ast_moh_stop(chan);
05429          break;
05430       case AST_CONTROL_RADIO_KEY:
05431          if (p->radio) 
05432              res =  zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
05433          res = 0;
05434          break;
05435       case AST_CONTROL_RADIO_UNKEY:
05436          if (p->radio)
05437              res =  zt_set_hook(p->subs[index].zfd, ZT_RINGOFF);
05438          res = 0;
05439          break;
05440       case AST_CONTROL_FLASH:
05441          /* flash hookswitch */
05442          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05443             /* Clear out the dial buffer */
05444             p->dop.dialstr[0] = '\0';
05445             if ((ioctl(p->subs[SUB_REAL].zfd,ZT_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05446                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
05447                   chan->name, strerror(errno));
05448             } else
05449                res = 0;
05450          } else
05451             res = 0;
05452          break;
05453       case -1:
05454          res = tone_zone_play_tone(p->subs[index].zfd, -1);
05455          break;
05456       }
05457    } else
05458       res = 0;
05459    ast_mutex_unlock(&p->lock);
05460    return res;
05461 }

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

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

03355                                                                  {
03356    int x;
03357    if (!slave || !master) {
03358       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03359       return;
03360    }
03361    for (x = 0; x < MAX_SLAVES; x++) {
03362       if (!master->slaves[x]) {
03363          master->slaves[x] = slave;
03364          break;
03365       }
03366    }
03367    if (x >= MAX_SLAVES) {
03368       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03369       master->slaves[MAX_SLAVES - 1] = slave;
03370    }
03371    if (slave->master) 
03372       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03373    slave->master = master;
03374    
03375    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03376 }

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

05464 {
05465    struct ast_channel *tmp;
05466    int deflaw;
05467    int res;
05468    int x,y;
05469    int features;
05470    char *b2 = NULL;
05471    ZT_PARAMS ps;
05472    if (i->subs[index].owner) {
05473       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05474       return NULL;
05475    }
05476    y = 1;
05477    do {
05478       if (b2)
05479          free(b2);
05480 #ifdef HAVE_PRI
05481       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05482          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05483       else
05484 #endif
05485       if (i->channel == CHAN_PSEUDO)
05486          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05487       else  
05488          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05489       for (x = 0; x < 3; x++) {
05490          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name))
05491             break;
05492       }
05493       y++;
05494    } while (x < 3);
05495    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "Zap/%s", b2);
05496    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
05497       free(b2);
05498    if (!tmp)
05499       return NULL;
05500    tmp->tech = &zap_tech;
05501    ps.channo = i->channel;
05502    res = ioctl(i->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps);
05503    if (res) {
05504       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW\n");
05505       ps.curlaw = ZT_LAW_MULAW;
05506    }
05507    if (ps.curlaw == ZT_LAW_ALAW)
05508       deflaw = AST_FORMAT_ALAW;
05509    else
05510       deflaw = AST_FORMAT_ULAW;
05511    if (law) {
05512       if (law == ZT_LAW_ALAW)
05513          deflaw = AST_FORMAT_ALAW;
05514       else
05515          deflaw = AST_FORMAT_ULAW;
05516    }
05517    tmp->fds[0] = i->subs[index].zfd;
05518    tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05519    /* Start out assuming ulaw since it's smaller :) */
05520    tmp->rawreadformat = deflaw;
05521    tmp->readformat = deflaw;
05522    tmp->rawwriteformat = deflaw;
05523    tmp->writeformat = deflaw;
05524    i->subs[index].linear = 0;
05525    zt_setlinear(i->subs[index].zfd, i->subs[index].linear);
05526    features = 0;
05527    if (index == SUB_REAL) {
05528       if (i->busydetect && CANBUSYDETECT(i))
05529          features |= DSP_FEATURE_BUSY_DETECT;
05530       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05531          features |= DSP_FEATURE_CALL_PROGRESS;
05532       if ((!i->outgoing && (i->callprogress & 4)) || 
05533           (i->outgoing && (i->callprogress & 2))) {
05534          features |= DSP_FEATURE_FAX_DETECT;
05535       }
05536 #ifdef ZT_TONEDETECT
05537       x = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
05538       if (ioctl(i->subs[index].zfd, ZT_TONEDETECT, &x)) {
05539 #endif      
05540          i->hardwaredtmf = 0;
05541          features |= DSP_FEATURE_DTMF_DETECT;
05542 #ifdef ZT_TONEDETECT
05543       } else if (NEED_MFDETECT(i)) {
05544          i->hardwaredtmf = 1;
05545          features |= DSP_FEATURE_DTMF_DETECT;
05546       }
05547 #endif
05548    }
05549    if (features) {
05550       if (i->dsp) {
05551          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05552       } else {
05553          if (i->channel != CHAN_PSEUDO)
05554             i->dsp = ast_dsp_new();
05555          else
05556             i->dsp = NULL;
05557          if (i->dsp) {
05558             i->dsp_features = features & ~DSP_PROGRESS_TALK;
05559 #ifdef HAVE_PRI
05560             /* We cannot do progress detection until receives PROGRESS message */
05561             if (i->outgoing && (i->sig == SIG_PRI)) {
05562                /* Remember requested DSP features, don't treat
05563                   talking as ANSWER */
05564                features = 0;
05565             }
05566 #endif
05567             ast_dsp_set_features(i->dsp, features);
05568             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05569             if (!ast_strlen_zero(progzone))
05570                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05571             if (i->busydetect && CANBUSYDETECT(i)) {
05572                ast_dsp_set_busy_count(i->dsp, i->busycount);
05573                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
05574             }
05575          }
05576       }
05577    }
05578       
05579    if (state == AST_STATE_RING)
05580       tmp->rings = 1;
05581    tmp->tech_pvt = i;
05582 #ifdef HAVE_PRI
05583    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
05584 #else
05585    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05586 #endif
05587       /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
05588       tmp->callgroup = i->callgroup;
05589       tmp->pickupgroup = i->pickupgroup;
05590    }
05591    if (!ast_strlen_zero(i->language))
05592       ast_string_field_set(tmp, language, i->language);
05593    if (!i->owner)
05594       i->owner = tmp;
05595    if (!ast_strlen_zero(i->accountcode))
05596       ast_string_field_set(tmp, accountcode, i->accountcode);
05597    if (i->amaflags)
05598       tmp->amaflags = i->amaflags;
05599    i->subs[index].owner = tmp;
05600    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05601    ast_string_field_set(tmp, call_forward, i->call_forward);
05602    /* If we've been told "no ADSI" then enforce it */
05603    if (!i->adsi)
05604       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05605    if (!ast_strlen_zero(i->exten))
05606       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05607    if (!ast_strlen_zero(i->rdnis))
05608       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05609    if (!ast_strlen_zero(i->dnid))
05610       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05611 
05612    /* Don't use ast_set_callerid() here because it will
05613     * generate a needless NewCallerID event */
05614 #ifdef PRI_ANI
05615    if (!ast_strlen_zero(i->cid_ani))
05616       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05617    else  
05618       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05619 #else
05620    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05621 #endif
05622    tmp->cid.cid_pres = i->callingpres;
05623    tmp->cid.cid_ton = i->cid_ton;
05624 #ifdef HAVE_PRI
05625    tmp->transfercapability = transfercapability;
05626    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05627    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05628       i->digital = 1;
05629    /* Assume calls are not idle calls unless we're told differently */
05630    i->isidlecall = 0;
05631    i->alreadyhungup = 0;
05632 #endif
05633    /* clear the fake event in case we posted one before we had ast_channel */
05634    i->fake_event = 0;
05635    /* Assure there is no confmute on this channel */
05636    zt_confmute(i, 0);
05637    /* Configure the new channel jb */
05638    ast_jb_configure(tmp, &global_jbconf);
05639    if (startpbx) {
05640       if (ast_pbx_start(tmp)) {
05641          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05642          ast_hangup(tmp);
05643          i->owner = NULL;
05644          return NULL;
05645       }
05646    }
05647 
05648    ast_module_ref(ast_module_info->self);
05649    
05650    return tmp;
05651 }

static int zt_open ( char *  fn  )  [static]

Definition at line 1050 of file chan_zap.c.

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

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

01051 {
01052    int fd;
01053    int isnum;
01054    int chan = 0;
01055    int bs;
01056    int x;
01057    isnum = 1;
01058    for (x = 0; x < strlen(fn); x++) {
01059       if (!isdigit(fn[x])) {
01060          isnum = 0;
01061          break;
01062       }
01063    }
01064    if (isnum) {
01065       chan = atoi(fn);
01066       if (chan < 1) {
01067          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01068          return -1;
01069       }
01070       fn = "/dev/zap/channel";
01071    }
01072    fd = open(fn, O_RDWR | O_NONBLOCK);
01073    if (fd < 0) {
01074       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01075       return -1;
01076    }
01077    if (chan) {
01078       if (ioctl(fd, ZT_SPECIFY, &chan)) {
01079          x = errno;
01080          close(fd);
01081          errno = x;
01082          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01083          return -1;
01084       }
01085    }
01086    bs = READ_SIZE;
01087    if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) {
01088       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01089       x = errno;
01090       close(fd);
01091       errno = x;
01092       return -1;
01093    }
01094    return fd;
01095 }

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

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

04897 {
04898    struct zt_pvt *p = ast->tech_pvt;
04899    int res;
04900    int index;
04901    void *readbuf;
04902    struct ast_frame *f;
04903    
04904 
04905    ast_mutex_lock(&p->lock);
04906    
04907    index = zt_get_index(ast, p, 0);
04908    
04909    /* Hang up if we don't really exist */
04910    if (index < 0) {
04911       ast_log(LOG_WARNING, "We dont exist?\n");
04912       ast_mutex_unlock(&p->lock);
04913       return NULL;
04914    }
04915    
04916    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
04917 
04918    p->subs[index].f.frametype = AST_FRAME_NULL;
04919    p->subs[index].f.datalen = 0;
04920    p->subs[index].f.samples = 0;
04921    p->subs[index].f.mallocd = 0;
04922    p->subs[index].f.offset = 0;
04923    p->subs[index].f.subclass = 0;
04924    p->subs[index].f.delivery = ast_tv(0,0);
04925    p->subs[index].f.src = "zt_read";
04926    p->subs[index].f.data = NULL;
04927    
04928    /* make sure it sends initial key state as first frame */
04929    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
04930    {
04931       ZT_PARAMS ps;
04932 
04933       ps.channo = p->channel;
04934       if (ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
04935          ast_mutex_unlock(&p->lock);
04936          return NULL;
04937       }
04938       p->firstradio = 1;
04939       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04940       if (ps.rxisoffhook)
04941       {
04942          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04943       }
04944       else
04945       {
04946          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04947       }
04948       ast_mutex_unlock(&p->lock);
04949       return &p->subs[index].f;
04950    }
04951    if (p->ringt == 1) {
04952       ast_mutex_unlock(&p->lock);
04953       return NULL;
04954    }
04955    else if (p->ringt > 0) 
04956       p->ringt--;
04957 
04958    if (p->subs[index].needringing) {
04959       /* Send ringing frame if requested */
04960       p->subs[index].needringing = 0;
04961       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04962       p->subs[index].f.subclass = AST_CONTROL_RINGING;
04963       ast_setstate(ast, AST_STATE_RINGING);
04964       ast_mutex_unlock(&p->lock);
04965       return &p->subs[index].f;
04966    }
04967 
04968    if (p->subs[index].needbusy) {
04969       /* Send busy frame if requested */
04970       p->subs[index].needbusy = 0;
04971       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04972       p->subs[index].f.subclass = AST_CONTROL_BUSY;
04973       ast_mutex_unlock(&p->lock);
04974       return &p->subs[index].f;
04975    }
04976 
04977    if (p->subs[index].needcongestion) {
04978       /* Send congestion frame if requested */
04979       p->subs[index].needcongestion = 0;
04980       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04981       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
04982       ast_mutex_unlock(&p->lock);
04983       return &p->subs[index].f;
04984    }
04985 
04986    if (p->subs[index].needcallerid) {
04987       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
04988                      S_OR(p->lastcid_name, NULL),
04989                      S_OR(p->lastcid_num, NULL)
04990                      );
04991       p->subs[index].needcallerid = 0;
04992    }
04993    
04994    if (p->subs[index].needanswer) {
04995       /* Send answer frame if requested */
04996       p->subs[index].needanswer = 0;
04997       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04998       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04999       ast_mutex_unlock(&p->lock);
05000       return &p->subs[index].f;
05001    }  
05002    
05003    if (p->subs[index].needflash) {
05004       /* Send answer frame if requested */
05005       p->subs[index].needflash = 0;
05006       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05007       p->subs[index].f.subclass = AST_CONTROL_FLASH;
05008       ast_mutex_unlock(&p->lock);
05009       return &p->subs[index].f;
05010    }  
05011    
05012    if (p->subs[index].needhold) {
05013       /* Send answer frame if requested */
05014       p->subs[index].needhold = 0;
05015       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05016       p->subs[index].f.subclass = AST_CONTROL_HOLD;
05017       ast_mutex_unlock(&p->lock);
05018       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
05019       return &p->subs[index].f;
05020    }  
05021    
05022    if (p->subs[index].needunhold) {
05023       /* Send answer frame if requested */
05024       p->subs[index].needunhold = 0;
05025       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05026       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
05027       ast_mutex_unlock(&p->lock);
05028       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
05029       return &p->subs[index].f;
05030    }  
05031    
05032    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05033       if (!p->subs[index].linear) {
05034          p->subs[index].linear = 1;
05035          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
05036          if (res) 
05037             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
05038       }
05039    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05040          (ast->rawreadformat == AST_FORMAT_ALAW)) {
05041       if (p->subs[index].linear) {
05042          p->subs[index].linear = 0;
05043          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
05044          if (res) 
05045             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
05046       }
05047    } else {
05048       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05049       ast_mutex_unlock(&p->lock);
05050       return NULL;
05051    }
05052    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
05053    CHECK_BLOCKING(ast);
05054    res = read(p->subs[index].zfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05055    ast_clear_flag(ast, AST_FLAG_BLOCKING);
05056    /* Check for hangup */
05057    if (res < 0) {
05058       f = NULL;
05059       if (res == -1)  {
05060          if (errno == EAGAIN) {
05061             /* Return "NULL" frame if there is nobody there */
05062             ast_mutex_unlock(&p->lock);
05063             return &p->subs[index].f;
05064          } else if (errno == ELAST) {
05065             f = __zt_exception(ast);
05066          } else
05067             ast_log(LOG_WARNING, "zt_rec: %s\n", strerror(errno));
05068       }
05069       ast_mutex_unlock(&p->lock);
05070       return f;
05071    }
05072    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
05073       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05074       f = __zt_exception(ast);
05075       ast_mutex_unlock(&p->lock);
05076       return f;
05077    }
05078    if (p->tdd) { /* if in TDD mode, see if we receive that */
05079       int c;
05080 
05081       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05082       if (c < 0) {
05083          ast_log(LOG_DEBUG,"tdd_feed failed\n");
05084          ast_mutex_unlock(&p->lock);
05085          return NULL;
05086       }
05087       if (c) { /* if a char to return */
05088          p->subs[index].f.subclass = 0;
05089          p->subs[index].f.frametype = AST_FRAME_TEXT;
05090          p->subs[index].f.mallocd = 0;
05091          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05092          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
05093          p->subs[index].f.datalen = 1;
05094          *((char *) p->subs[index].f.data) = c;
05095          ast_mutex_unlock(&p->lock);
05096          return &p->subs[index].f;
05097       }
05098    }
05099    if (p->callwaitingrepeat)
05100       p->callwaitingrepeat--;
05101    if (p->cidcwexpire)
05102       p->cidcwexpire--;
05103    /* Repeat callwaiting */
05104    if (p->callwaitingrepeat == 1) {
05105       p->callwaitrings++;
05106       zt_callwait(ast);
05107    }
05108    /* Expire CID/CW */
05109    if (p->cidcwexpire == 1) {
05110       if (option_verbose > 2)
05111          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
05112       restore_conference(p);
05113    }
05114    if (p->subs[index].linear) {
05115       p->subs[index].f.datalen = READ_SIZE * 2;
05116    } else 
05117       p->subs[index].f.datalen = READ_SIZE;
05118 
05119    /* Handle CallerID Transmission */
05120    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05121       send_callerid(p);
05122    }
05123 
05124    p->subs[index].f.frametype = AST_FRAME_VOICE;
05125    p->subs[index].f.subclass = ast->rawreadformat;
05126    p->subs[index].f.samples = READ_SIZE;
05127    p->subs[index].f.mallocd = 0;
05128    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05129    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
05130 #if 0
05131    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
05132 #endif   
05133    if (p->dialing || /* Transmitting something */
05134       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
05135       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05136       ) {
05137       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05138          don't send anything */
05139       p->subs[index].f.frametype = AST_FRAME_NULL;
05140       p->subs[index].f.subclass = 0;
05141       p->subs[index].f.samples = 0;
05142       p->subs[index].f.mallocd = 0;
05143       p->subs[index].f.offset = 0;
05144       p->subs[index].f.data = NULL;
05145       p->subs[index].f.datalen= 0;
05146    }
05147    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
05148       /* Perform busy detection. etc on the zap line */
05149       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05150       if (f) {
05151          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05152             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05153                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05154                   a busy  */
05155                f = NULL;
05156             }
05157          } else if (f->frametype == AST_FRAME_DTMF) {
05158 #ifdef HAVE_PRI
05159             if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
05160                /* Don't accept in-band DTMF when in overlap dial mode 
05161                   or when in non-overlap overlapdialing mode ... */
05162                f->frametype = AST_FRAME_NULL;
05163                f->subclass = 0;
05164             }
05165 #endif            
05166             /* DSP clears us of being pulse */
05167             p->pulsedial = 0;
05168          }
05169       }
05170    } else 
05171       f = &p->subs[index].f; 
05172 
05173    if (f && (f->frametype == AST_FRAME_DTMF))
05174       zt_handle_dtmfup(ast, index, &f);
05175 
05176    /* If we have a fake_event, trigger exception to handle it */
05177    if (p->fake_event)
05178       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05179 
05180    ast_mutex_unlock(&p->lock);
05181    return f;
05182 }

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

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

08123 {
08124    int groupmatch = 0;
08125    int channelmatch = -1;
08126    int roundrobin = 0;
08127    int callwait = 0;
08128    int busy = 0;
08129    struct zt_pvt *p;
08130    struct ast_channel *tmp = NULL;
08131    char *dest=NULL;
08132    int x;
08133    char *s;
08134    char opt=0;
08135    int res=0, y=0;
08136    int backwards = 0;
08137 #ifdef HAVE_PRI
08138    int crv;
08139    int bearer = -1;
08140    int trunkgroup;
08141    struct zt_pri *pri=NULL;
08142 #endif   
08143    struct zt_pvt *exit, *start, *end;
08144    ast_mutex_t *lock;
08145    int channelmatched = 0;
08146    int groupmatched = 0;
08147    
08148    /* Assume we're locking the iflock */
08149    lock = &iflock;
08150    start = iflist;
08151    end = ifend;
08152    if (data) {
08153       dest = ast_strdupa((char *)data);
08154    } else {
08155       ast_log(LOG_WARNING, "Channel requested with no data\n");
08156       return NULL;
08157    }
08158    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08159       /* Retrieve the group number */
08160       char *stringp=NULL;
08161       stringp=dest + 1;
08162       s = strsep(&stringp, "/");
08163       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08164          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08165          return NULL;
08166       }
08167       groupmatch = 1 << x;
08168       if (toupper(dest[0]) == 'G') {
08169          if (dest[0] == 'G') {
08170             backwards = 1;
08171             p = ifend;
08172          } else
08173             p = iflist;
08174       } else {
08175          if (dest[0] == 'R') {
08176             backwards = 1;
08177             p = round_robin[x]?round_robin[x]->prev:ifend;
08178             if (!p)
08179                p = ifend;
08180          } else {
08181             p = round_robin[x]?round_robin[x]->next:iflist;
08182             if (!p)
08183                p = iflist;
08184          }
08185          roundrobin = 1;
08186       }
08187    } else {
08188       char *stringp=NULL;
08189       stringp=dest;
08190       s = strsep(&stringp, "/");
08191       p = iflist;
08192       if (!strcasecmp(s, "pseudo")) {
08193          /* Special case for pseudo */
08194          x = CHAN_PSEUDO;
08195          channelmatch = x;
08196       } 
08197 #ifdef HAVE_PRI
08198       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08199          if ((trunkgroup < 1) || (crv < 1)) {
08200             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08201             return NULL;
08202          }
08203          res--;
08204          for (x = 0; x < NUM_SPANS; x++) {
08205             if (pris[x].trunkgroup == trunkgroup) {
08206                pri = pris + x;
08207                lock = &pri->lock;
08208                start = pri->crvs;
08209                end = pri->crvend;
08210                break;
08211             }
08212          }
08213          if (!pri) {
08214             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08215             return NULL;
08216          }
08217          channelmatch = crv;
08218          p = pris[x].crvs;
08219       }
08220 #endif   
08221       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08222          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08223          return NULL;
08224       } else {
08225          channelmatch = x;
08226       }
08227    }
08228    /* Search for an unowned channel */
08229    ast_mutex_lock(lock);
08230    exit = p;
08231    while (p && !tmp) {
08232       if (roundrobin)
08233          round_robin[x] = p;
08234 #if 0
08235       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08236 #endif
08237 
08238       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08239          if (option_debug)
08240             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08241             if (p->inalarm) 
08242                goto next;
08243 
08244          callwait = (p->owner != NULL);
08245 #ifdef HAVE_PRI
08246          if (pri && (p->subs[SUB_REAL].zfd < 0)) {
08247             if (p->sig != SIG_FXSKS) {
08248                /* Gotta find an actual channel to use for this
08249                   CRV if this isn't a callwait */
08250                bearer = pri_find_empty_chan(pri, 0);
08251                if (bearer < 0) {
08252                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08253                   p = NULL;
08254                   break;
08255                }
08256                pri_assign_bearer(p, pri, pri->pvts[bearer]);
08257             } else {
08258                if (alloc_sub(p, 0)) {
08259                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08260                   p = NULL;
08261                   break;
08262                } else
08263                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08264                p->pri = pri;
08265             }
08266          }
08267 #endif         
08268          if (p->channel == CHAN_PSEUDO) {
08269             p = chandup(p);
08270             if (!p) {
08271                break;
08272             }
08273          }
08274          if (p->owner) {
08275             if (alloc_sub(p, SUB_CALLWAIT)) {
08276                p = NULL;
08277                break;
08278             }
08279          }
08280          p->outgoing = 1;
08281          tmp = zt_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08282 #ifdef HAVE_PRI
08283          if (p->bearer) {
08284             /* Log owner to bearer channel, too */
08285             p->bearer->owner = tmp;
08286          }
08287 #endif         
08288          /* Make special notes */
08289          if (res > 1) {
08290             if (opt == 'c') {
08291                /* Confirm answer */
08292                p->confirmanswer = 1;
08293             } else if (opt == 'r') {
08294                /* Distinctive ring */
08295                if (res < 3)
08296                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08297                else
08298                   p->distinctivering = y;
08299             } else if (opt == 'd') {
08300                /* If this is an ISDN call, make it digital */
08301                p->digital = 1;
08302                if (tmp)
08303                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08304             } else if (opt == 'm') {
08305                /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
08306                p->faxhandled = 1;
08307                if (tmp)
08308                    tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
08309             } else {
08310                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08311             }
08312          }
08313          /* Note if the call is a call waiting call */
08314          if (tmp && callwait)
08315             tmp->cdrflags |= AST_CDR_CALLWAIT;
08316          break;
08317       }
08318 next:
08319       if (backwards) {
08320          p = p->prev;
08321          if (!p)
08322             p = end;
08323       } else {
08324          p = p->next;
08325          if (!p)
08326             p = start;
08327       }
08328       /* stop when you roll to the one that we started from */
08329       if (p == exit)
08330          break;
08331    }
08332    ast_mutex_unlock(lock);
08333    restart_monitor();
08334    if (callwait)
08335       *cause = AST_CAUSE_BUSY;
08336    else if (!tmp) {
08337       if (channelmatched) {
08338          if (busy)
08339             *cause = AST_CAUSE_BUSY;
08340       } else if (groupmatched) {
08341          *cause = AST_CAUSE_CONGESTION;
08342       } else {
08343          *cause = AST_CAUSE_CONGESTION;
08344       }
08345    }
08346       
08347    return tmp;
08348 }

static int zt_ring_phone ( struct zt_pvt p  )  [static]

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

03744 {
03745    int x;
03746    int res;
03747    /* Make sure our transmit state is on hook */
03748    x = 0;
03749    x = ZT_ONHOOK;
03750    res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03751    do {
03752       x = ZT_RING;
03753       res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
03754       if (res) {
03755          switch (errno) {
03756          case EBUSY:
03757          case EINTR:
03758             /* Wait just in case */
03759             usleep(10000);
03760             continue;
03761          case EINPROGRESS:
03762             res = 0;
03763             break;
03764          default:
03765             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03766             res = 0;
03767          }
03768       }
03769    } while (res);
03770    return res;
03771 }

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

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

13249                                                                                              {
13250  struct zt_pvt *p = c->tech_pvt;
13251  if (!p) return -1;
13252  if (p->sig == SIG_PRI) {
13253 #ifdef HAVE_PRI
13254    if (ispdu) {
13255        ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP ISDN channel\n");
13256        return -1;
13257    }
13258    return zt_pri_sendtext(c, text);
13259 #endif
13260  } else if (p->sig == SIG_GSM) {
13261 #ifdef HAVE_GSMAT
13262      return zt_gsm_sendtext(c, dest, text, ispdu);
13263 #endif
13264  } else {
13265    return zt_tdd_sendtext(c, text);
13266  }
13267  return -1;
13268 }

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

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

01800 {
01801    int x, res;
01802 
01803    x = hs;
01804    res = ioctl(fd, ZT_HOOK, &x);
01805 
01806    if (res < 0) {
01807       if (errno == EINPROGRESS)
01808          return 0;
01809       ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
01810    }
01811 
01812    return res;
01813 }

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

Definition at line 2632 of file chan_zap.c.

02633 {
02634    int res;
02635    res = ioctl(zfd, ZT_SETLAW, &law);
02636    if (res)
02637       return res;
02638    return 0;
02639 }

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

Definition at line 1103 of file chan_zap.c.

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

01104 {
01105    int res;
01106    res = ioctl(zfd, ZT_SETLINEAR, &linear);
01107    if (res)
01108       return res;
01109    return 0;
01110 }

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

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

03094 {
03095    char *cp;
03096    signed char *scp;
03097    int x;
03098    int index;
03099    struct zt_pvt *p = chan->tech_pvt, *pp;
03100    struct oprmode *oprmode;
03101    
03102 
03103    /* all supported options require data */
03104    if (!data || (datalen < 1)) {
03105       errno = EINVAL;
03106       return -1;
03107    }
03108 
03109    switch (option) {
03110    case AST_OPTION_TXGAIN:
03111       scp = (signed char *) data;
03112       index = zt_get_index(chan, p, 0);
03113       if (index < 0) {
03114          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03115          return -1;
03116       }
03117       if (option_debug)
03118          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03119       return set_actual_txgain(p->subs[index].zfd, 0, p->txgain + (float) *scp, p->law);
03120    case AST_OPTION_RXGAIN:
03121       scp = (signed char *) data;
03122       index = zt_get_index(chan, p, 0);
03123       if (index < 0) {
03124          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03125          return -1;
03126       }
03127       if (option_debug)
03128          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03129       return set_actual_rxgain(p->subs[index].zfd, 0, p->rxgain + (float) *scp, p->law);
03130    case AST_OPTION_TONE_VERIFY:
03131       if (!p->dsp)
03132          break;
03133       cp = (char *) data;
03134       switch (*cp) {
03135       case 1:
03136          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03137          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
03138          break;
03139       case 2:
03140          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03141          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
03142          break;
03143       default:
03144          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03145          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
03146          break;
03147       }
03148       break;
03149    case AST_OPTION_TDD:
03150       /* turn on or off TDD */
03151       cp = (char *) data;
03152       p->mate = 0;
03153       if (!*cp) { /* turn it off */
03154          if (option_debug)
03155             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03156          if (p->tdd)
03157             tdd_free(p->tdd);
03158          p->tdd = 0;
03159          break;
03160       }
03161       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03162          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03163       zt_disable_ec(p);
03164       /* otherwise, turn it on */
03165       if (!p->didtdd) { /* if havent done it yet */
03166          unsigned char mybuf[41000], *buf;
03167          int size, res, fd, len;
03168          struct pollfd fds[1];
03169 
03170          buf = mybuf;
03171          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03172          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03173          len = 40000;
03174          index = zt_get_index(chan, p, 0);
03175          if (index < 0) {
03176             ast_log(LOG_WARNING, "No index in TDD?\n");
03177             return -1;
03178          }
03179          fd = p->subs[index].zfd;
03180          while (len) {
03181             if (ast_check_hangup(chan))
03182                return -1;
03183             size = len;
03184             if (size > READ_SIZE)
03185                size = READ_SIZE;
03186             fds[0].fd = fd;
03187             fds[0].events = POLLPRI | POLLOUT;
03188             fds[0].revents = 0;
03189             res = poll(fds, 1, -1);
03190             if (!res) {
03191                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03192                continue;
03193             }
03194             /* if got exception */
03195             if (fds[0].revents & POLLPRI)
03196                return -1;
03197             if (!(fds[0].revents & POLLOUT)) {
03198                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03199                continue;
03200             }
03201             res = write(fd, buf, size);
03202             if (res != size) {
03203                if (res == -1) return -1;
03204                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03205                break;
03206             }
03207             len -= size;
03208             buf += size;
03209          }
03210          p->didtdd = 1; /* set to have done it now */    
03211       }
03212       if (*cp == 2) { /* Mate mode */
03213          if (p->tdd)
03214             tdd_free(p->tdd);
03215          p->tdd = 0;
03216          p->mate = 1;
03217          break;
03218       }     
03219       if (!p->tdd) { /* if we dont have one yet */
03220          p->tdd = tdd_new(); /* allocate one */
03221       }     
03222       break;
03223    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03224       if (!p->dsp)
03225          break;
03226       cp = (char *) data;
03227       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03228          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03229                 p->dtmfrelax = 0;
03230                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03231                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03232       break;
03233    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03234       cp = (char *) data;
03235       if (!*cp) {    
03236          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03237          x = 0;
03238          zt_disable_ec(p);
03239       } else {    
03240          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03241          x = 1;
03242       }
03243       if (ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x) == -1)
03244          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", p->channel, x);
03245       break;
03246    case AST_OPTION_OPRMODE:  /* Operator services mode */
03247       oprmode = (struct oprmode *) data;
03248       pp = oprmode->peer->tech_pvt;
03249       p->oprmode = pp->oprmode = 0;
03250       /* setup peers */
03251       p->oprpeer = pp;
03252       pp->oprpeer = p;
03253       /* setup modes, if any */
03254       if (oprmode->mode) 
03255       {
03256          pp->oprmode = oprmode->mode;
03257          p->oprmode = -oprmode->mode;
03258       }
03259       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03260          oprmode->mode, chan->name,oprmode->peer->name);;
03261       break;
03262    case AST_OPTION_ECHOCAN:
03263       cp = (char *) data;
03264       if (*cp) {
03265          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03266          zt_enable_ec(p);
03267       } else {
03268          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03269          zt_disable_ec(p);
03270       }
03271       break;
03272    }
03273    errno = 0;
03274 
03275    return 0;
03276 }

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

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

13271 {
13272 #define  END_SILENCE_LEN 400
13273 #define  HEADER_MS 50
13274 #define  TRAILER_MS 5
13275 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
13276 #define  ASCII_BYTES_PER_CHAR 80
13277 
13278    unsigned char *buf,*mybuf;
13279    struct zt_pvt *p = c->tech_pvt;
13280    struct pollfd fds[1];
13281    int size,res,fd,len,x;
13282    int bytes=0;
13283    /* Initial carrier (imaginary) */
13284    float cr = 1.0;
13285    float ci = 0.0;
13286    float scont = 0.0;
13287    int index;
13288 
13289 
13290    index = zt_get_index(c, p, 0);
13291    if (index < 0) {
13292       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
13293       return -1;
13294    }
13295    if (!text[0]) return(0); /* if nothing to send, dont */
13296    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
13297    if (p->mate) 
13298       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
13299    else
13300       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
13301    if (!buf)
13302       return -1;
13303    mybuf = buf;
13304    if (p->mate) {
13305       int codec = AST_LAW(p);
13306       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
13307          PUT_CLID_MARKMS;
13308       }
13309       /* Put actual message */
13310       for (x = 0; text[x]; x++) {
13311          PUT_CLID(text[x]);
13312       }
13313       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
13314          PUT_CLID_MARKMS;
13315       }
13316       len = bytes;
13317       buf = mybuf;
13318    } else {
13319       len = tdd_generate(p->tdd, buf, text);
13320       if (len < 1) {
13321          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
13322          free(mybuf);
13323          return -1;
13324       }
13325    }
13326    memset(buf + len, 0x7f, END_SILENCE_LEN);
13327    len += END_SILENCE_LEN;
13328    fd = p->subs[index].zfd;
13329    while (len) {
13330       if (ast_check_hangup(c)) {
13331          free(mybuf);
13332          return -1;
13333       }
13334       size = len;
13335       if (size > READ_SIZE)
13336          size = READ_SIZE;
13337       fds[0].fd = fd;
13338       fds[0].events = POLLOUT | POLLPRI;
13339       fds[0].revents = 0;
13340       res = poll(fds, 1, -1);
13341       if (!res) {
13342          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
13343          continue;
13344       }
13345         /* if got exception */
13346       if (fds[0].revents & POLLPRI) {
13347          ast_free(mybuf);
13348          return -1;
13349       }
13350       if (!(fds[0].revents & POLLOUT)) {
13351          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
13352          continue;
13353       }
13354       res = write(fd, buf, size);
13355       if (res != size) {
13356          if (res == -1) {
13357             free(mybuf);
13358             return -1;
13359          }
13360          if (option_debug)
13361             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
13362          break;
13363       }
13364       len -= size;
13365       buf += size;
13366    }
13367    free(mybuf);
13368    return(0);
13369 }

static void zt_train_ec ( struct zt_pvt p  )  [static]

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

01632 {
01633    int x;
01634    int res;
01635    if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
01636       x = p->echotraining;
01637       res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
01638       if (res)
01639          ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
01640       else {
01641          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01642       }
01643    } else
01644       ast_log(LOG_DEBUG, "No echo training requested\n");
01645 }

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

Definition at line 3297 of file chan_zap.c.

References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), zt_pvt::channel, conf_del(), 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().

03298 {
03299    /* Unlink a specific slave or all slaves/masters from a given master */
03300    int x;
03301    int hasslaves;
03302    if (!master)
03303       return;
03304    if (needlock) {
03305       ast_mutex_lock(&master->lock);
03306       if (slave) {
03307          while (ast_mutex_trylock(&slave->lock)) {
03308             ast_mutex_unlock(&master->lock);
03309             usleep(1);
03310             ast_mutex_lock(&master->lock);
03311          }
03312       }
03313    }
03314    hasslaves = 0;
03315    for (x = 0; x < MAX_SLAVES; x++) {
03316       if (master->slaves[x]) {
03317          if (!slave || (master->slaves[x] == slave)) {
03318             /* Take slave out of the conference */
03319             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03320             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03321             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03322             master->slaves[x]->master = NULL;
03323             master->slaves[x] = NULL;
03324          } else
03325             hasslaves = 1;
03326       }
03327       if (!hasslaves)
03328          master->inconference = 0;
03329    }
03330    if (!slave) {
03331       if (master->master) {
03332          /* Take master out of the conference */
03333          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03334          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03335          hasslaves = 0;
03336          for (x = 0; x < MAX_SLAVES; x++) {
03337             if (master->master->slaves[x] == master)
03338                master->master->slaves[x] = NULL;
03339             else if (master->master->slaves[x])
03340                hasslaves = 1;
03341          }
03342          if (!hasslaves)
03343             master->master->inconference = 0;
03344       }
03345       master->master = NULL;
03346    }
03347    update_conf(master);
03348    if (needlock) {
03349       if (slave)
03350          ast_mutex_unlock(&slave->lock);
03351       ast_mutex_unlock(&master->lock);
03352    }
03353 }

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

Avoid the silly zt_waitevent which ignores a bunch of events.

Definition at line 273 of file chan_zap.c.

Referenced by flash_exec(), and ss_thread().

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

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

Definition at line 5673 of file chan_zap.c.

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

Referenced by ss_thread().

05674 {
05675    int j;
05676    zt_set_hook(p->subs[index].zfd, ZT_WINK);
05677    for (;;)
05678    {
05679          /* set bits of interest */
05680       j = ZT_IOMUX_SIGEVENT;
05681           /* wait for some happening */
05682       if (ioctl(p->subs[index].zfd,ZT_IOMUX,&j) == -1) return(-1);
05683          /* exit loop if we have it */
05684       if (j & ZT_IOMUX_SIGEVENT) break;
05685    }
05686      /* get the event info */
05687    if (ioctl(p->subs[index].zfd,ZT_GETEVENT,&j) == -1) return(-1);
05688    return 0;
05689 }

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

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

05208 {
05209    struct zt_pvt *p = ast->tech_pvt;
05210    int res;
05211    int index;
05212    index = zt_get_index(ast, p, 0);
05213    if (index < 0) {
05214       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05215       return -1;
05216    }
05217 
05218 #if 0
05219 #ifdef HAVE_PRI
05220    ast_mutex_lock(&p->lock);
05221    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05222       if (p->pri->pri) {      
05223          if (!pri_grab(p, p->pri)) {
05224                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05225                pri_rel(p->pri);
05226          } else
05227                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05228       }
05229       p->proceeding=1;
05230    }
05231    ast_mutex_unlock(&p->lock);
05232 #endif
05233 #endif
05234    /* Write a frame of (presumably voice) data */
05235    if (frame->frametype != AST_FRAME_VOICE) {
05236       if (frame->frametype == AST_FRAME_TEXT) {
05237          ast_log(LOG_NOTICE, "text\n");
05238       } else if (frame->frametype != AST_FRAME_IMAGE)
05239          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05240       return 0;
05241    }
05242    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
05243        (frame->subclass != AST_FORMAT_ULAW) &&
05244        (frame->subclass != AST_FORMAT_ALAW)) {
05245       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05246       return -1;
05247    }
05248    if (p->dialing) {
05249       if (option_debug)
05250          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05251       return 0;
05252    }
05253    if (!p->owner) {
05254       if (option_debug)
05255          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05256       return 0;
05257    }
05258    if (p->cidspill) {
05259       if (option_debug)
05260          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05261       return 0;
05262    }
05263    /* Return if it's not valid data */
05264    if (!frame->data || !frame->datalen)
05265       return 0;
05266 
05267    if (frame->subclass == AST_FORMAT_SLINEAR) {
05268       if (!p->subs[index].linear) {
05269          p->subs[index].linear = 1;
05270          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
05271          if (res)
05272             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05273       }
05274       res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05275    } else {
05276       /* x-law already */
05277       if (p->subs[index].linear) {
05278          p->subs[index].linear = 0;
05279          res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
05280          if (res)
05281             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05282       }
05283       res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05284    }
05285    if (res < 0) {
05286       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05287       return -1;
05288    } 
05289    return 0;
05290 }


Variable Documentation

int alarm

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

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

Definition at line 175 of file chan_zap.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 119 of file chan_zap.c.

char defaultcic[64] = "" [static]

Definition at line 215 of file chan_zap.c.

char defaultozz[64] = "" [static]

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

int distinctiveringaftercid = 0 [static]

Definition at line 220 of file chan_zap.c.

struct zt_distRings drings [static]

Definition at line 417 of file chan_zap.c.

Referenced by mkintf(), and process_zap().

char* events[] [static]

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

int gendigittimeout = 8000 [static]

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

Definition at line 235 of file chan_zap.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 126 of file chan_zap.c.

char gsm_modem_exten[AST_MAX_EXTENSION] [static]

Definition at line 244 of file chan_zap.c.

char gsm_modem_pin[20] [static]

Definition at line 243 of file chan_zap.c.

int ifcount = 0 [static]

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

char* name

Definition at line 1304 of file chan_zap.c.

int num_cadence = 4 [static]

Definition at line 809 of file chan_zap.c.

int numbufs = 4 [static]

Definition at line 222 of file chan_zap.c.

char progzone[10] = "" [static]

Definition at line 218 of file chan_zap.c.

int ringt_base = DEFAULT_RINGT [static]

Definition at line 298 of file chan_zap.c.

struct zt_pvt* round_robin[32]

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

char* subnames[] [static]

Initial value:

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

Definition at line 430 of file chan_zap.c.

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

Definition at line 169 of file chan_zap.c.

int user_has_defined_cadences = 0 [static]

Definition at line 810 of file chan_zap.c.

struct ast_cli_entry zap_cli[] [static]

Definition at line 11933 of file chan_zap.c.

char zap_restart_usage[] [static]

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

struct ast_channel_tech zap_tech [static]

Definition at line 751 of file chan_zap.c.

char* zapEC_app = "zapEC" [static]

Definition at line 11571 of file chan_zap.c.

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

Definition at line 11572 of file chan_zap.c.

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

Definition at line 11570 of file chan_zap.c.


Generated on Sat Apr 12 07:12:43 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.5