Fri Jan 31 13:16:32 2014

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI 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 <libpri.h>
#include <openr2.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/dahdi_compat.h"
#include "asterisk/tonezone_compat.h"

Go to the source code of this file.

Data Structures

struct  dahdi_chan_conf
 Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More...
struct  dahdi_distRings
struct  dahdi_mfcr2
struct  dahdi_pri
struct  dahdi_pvt
struct  dahdi_subchannel
struct  distRingData
struct  ringContextData

Defines

#define ASCII_BYTES_PER_CHAR   80
#define AST_LAW(p)   (((p)->law == DAHDI_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 CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE)
#define CANBUSYDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CANPROGRESSDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CHAN_PSEUDO   -2
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define DAHDI_EVENT_DTMFDOWN   0
#define DAHDI_EVENT_DTMFUP   0
#define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
#define DAHDI_OVERLAPDIAL_INCOMING   2
#define DAHDI_OVERLAPDIAL_NONE   0
#define DAHDI_OVERLAPDIAL_OUTGOING   1
#define DAHDI_R2_LOCAL_BLOCK   (1 << 1)
#define DAHDI_R2_REMOTE_BLOCK   (1 << 0)
#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_PRI_DEBUG   0
#define DEFAULT_RINGT   ((8000 * 8) / READ_SIZE)
#define END_SILENCE_LEN   400
#define FORCE_RESTART_UNAVAIL_CHANS   1
#define FORMAT   "%-40.40s %-10.10s %-10d %-10d %-10d\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define FORMAT   "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
#define FORMAT   "%4s %40s\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)->bearer ? (p)->bearer->channel : p->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#define local_astman_ack(s, m, msg, zap)   do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
#define local_astman_header(m, hdr, zap)   astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
#define local_astman_register(a, b, c, d)
#define local_astman_unregister(a)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_CHANNELS   672
#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ((2000) )
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro.
#define NUM_CADENCE_MAX   25
#define NUM_DCHANS   4
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PRI_CHANNEL(p)   ((p) & 0xff)
#define PRI_EXPLICIT(p)   (((p) >> 16) & 0x01)
#define PRI_SPAN(p)   (((p) >> 8) & 0xff)
#define PVT_TO_CHANNEL(p)   (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
#define READ_SIZE   160
#define sig2str   dahdi_sig2str
#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)
#define SIG_EM   DAHDI_SIG_EM
#define SIG_EM_E1   DAHDI_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)
#define SIG_FXOGS   DAHDI_SIG_FXOGS
#define SIG_FXOKS   DAHDI_SIG_FXOKS
#define SIG_FXOLS   DAHDI_SIG_FXOLS
#define SIG_FXSGS   DAHDI_SIG_FXSGS
#define SIG_FXSKS   DAHDI_SIG_FXSKS
#define SIG_FXSLS   DAHDI_SIG_FXSLS
#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)
#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)
#define SIG_MFCR2   DAHDI_SIG_CAS
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_PRI_LIB_HANDLE_CASES   SIG_PRI
#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define tdesc   "DAHDI Telephony w/PRI"
#define TRAILER_MS   5
#define TRANSFER   0

Enumerations

enum  dahdi_call_level {
  DAHDI_CALL_LEVEL_IDLE, DAHDI_CALL_LEVEL_SETUP, DAHDI_CALL_LEVEL_OVERLAP, DAHDI_CALL_LEVEL_PROCEEDING,
  DAHDI_CALL_LEVEL_ALERTING, DAHDI_CALL_LEVEL_CONNECT
}

Functions

static int __action_dialoffhook (struct mansession *s, const struct message *m, int zap_mode)
static int __action_dnd (struct mansession *s, const struct message *m, int zap_mode, int dnd)
static int __action_restart (struct mansession *s, const struct message *m, int zap_mode)
static int __action_showchannels (struct mansession *s, const struct message *m, int zap_mode)
static int __action_transfer (struct mansession *s, const struct message *m, int zap_mode)
static int __action_transferhangup (struct mansession *s, const struct message *m, int zap_mode)
static struct ast_frame__dahdi_exception (struct ast_channel *ast)
static void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static int _dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
static char * alarm2str (int alarm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static void apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt *p, int channelmatch, ast_group_t *groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static void build_status (char *s, size_t len, int status, int active)
static int bump_gains (struct dahdi_pvt *p)
static int calc_energy (const unsigned char *buf, int len, int law)
static struct dahdi_pvtchandup (struct dahdi_pvt *src)
static int check_for_conference (struct dahdi_pvt *p)
static char * complete_span_4 (const char *line, const char *word, int pos, int state)
static char * complete_span_5 (const char *line, const char *word, int pos, int state)
static char * complete_span_helper (const char *line, const char *word, int pos, int state, int rpos)
static int conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
static int dahdi_accept_r2_call_exec (struct ast_channel *chan, void *data)
static int dahdi_action_dialoffhook (struct mansession *s, const struct message *m)
static int dahdi_action_dndoff (struct mansession *s, const struct message *m)
static int dahdi_action_dndon (struct mansession *s, const struct message *m)
static int dahdi_action_restart (struct mansession *s, const struct message *m)
static int dahdi_action_showchannels (struct mansession *s, const struct message *m)
static int dahdi_action_transfer (struct mansession *s, const struct message *m)
static int dahdi_action_transferhangup (struct mansession *s, const struct message *m)
static int dahdi_answer (struct ast_channel *ast)
static
openr2_call_disconnect_cause_t 
dahdi_ast_cause_to_r2_cause (int cause)
static enum ast_bridge_result dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int dahdi_call (struct ast_channel *ast, char *rdest, int timeout)
static int dahdi_callwait (struct ast_channel *ast)
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static void dahdi_close (int fd)
static void dahdi_close_pri_fd (struct dahdi_pri *pri, int fd_num)
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
static int dahdi_destroy_channel (int fd, int argc, char **argv)
static int dahdi_destroy_channel_bynum (int channel)
static int dahdi_digit_begin (struct ast_channel *ast, char digit)
static int dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void dahdi_disable_ec (struct dahdi_pvt *p)
static void dahdi_enable_ec (struct dahdi_pvt *p)
static struct ast_framedahdi_exception (struct ast_channel *ast)
static int dahdi_fake_event (struct dahdi_pvt *p, int mode)
static int dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int dahdi_func_read (struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
static int dahdi_func_write (struct ast_channel *chan, char *function, char *data, const char *value)
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events.
static void dahdi_handle_dtmf (struct ast_channel *ast, int index, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
static void dahdi_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx)
static struct ast_channeldahdi_new (struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
static int dahdi_open (char *fn)
static void dahdi_pri_error (struct pri *pri, char *s)
static void dahdi_pri_message (struct pri *pri, char *s)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
static int16_t dahdi_r2_alaw_to_linear (uint8_t sample)
static int dahdi_r2_answer (struct dahdi_pvt *p)
static void dahdi_r2_disconnect_call (struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
static
openr2_calling_party_category_t 
dahdi_r2_get_channel_category (struct ast_channel *c)
static uint8_t dahdi_r2_linear_to_alaw (int sample)
static void dahdi_r2_on_ani_digit_received (openr2_chan_t *r2chan, char digit)
static void dahdi_r2_on_billing_pulse_received (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_accepted (openr2_chan_t *r2chan, openr2_call_mode_t mode)
static void dahdi_r2_on_call_answered (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_disconnect (openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
static void dahdi_r2_on_call_end (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_init (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_offered (openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
static void dahdi_r2_on_call_read (openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
static void dahdi_r2_on_chan_log (openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
static void dahdi_r2_on_context_log (openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
static int dahdi_r2_on_dnis_digit_received (openr2_chan_t *r2chan, char digit)
static void dahdi_r2_on_hardware_alarm (openr2_chan_t *r2chan, int alarm)
static void dahdi_r2_on_line_blocked (openr2_chan_t *r2chan)
static void dahdi_r2_on_line_idle (openr2_chan_t *r2chan)
static void dahdi_r2_on_os_error (openr2_chan_t *r2chan, int errorcode)
static void dahdi_r2_on_protocol_error (openr2_chan_t *r2chan, openr2_protocol_error_t reason)
static void dahdi_r2_write_log (openr2_log_level_t level, char *logmessage)
static struct ast_framedahdi_read (struct ast_channel *ast)
static struct ast_channeldahdi_request (const char *type, int format, void *data, int *cause)
static int dahdi_restart (void)
static int dahdi_restart_cmd (int fd, int argc, char **argv)
static int dahdi_ring_phone (struct dahdi_pvt *p)
static int dahdi_send_keypad_facility_exec (struct ast_channel *chan, void *data)
static int dahdi_sendtext (struct ast_channel *c, const char *text)
static int dahdi_set_hook (int fd, int hs)
static int dahdi_setlaw (int dfd, int law)
static int dahdi_setlinear (int dfd, int linear)
static int dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen)
static int dahdi_show_channel (int fd, int argc, char **argv)
static int dahdi_show_channels (int fd, int argc, char **argv)
static int dahdi_show_status (int fd, int argc, char *argv[])
static char * dahdi_sig2str (int sig)
static void dahdi_softhangup_all (void)
static void dahdi_train_ec (struct dahdi_pvt *p)
static void dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events.
static int dahdi_wink (struct dahdi_pvt *p, int index)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static void destroy_all_channels (void)
static int destroy_channel (struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt **pvt)
static char * dialplan2str (int dialplan)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_idle_thread (void *vchan)
static void * do_monitor (void *data)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, int law)
static struct dahdi_pvtfind_channel (int channel)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alarms)
static int handle_dahdi_show_cadences (int fd, int argc, char *argv[])
static struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
static int handle_mfcr2_call_files (int fd, int argc, char *argv[])
static int handle_mfcr2_set_blocked (int fd, int argc, char *argv[])
static int handle_mfcr2_set_debug (int fd, int argc, char *argv[])
static int handle_mfcr2_set_idle (int fd, int argc, char *argv[])
static int handle_mfcr2_show_channels (int fd, int argc, char *argv[])
static int handle_mfcr2_show_variants (int fd, int argc, char *argv[])
static int handle_mfcr2_version (int fd, int argc, char *argv[])
static int handle_pri_debug (int fd, int argc, char *argv[])
static int handle_pri_no_debug (int fd, int argc, char *argv[])
static int handle_pri_really_debug (int fd, int argc, char *argv[])
static int handle_pri_set_debug_file (int fd, int argc, char **argv)
static int handle_pri_show_debug (int fd, int argc, char *argv[])
static int handle_pri_show_span (int fd, int argc, char *argv[])
static int handle_pri_show_spans (int fd, int argc, char *argv[])
static int handle_pri_version (int fd, int agc, char *argv[])
static int has_voicemail (struct dahdi_pvt *p)
static void init_mfcr2_globals (void)
static int isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
static int load_module (void)
static struct dahdi_mfcr2mfcr2_get_context (int id)
static void * mfcr2_monitor (void *data)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static int parse_buffers_policy (const char *parse, int *num_buffers, int *policy)
static int pri_active_dchan_fd (struct dahdi_pri *pri)
static int pri_assign_bearer (struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
static void pri_check_restart (struct dahdi_pri *pri)
static int pri_create_spanmap (int span, int trunkgroup, int logicalspan)
static int pri_create_trunkgroup (int trunkgroup, int *channels)
static void * pri_dchannel (void *vpri)
static struct dahdi_pvtpri_find_crv (struct dahdi_pri *pri, int crv)
static int pri_find_dchan (struct dahdi_pri *pri)
static int pri_find_empty_chan (struct dahdi_pri *pri, int backwards, int orig)
static int pri_find_fixup_principle (struct dahdi_pri *pri, int channel, q931_call *call)
static int pri_find_principle (struct dahdi_pri *pri, int channel)
static int pri_find_principle_by_call (struct dahdi_pri *pri, q931_call *call)
static int pri_fixup_principle (struct dahdi_pri *pri, int principle, q931_call *c)
static int pri_grab (struct dahdi_pvt *pvt, struct dahdi_pri *pri)
static int pri_hangup_all (struct dahdi_pvt *p, struct dahdi_pri *pri)
static int pri_is_up (struct dahdi_pri *pri)
static char * pri_order (int level)
static void pri_queue_control (struct dahdi_pri *pri, int chanpos, int subclass)
static void pri_queue_frame (struct dahdi_pri *pri, int chanpos, struct ast_frame *frame)
static void pri_rel (struct dahdi_pri *pri)
static int pri_resolve_span (int *span, int channel, int offset, struct dahdi_spaninfo *si)
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
static char * redirectingreason2str (int redirectingreason)
static int reload (void)
static int reset_conf (struct dahdi_pvt *p)
static int restart_monitor (void)
static int restore_conference (struct dahdi_pvt *p)
static int restore_gains (struct dahdi_pvt *p)
static int save_conference (struct dahdi_pvt *p)
static int send_callerid (struct dahdi_pvt *p)
static int send_cwcidspill (struct dahdi_pvt *p)
static int send_keypad_facility_exec (struct ast_channel *chan, void *data)
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_dahdi (int reload)
static int sig_pri_available (struct dahdi_pvt *pvt)
static int sig_pri_available_check (struct dahdi_pvt *pvt)
static int sig_pri_is_chan_available (struct dahdi_pvt *pvt)
static int sig_pri_is_chan_in_use (struct dahdi_pvt *pvt)
static void sig_pri_kill_call (struct dahdi_pri *pri, q931_call *call, int cause)
static void sig_pri_lock_owner (struct dahdi_pri *pri, int chanpos)
static void * ss_thread (void *data)
static int start_pri (struct dahdi_pri *pri)
static void swap_subs (struct dahdi_pvt *p, int a, int b)
static int unalloc_sub (struct dahdi_pvt *p, int x)
static int unload_module (void)
static int update_conf (struct dahdi_pvt *p)
static void wakeup_sub (struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
static int zap_accept_r2_call_exec (struct ast_channel *chan, void *data)
static int zap_action_dialoffhook (struct mansession *s, const struct message *m)
static int zap_action_dndoff (struct mansession *s, const struct message *m)
static int zap_action_dndon (struct mansession *s, const struct message *m)
static int zap_action_restart (struct mansession *s, const struct message *m)
static int zap_action_showchannels (struct mansession *s, const struct message *m)
static int zap_action_transfer (struct mansession *s, const struct message *m)
static int zap_action_transferhangup (struct mansession *s, const struct message *m)
static int zap_send_keypad_facility_exec (struct ast_channel *chan, void *data)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, }
struct {
   int   alarm
   char *   name
alarms []
static const struct
ast_module_info
ast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static struct ast_channel_techchan_tech
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 struct ast_cli_entry cli_zap_destroy_channel_deprecated
static struct ast_cli_entry cli_zap_restart_deprecated
static struct ast_cli_entry cli_zap_show_cadences_deprecated
static struct ast_cli_entry cli_zap_show_channel_deprecated
static struct ast_cli_entry cli_zap_show_channels_deprecated
static struct ast_cli_entry cli_zap_show_status_deprecated
static char * dahdi_accept_r2_call_app = "DAHDIAcceptR2Call"
static char * dahdi_accept_r2_call_descrip
static char * dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)"
static struct ast_cli_entry dahdi_cli []
static struct ast_cli_entry dahdi_mfcr2_cli []
static struct ast_cli_entry dahdi_pri_cli []
static const char dahdi_r2_callfiles_help []
static openr2_event_interface_t dahdi_r2_event_iface
static const char dahdi_r2_setblocked_help []
static const char dahdi_r2_setdebug_help []
static const char dahdi_r2_setidle_help []
static const char dahdi_r2_showchannels_help []
static
openr2_transcoder_interface_t 
dahdi_r2_transcode_iface
static const char dahdi_r2_variants_help []
static const char dahdi_r2_version_help []
static char dahdi_restart_usage []
static char * dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility"
static char * dahdi_send_keypad_facility_descrip
static char * dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI"
static char dahdi_show_cadences_usage []
static char dahdi_show_status_usage []
static struct ast_channel_tech dahdi_tech
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 dahdi_distRings drings
static int dtmfcid_level = 256
static char * events []
static int firstdigittimeout = 16000
 Wait up to 16 seconds for first digit (FXO logic).
static int gendigittimeout = 8000
 How long to wait for following digits (FXO logic).
static struct ast_jb_conf global_jbconf
static int ifcount = 0
static struct dahdi_pvtifend
static struct dahdi_pvtiflist
static ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 Protect the interface list (of dahdi_pvt's).
static struct ast_channel inuse
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static int mfcr2_cur_accept_on_offer = 1
static int mfcr2_cur_allow_collect_calls = 0
static int mfcr2_cur_call_files = 0
static
openr2_calling_party_category_t 
mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
static int mfcr2_cur_charge_calls = 1
static int mfcr2_cur_context_index = 0
static int mfcr2_cur_double_answer = 0
static int mfcr2_cur_forced_release = 0
static int mfcr2_cur_get_ani_first = -1
static int mfcr2_cur_immediate_accept = -1
static char mfcr2_cur_logdir [OR2_MAX_PATH]
static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING
static int mfcr2_cur_max_ani = 10
static int mfcr2_cur_max_dnis = 4
static int mfcr2_cur_metering_pulse_timeout = -1
static int mfcr2_cur_mfback_timeout = -1
static char mfcr2_cur_r2proto_file [OR2_MAX_PATH]
static int mfcr2_cur_skip_category = -1
static openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN
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 ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static const char pri_debug_help []
static const char pri_no_debug_help []
static const char pri_really_debug_help []
static const char pri_show_span_help []
static const char pri_show_spans_help []
static int pridebugfd = -1
static ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char pridebugfilename [1024] = ""
static struct dahdi_pri pris [NUM_SPANS]
static char progzone [10] = ""
static struct dahdi_mfcr2 r2links [NUM_SPANS]
static ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
struct dahdi_pvtround_robin [32]
static char show_channel_usage []
static char show_channels_usage []
static ast_cond_t ss_thread_complete
static int ss_thread_count = 0
static ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char * subnames []
static const char tdesc []
static int user_has_defined_cadences = 0
static char * zap_accept_r2_call_app = "ZapAcceptR2Call"
static char * zap_accept_r2_call_descrip
static char * zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)"
static char * zap_send_keypad_facility_app = "ZapSendKeypadFacility"
static char * zap_send_keypad_facility_descrip
static char * zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI"
static struct ast_channel_tech zap_tech

Detailed Description

DAHDI Pseudo TDM interface.

Author:
Mark Spencer <markster@digium.com>

Connects to the DAHDI 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 DAHDI channel.

See also
  • Config_dahdi
Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by dahdi_sendtext().

#define AST_LAW (  )     (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
#define CALLWAITING_REPEAT_SAMPLES   ((10000 * 8) / READ_SIZE)

10,000 ms

Definition at line 316 of file chan_dahdi.c.

Referenced by dahdi_callwait().

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

300 ms

Definition at line 315 of file chan_dahdi.c.

#define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE)

100 ms

Definition at line 317 of file chan_dahdi.c.

Referenced by send_callerid().

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

Definition at line 1241 of file chan_dahdi.c.

Referenced by dahdi_new().

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

Definition at line 1242 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

#define CHAN_PSEUDO   -2
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)

500 ms

Definition at line 318 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 509 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 510 of file chan_dahdi.c.

#define DAHDI_EVENT_DTMFDOWN   0

Definition at line 126 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DAHDI_EVENT_DTMFUP   0

Definition at line 127 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define dahdi_get_index ( ast,
p,
nullok   )     _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

Definition at line 226 of file chan_dahdi.c.

Referenced by process_dahdi(), and start_pri().

#define DAHDI_OVERLAPDIAL_INCOMING   2
#define DAHDI_OVERLAPDIAL_NONE   0

Definition at line 223 of file chan_dahdi.c.

Referenced by process_dahdi().

#define DAHDI_OVERLAPDIAL_OUTGOING   1

Definition at line 224 of file chan_dahdi.c.

Referenced by dahdi_read(), pri_dchannel(), process_dahdi(), and start_pri().

#define DAHDI_R2_LOCAL_BLOCK   (1 << 1)
#define DAHDI_R2_REMOTE_BLOCK   (1 << 0)

Definition at line 1722 of file chan_dahdi.c.

Referenced by dahdi_r2_on_line_blocked(), dahdi_r2_on_line_idle(), and mkintf().

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 220 of file chan_dahdi.c.

Referenced by pri_find_dchan(), and pri_is_up().

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 217 of file chan_dahdi.c.

Referenced by build_status(), pri_dchannel(), and start_pri().

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 216 of file chan_dahdi.c.

Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().

#define DCHAN_UP   (1 << 2)

Definition at line 218 of file chan_dahdi.c.

Referenced by build_status(), and pri_dchannel().

#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 167 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

#define DEFAULT_PRI_DEBUG   0

Definition at line 449 of file chan_dahdi.c.

Referenced by start_pri().

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

8,000 ms

Definition at line 320 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

#define FORCE_RESTART_UNAVAIL_CHANS   1

Define to make always pick a channel if allowed. Useful for testing channel shifting.

Define to force a RESTART on a channel that returns a cause code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If the cause is because of a stuck channel on the peer and the channel is always the next channel we pick for an outgoing call then this can help.

Definition at line 146 of file chan_dahdi.c.

#define FORMAT   "%-40.40s %-10.10s %-10d %-10d %-10d\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define FORMAT   "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
#define FORMAT   "%4s %40s\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)->bearer ? (p)->bearer->channel : p->channel)

Definition at line 1191 of file chan_dahdi.c.

Referenced by update_conf().

#define HANGUP   1

Definition at line 13667 of file chan_dahdi.c.

Referenced by __action_transferhangup(), and dahdi_fake_event().

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

Referenced by dahdi_sendtext().

#define ISTRUNK (  ) 
Value:
((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
         (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))

Definition at line 1238 of file chan_dahdi.c.

Referenced by dahdi_indicate(), dahdi_show_channel(), and ss_thread().

#define local_astman_ack ( s,
m,
msg,
zap   )     do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
#define local_astman_header ( m,
hdr,
zap   )     astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
#define local_astman_register ( a,
b,
c,
 ) 

Definition at line 15104 of file chan_dahdi.c.

Referenced by load_module().

#define local_astman_unregister (  ) 

Definition at line 13918 of file chan_dahdi.c.

Referenced by __unload_module().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 312 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 313 of file chan_dahdi.c.

#define MAX_CHANLIST_LEN   80

The length of the parameters list of 'dahdichan'.

Todo:
Move definition of MAX_CHANLIST_LEN to a proper place.

Definition at line 14120 of file chan_dahdi.c.

Referenced by process_dahdi().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 212 of file chan_dahdi.c.

Referenced by mkintf().

#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

Definition at line 319 of file chan_dahdi.c.

Referenced by dahdi_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 172 of file chan_dahdi.c.

Referenced by dahdi_new(), and ss_thread().

#define NUM_CADENCE_MAX   25

Definition at line 1216 of file chan_dahdi.c.

Referenced by process_dahdi().

#define NUM_DCHANS   4
#define NUM_SPANS   32
#define POLARITY_IDLE   0

Definition at line 467 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), dahdi_hangup(), ss_thread(), and unalloc_sub().

#define POLARITY_REV   1

Definition at line 468 of file chan_dahdi.c.

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

#define PRI_CHANNEL (  )     ((p) & 0xff)

Definition at line 372 of file chan_dahdi.c.

Referenced by pri_dchannel(), pri_find_fixup_principle(), and pri_find_principle().

#define PRI_EXPLICIT (  )     (((p) >> 16) & 0x01)

Definition at line 374 of file chan_dahdi.c.

Referenced by pri_find_principle().

#define PRI_SPAN (  )     (((p) >> 8) & 0xff)

Definition at line 373 of file chan_dahdi.c.

Referenced by pri_dchannel(), pri_find_fixup_principle(), and pri_find_principle().

#define PVT_TO_CHANNEL (  )     (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))

Definition at line 371 of file chan_dahdi.c.

Referenced by dahdi_call(), dahdi_indicate(), pri_check_restart(), pri_dchannel(), and ss_thread().

#define READ_SIZE   160

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

Definition at line 310 of file chan_dahdi.c.

Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().

#define sig2str   dahdi_sig2str
#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)
#define SIG_EM   DAHDI_SIG_EM
#define SIG_EM_E1   DAHDI_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)
#define SIG_FXOGS   DAHDI_SIG_FXOGS
#define SIG_FXOKS   DAHDI_SIG_FXOKS
#define SIG_FXOLS   DAHDI_SIG_FXOLS
#define SIG_FXSGS   DAHDI_SIG_FXSGS
#define SIG_FXSKS   DAHDI_SIG_FXSKS
#define SIG_FXSLS   DAHDI_SIG_FXSLS
#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)

Definition at line 207 of file chan_dahdi.c.

Referenced by dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().

#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)

Definition at line 208 of file chan_dahdi.c.

Referenced by dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().

#define SIG_MFCR2   DAHDI_SIG_CAS
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_PRI_LIB_HANDLE_CASES   SIG_PRI

Definition at line 285 of file chan_dahdi.c.

Referenced by available(), and dahdi_request().

#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 109 of file chan_dahdi.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define tdesc   "DAHDI Telephony w/PRI"

Definition at line 15302 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Definition at line 13666 of file chan_dahdi.c.

Referenced by __action_transfer(), and dahdi_fake_event().


Enumeration Type Documentation

Call establishment life cycle level for simple comparisons.

Enumerator:
DAHDI_CALL_LEVEL_IDLE 

Call does not exist.

DAHDI_CALL_LEVEL_SETUP 

Call is present but has no response yet. (SETUP)

DAHDI_CALL_LEVEL_OVERLAP 

Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE)

DAHDI_CALL_LEVEL_PROCEEDING 

Call routing is happening. (PROCEEDING)

DAHDI_CALL_LEVEL_ALERTING 

Called party is being alerted of the call. (ALERTING)

DAHDI_CALL_LEVEL_CONNECT 

Call is connected/answered. (CONNECT)

Definition at line 377 of file chan_dahdi.c.

00377                       {
00378    /*! Call does not exist. */
00379    DAHDI_CALL_LEVEL_IDLE,
00380    /*! Call is present but has no response yet. (SETUP) */
00381    DAHDI_CALL_LEVEL_SETUP,
00382    /*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */
00383    DAHDI_CALL_LEVEL_OVERLAP,
00384    /*! Call routing is happening. (PROCEEDING) */
00385    DAHDI_CALL_LEVEL_PROCEEDING,
00386    /*! Called party is being alerted of the call. (ALERTING) */
00387    DAHDI_CALL_LEVEL_ALERTING,
00388    /*! Call is connected/answered. (CONNECT) */
00389    DAHDI_CALL_LEVEL_CONNECT,
00390 };


Function Documentation

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

Definition at line 13796 of file chan_dahdi.c.

References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_error(), dahdi_pvt::channel, dahdi_queue_frame(), find_channel(), local_astman_ack, local_astman_header, and dahdi_pvt::owner.

Referenced by dahdi_action_dialoffhook(), and zap_action_dialoffhook().

13797 {
13798    struct dahdi_pvt *p = NULL;
13799    const char *channel = local_astman_header(m, "Channel", zap_mode);
13800    const char *number = astman_get_header(m, "Number");
13801    int i;
13802 
13803    if (ast_strlen_zero(channel)) {
13804       astman_send_error(s, m, "No channel specified");
13805       return 0;
13806    }
13807    if (ast_strlen_zero(number)) {
13808       astman_send_error(s, m, "No number specified");
13809       return 0;
13810    }
13811    if (!(p = find_channel(atoi(channel)))) {
13812       astman_send_error(s, m, "No such channel");
13813       return 0;
13814    }
13815    if (!p->owner) {
13816       astman_send_error(s, m, "Channel does not have an owner");
13817       return 0;
13818    }
13819    for (i = 0; i < strlen(number); i++) {
13820       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13821 
13822       dahdi_queue_frame(p, &f, NULL); 
13823    }
13824    local_astman_ack(s, m, "DialOffHook", zap_mode);
13825 
13826    return 0;
13827 }

static int __action_dnd ( struct mansession s,
const struct message m,
int  zap_mode,
int  dnd 
) [static]

Definition at line 13700 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, find_channel(), local_astman_ack, and local_astman_header.

Referenced by dahdi_action_dndoff(), dahdi_action_dndon(), zap_action_dndoff(), and zap_action_dndon().

13701 {
13702    struct dahdi_pvt *p = NULL;
13703    const char *channel = local_astman_header(m, "Channel", zap_mode);
13704 
13705    if (ast_strlen_zero(channel)) {
13706       astman_send_error(s, m, "No channel specified");
13707       return 0;
13708    }
13709    if (!(p = find_channel(atoi(channel)))) {
13710       astman_send_error(s, m, "No such channel");
13711       return 0;
13712    }
13713    p->dnd = dnd;
13714    local_astman_ack(s, m, "DND", zap_mode);
13715 
13716    return 0;
13717 }

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

Definition at line 13894 of file chan_dahdi.c.

References astman_send_error(), dahdi_restart(), and local_astman_ack.

Referenced by dahdi_action_restart(), and zap_action_restart().

13895 {
13896    if (dahdi_restart() != 0) {
13897       if (zap_mode) {
13898          astman_send_error(s, m, "Failed to restart Zap");
13899       } else {
13900          astman_send_error(s, m, "Failed to restart DAHDI");
13901       }
13902       return 1;
13903    }
13904    local_astman_ack(s, m, "Restart: Success", zap_mode);
13905    return 0;
13906 }

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

Definition at line 13839 of file chan_dahdi.c.

References alarm, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_chan_name, dahdi_pvt::dnd, get_alarms(), iflist, iflock, local_astman_ack, dahdi_pvt::next, dahdi_pvt::sig, and sig2str.

Referenced by dahdi_action_showchannels(), and zap_action_showchannels().

13840 {
13841    struct dahdi_pvt *tmp = NULL;
13842    const char *id = astman_get_header(m, "ActionID");
13843    char idText[256] = "";
13844 
13845    local_astman_ack(s, m, " channel status will follow", zap_mode);
13846    if (!ast_strlen_zero(id))
13847       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
13848 
13849    ast_mutex_lock(&iflock);
13850    
13851    tmp = iflist;
13852    while (tmp) {
13853       if (tmp->channel > 0) {
13854          int alarm = get_alarms(tmp);
13855          astman_append(s,
13856                   "Event: %sShowChannels\r\n"
13857                   "Channel: %d\r\n"
13858                   "Signalling: %s\r\n"
13859                   "Context: %s\r\n"
13860                   "DND: %s\r\n"
13861                   "Alarm: %s\r\n"
13862                   "%s"
13863                   "\r\n",
13864                   dahdi_chan_name,
13865                   tmp->channel, sig2str(tmp->sig), tmp->context, 
13866                   tmp->dnd ? "Enabled" : "Disabled",
13867                   alarm2str(alarm), idText);
13868       } 
13869 
13870       tmp = tmp->next;
13871    }
13872 
13873    ast_mutex_unlock(&iflock);
13874    
13875    astman_append(s, 
13876             "Event: %sShowChannelsComplete\r\n"
13877             "%s"
13878             "\r\n",
13879             dahdi_chan_name,
13880             idText);
13881    return 0;
13882 }

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

Definition at line 13739 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), local_astman_ack, local_astman_header, and TRANSFER.

Referenced by dahdi_action_transfer(), and zap_action_transfer().

13740 {
13741    struct dahdi_pvt *p = NULL;
13742    const char *channel = local_astman_header(m, "Channel", zap_mode);
13743 
13744    if (ast_strlen_zero(channel)) {
13745       astman_send_error(s, m, "No channel specified");
13746       return 0;
13747    }
13748    if (!(p = find_channel(atoi(channel)))) {
13749       astman_send_error(s, m, "No such channel");
13750       return 0;
13751    }
13752    dahdi_fake_event(p,TRANSFER);
13753    local_astman_ack(s, m, "Transfer", zap_mode);
13754 
13755    return 0;
13756 }

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

Definition at line 13768 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), HANGUP, local_astman_ack, and local_astman_header.

Referenced by dahdi_action_transferhangup(), and zap_action_transferhangup().

13769 {
13770    struct dahdi_pvt *p = NULL;
13771    const char *channel = local_astman_header(m, "Channel", zap_mode);
13772 
13773    if (ast_strlen_zero(channel)) {
13774       astman_send_error(s, m, "No channel specified");
13775       return 0;
13776    }
13777    if (!(p = find_channel(atoi(channel)))) {
13778       astman_send_error(s, m, "No such channel");
13779       return 0;
13780    }
13781    dahdi_fake_event(p, HANGUP);
13782    local_astman_ack(s, m, "Hangup", zap_mode);
13783    return 0;
13784 }

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

Definition at line 6143 of file chan_dahdi.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_tv(), ast_verbose(), dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, event2str(), dahdi_subchannel::f, dahdi_pvt::fake_event, ast_channel::fds, dahdi_pvt::flashtime, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, dahdi_subchannel::needanswer, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, update_conf(), and VERBOSE_PREFIX_3.

Referenced by dahdi_exception(), and dahdi_read().

06144 {
06145    struct dahdi_pvt *p = ast->tech_pvt;
06146    int res;
06147    int index;
06148    struct ast_frame *f;
06149 
06150 
06151    index = dahdi_get_index(ast, p, 1);
06152    if (index < 0) {
06153       index = SUB_REAL;
06154    }
06155    
06156    p->subs[index].f.frametype = AST_FRAME_NULL;
06157    p->subs[index].f.datalen = 0;
06158    p->subs[index].f.samples = 0;
06159    p->subs[index].f.mallocd = 0;
06160    p->subs[index].f.offset = 0;
06161    p->subs[index].f.subclass = 0;
06162    p->subs[index].f.delivery = ast_tv(0,0);
06163    p->subs[index].f.src = "dahdi_exception";
06164    p->subs[index].f.data = NULL;
06165    
06166    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06167       /* If nobody owns us, absorb the event appropriately, otherwise
06168          we loop indefinitely.  This occurs when, during call waiting, the
06169          other end hangs up our channel so that it no longer exists, but we
06170          have neither FLASH'd nor ONHOOK'd to signify our desire to
06171          change to the other channel. */
06172       if (p->fake_event) {
06173          res = p->fake_event;
06174          p->fake_event = 0;
06175       } else
06176          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06177       /* Switch to real if there is one and this isn't something really silly... */
06178       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06179          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06180          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
06181          p->owner = p->subs[SUB_REAL].owner;
06182          if (p->owner && ast != p->owner) {
06183             /*
06184              * Could this even happen?
06185              * Possible deadlock because we do not have the real-call lock.
06186              */
06187             ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n",
06188                event2str(res), ast->name, p->owner->name);
06189          }
06190          if (p->owner && ast_bridged_channel(p->owner))
06191             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06192          p->subs[SUB_REAL].needunhold = 1;
06193       }
06194       switch (res) {
06195       case DAHDI_EVENT_ONHOOK:
06196          dahdi_disable_ec(p);
06197          if (p->owner) {
06198             if (option_verbose > 2) 
06199                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
06200             dahdi_ring_phone(p);
06201             p->callwaitingrepeat = 0;
06202             p->cidcwexpire = 0;
06203             p->cid_suppress_expire = 0;
06204          } else {
06205             ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
06206                event2str(res));
06207          }
06208          update_conf(p);
06209          break;
06210       case DAHDI_EVENT_RINGOFFHOOK:
06211          dahdi_enable_ec(p);
06212          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06213          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06214             p->subs[SUB_REAL].needanswer = 1;
06215             p->dialing = 0;
06216          }
06217          break;
06218       case DAHDI_EVENT_HOOKCOMPLETE:
06219       case DAHDI_EVENT_RINGERON:
06220       case DAHDI_EVENT_RINGEROFF:
06221          /* Do nothing */
06222          break;
06223       case DAHDI_EVENT_WINKFLASH:
06224          gettimeofday(&p->flashtime, NULL);
06225          if (p->owner) {
06226             if (option_verbose > 2) 
06227                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06228             if (p->owner->_state != AST_STATE_UP) {
06229                /* Answer if necessary */
06230                p->subs[SUB_REAL].needanswer = 1;
06231                ast_setstate(p->owner, AST_STATE_UP);
06232             }
06233             p->callwaitingrepeat = 0;
06234             p->cidcwexpire = 0;
06235             p->cid_suppress_expire = 0;
06236             if (ast_bridged_channel(p->owner))
06237                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06238             p->subs[SUB_REAL].needunhold = 1;
06239          } else {
06240             ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
06241                event2str(res));
06242          }
06243          update_conf(p);
06244          break;
06245       default:
06246          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06247          break;
06248       }
06249       f = &p->subs[index].f;
06250       return f;
06251    }
06252    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
06253       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06254    /* If it's not us, return NULL immediately */
06255    if (ast != p->owner) {
06256       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06257       f = &p->subs[index].f;
06258       return f;
06259    }
06260    f = dahdi_handle_event(ast);
06261    return f;
06262 }

static void __reg_module ( void   )  [static]

Definition at line 15311 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 13925 of file chan_dahdi.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), CHAN_DAHDI_PLUS_ZAP_MODE, dahdi_chan_mode, dahdi_close_pri_fd(), destroy_all_channels(), iflist, iflock, local_astman_unregister, master, monlock, dahdi_pvt::next, NUM_DCHANS, NUM_SPANS, dahdi_pvt::owner, pris, and r2links.

Referenced by load_module(), and unload_module().

13926 {
13927    struct dahdi_pvt *p;
13928 
13929 #ifdef HAVE_OPENR2
13930    int r;
13931 #endif
13932 
13933 #ifdef HAVE_PRI
13934    int i, j;
13935    for (i = 0; i < NUM_SPANS; i++) {
13936       if (pris[i].master != AST_PTHREADT_NULL) 
13937          pthread_cancel(pris[i].master);
13938    }
13939    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13940 
13941    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13942       ast_unregister_application(dahdi_send_keypad_facility_app);
13943    }
13944    ast_unregister_application(zap_send_keypad_facility_app);
13945 #endif
13946 
13947 #ifdef HAVE_OPENR2
13948    for (r = 0; r < NUM_SPANS; r++) {
13949       if (r2links[r].master != AST_PTHREADT_NULL) {
13950          pthread_cancel(r2links[r].master);
13951          pthread_join(r2links[r].master, NULL);
13952       }
13953    }
13954    ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
13955    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13956       ast_unregister_application(dahdi_accept_r2_call_app);
13957    }
13958    ast_unregister_application(zap_accept_r2_call_app);
13959 #endif
13960 
13961    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13962    local_astman_unregister("DialOffHook");
13963    local_astman_unregister("Hangup");
13964    local_astman_unregister("Transfer");
13965    local_astman_unregister("DNDoff");
13966    local_astman_unregister("DNDon");
13967    local_astman_unregister("ShowChannels");
13968    local_astman_unregister("Restart");
13969    ast_channel_unregister(chan_tech);
13970    ast_mutex_lock(&iflock);
13971    /* Hangup all interfaces if they have an owner */
13972    p = iflist;
13973    while (p) {
13974       if (p->owner)
13975          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
13976       p = p->next;
13977    }
13978    ast_mutex_unlock(&iflock);
13979    ast_mutex_lock(&monlock);
13980    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13981       pthread_cancel(monitor_thread);
13982       pthread_kill(monitor_thread, SIGURG);
13983       pthread_join(monitor_thread, NULL);
13984    }
13985    monitor_thread = AST_PTHREADT_STOP;
13986    ast_mutex_unlock(&monlock);
13987 
13988    destroy_all_channels();
13989 #ifdef HAVE_PRI      
13990    for (i = 0; i < NUM_SPANS; i++) {
13991       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
13992          pthread_join(pris[i].master, NULL);
13993       for (j = 0; j < NUM_DCHANS; j++) {
13994          dahdi_close_pri_fd(&(pris[i]), j);
13995       }
13996    }
13997 #endif
13998 
13999 #ifdef HAVE_OPENR2
14000    for (r = 0; r < NUM_SPANS; r++) {
14001       if (r2links[r].protocol_context) {
14002          openr2_context_delete(r2links[r].protocol_context);
14003       }
14004    }
14005 #endif
14006 
14007    ast_cond_destroy(&ss_thread_complete);
14008    return 0;
14009 }

static void __unreg_module ( void   )  [static]

Definition at line 15311 of file chan_dahdi.c.

static int _dahdi_get_index ( struct ast_channel ast,
struct dahdi_pvt p,
int  nullok,
const char *  fname,
unsigned long  line 
) [static]

Definition at line 1245 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, LOG_WARNING, dahdi_subchannel::owner, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

01246 {
01247    int res;
01248    if (p->subs[SUB_REAL].owner == ast)
01249       res = 0;
01250    else if (p->subs[SUB_CALLWAIT].owner == ast)
01251       res = 1;
01252    else if (p->subs[SUB_THREEWAY].owner == ast)
01253       res = 2;
01254    else {
01255       res = -1;
01256       if (!nullok)
01257          ast_log(LOG_WARNING,
01258             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
01259             ast ? ast->name : "", p->channel, fname, line);
01260    }
01261    return res;
01262 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 2169 of file chan_dahdi.c.

References alarms.

Referenced by __action_showchannels(), and handle_alarms().

02170 {
02171    int x;
02172    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
02173       if (alarms[x].alarm & alarm)
02174          return alarms[x].name;
02175    }
02176    return alarm ? "Unknown Alarm" : "No Alarm";
02177 }

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

Definition at line 1954 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), DAHDI_FILE_PSEUDO, dahdi_open(), dahdi_subchannel::dfd, errno, LOG_DEBUG, LOG_WARNING, option_debug, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().

01955 {
01956    struct dahdi_bufferinfo bi;
01957    int res;
01958    if (p->subs[x].dfd < 0) {
01959       p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01960       if (p->subs[x].dfd > -1) {
01961          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01962          if (!res) {
01963             bi.txbufpolicy = p->buf_policy;
01964             bi.rxbufpolicy = p->buf_policy;
01965             bi.numbufs = p->buf_no;
01966             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01967             if (res < 0) {
01968                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01969             }
01970          } else 
01971             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01972          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01973             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01974             dahdi_close_sub(p, x);
01975             return -1;
01976          }
01977          if (option_debug)
01978             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01979          return 0;
01980       } else
01981          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01982       return -1;
01983    }
01984    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01985    return -1;
01986 }

static void apply_plan_to_number ( char *  buf,
size_t  size,
const struct dahdi_pri pri,
const char *  number,
const int  plan 
) [static]

Definition at line 10990 of file chan_dahdi.c.

References ast_strlen_zero(), dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.

Referenced by pri_dchannel().

10991 {
10992    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10993       if (size) {
10994          *buf = '\0';
10995       }
10996       return;
10997    }
10998 
10999    switch (plan) {
11000    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
11001       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
11002       break;
11003    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
11004       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
11005       break;
11006    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
11007       snprintf(buf, size, "%s%s", pri->localprefix, number);
11008       break;
11009    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
11010       snprintf(buf, size, "%s%s", pri->privateprefix, number);
11011       break;
11012    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
11013       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
11014       break;
11015    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
11016       snprintf(buf, size, "%s", number);
11017       break;
11018    }
11019 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 4981 of file chan_dahdi.c.

References ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_indicate(), ast_log(), ast_mutex_unlock(), ast_queue_control(), AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, ast_channel::lock, LOG_DEBUG, LOG_WARNING, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().

Referenced by dahdi_handle_event(), handle_onhook_message(), and handle_soft_key_event_message().

04982 {
04983    /* In order to transfer, we need at least one of the channels to
04984       actually be in a call bridge.  We can't conference two applications
04985       together (but then, why would we want to?) */
04986    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04987       /* The three-way person we're about to transfer to could still be in MOH, so
04988          stop it now if appropriate */
04989       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04990          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04991       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04992          /*
04993           * This may not be safe.
04994           * We currently hold the locks on the real-call, private, and 3-way call.
04995           * We could possibly avoid this here by using an ast_queue_control() instead.
04996           * However, the following ast_channel_masquerade() is going to be locking
04997           * the bridged channel again anyway.
04998           */
04999          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05000       }
05001       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05002          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05003       }
05004        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05005          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05006                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05007          return -1;
05008       }
05009       /* Orphan the channel after releasing the lock */
05010       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05011       unalloc_sub(p, SUB_THREEWAY);
05012    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05013       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05014       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05015          /*
05016           * This may not be safe.
05017           * We currently hold the locks on the real-call, private, and 3-way call.
05018           * We could possibly avoid this here by using an ast_queue_control() instead.
05019           * However, the following ast_channel_masquerade() is going to be locking
05020           * the bridged channel again anyway.
05021           */
05022          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05023       }
05024       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05025          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05026       }
05027       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05028          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05029                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05030          return -1;
05031       }
05032       /* Three-way is now the REAL */
05033       swap_subs(p, SUB_THREEWAY, SUB_REAL);
05034       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05035       unalloc_sub(p, SUB_THREEWAY);
05036       /* Tell the caller not to hangup */
05037       return 1;
05038    } else {
05039       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05040                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05041       return -1;
05042    }
05043    return 0;
05044 }

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

Definition at line 9798 of file chan_dahdi.c.

References ast_channel::_state, ast_have_common_group(), ast_is_empty_group(), ast_log(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::callwaiting, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::dnd, errno, dahdi_pvt::group, dahdi_pvt::guardtime, dahdi_subchannel::inthreeway, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, sig_pri_available(), SIG_PRI_LIB_HANDLE_CASES, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

Referenced by __ast_string_field_index_build_va(), and dahdi_request().

09799 {
09800    int res;
09801    struct dahdi_params par;
09802 
09803    /* First, check group matching */
09804    if (!ast_is_empty_group(groupmatch)) {
09805       if (!ast_have_common_group(&p->group, groupmatch)) {
09806          /* Doesn't match the specified group, try the next one */
09807          return 0;
09808       }
09809       *groupmatched = 1;
09810    }
09811    /* Check to see if we have a channel match */
09812    if (channelmatch != -1) {
09813       if (p->channel != channelmatch)
09814          return 0;
09815       *channelmatched = 1;
09816    }
09817 
09818 #if defined(HAVE_PRI)
09819    switch (p->sig) {
09820    case SIG_PRI_LIB_HANDLE_CASES:
09821       return sig_pri_available(p);
09822    default:
09823       break;
09824    }
09825 #endif   /* defined(HAVE_PRI) */
09826 
09827    /* We're at least busy at this point */
09828    if (busy) {
09829       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09830          *busy = 1;
09831    }
09832    /* If do not disturb, definitely not */
09833    if (p->dnd)
09834       return 0;
09835    /* If guard time, definitely not */
09836    if (p->guardtime && (time(NULL) < p->guardtime)) 
09837       return 0;
09838       
09839    /* If no owner definitely available */
09840    if (!p->owner) {
09841 #ifdef HAVE_PRI
09842       /* Trust PRI */
09843       if (p->pri) {
09844          /* Likely only GR-303 gets here. */
09845          return sig_pri_available(p);
09846       }
09847 #endif
09848 
09849 #ifdef HAVE_OPENR2
09850       /* Trust MFC/R2 */
09851       if (p->mfcr2) {
09852          if (p->mfcr2call || p->mfcr2block)
09853             return 0;
09854          else
09855             return 1;
09856       }
09857 #endif
09858 
09859       if (!(p->radio || (p->oprmode < 0)))
09860       {
09861          if (!p->sig || (p->sig == SIG_FXSLS))
09862             return 1;
09863          /* Check hook state */
09864          if (p->subs[SUB_REAL].dfd > -1) {
09865             memset(&par, 0, sizeof(par));
09866             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09867          } else {
09868             /* Assume not off hook on CVRS */
09869             res = 0;
09870             par.rxisoffhook = 0;
09871          }
09872          if (res) {
09873             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09874          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09875             /* When "onhook" that means no battery on the line, and thus
09876               it is out of service..., if it's on a TDM card... If it's a channel
09877               bank, there is no telling... */
09878             if (par.rxbits > -1)
09879                return 1;
09880             if (par.rxisoffhook)
09881                return 1;
09882             else
09883 #ifdef DAHDI_CHECK_HOOKSTATE
09884                return 0;
09885 #else
09886                return 1;
09887 #endif
09888          } else if (par.rxisoffhook) {
09889             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09890             /* Not available when the other end is off hook */
09891             return 0;
09892          }
09893       }
09894       return 1;
09895    }
09896 
09897    /* If it's not an FXO, forget about call wait */
09898    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09899       return 0;
09900 
09901    if (!p->callwaiting) {
09902       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09903       return 0;
09904    }
09905 
09906    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09907       /* If there is already a call waiting call, then we can't take a second one */
09908       return 0;
09909    }
09910    
09911    if ((p->owner->_state != AST_STATE_UP) &&
09912        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09913       /* If the current call is not up, then don't allow the call */
09914       return 0;
09915    }
09916    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09917       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09918       return 0;
09919    }
09920    /* We're cool */
09921    return 1;
09922 }

static int build_channels ( struct dahdi_chan_conf conf,
int  iscrv,
const char *  value,
int  reload,
int  lineno,
int *  found_pseudo 
) [static]

Definition at line 14021 of file chan_dahdi.c.

References ast_log(), ast_strdupa, ast_verbose(), dahdi_chan_conf::chan, CHAN_PSEUDO, LOG_ERROR, LOG_WARNING, mkintf(), NUM_SPANS, option_verbose, pris, r2links, dahdi_pvt::sig, sig2str, strsep(), dahdi_pri::trunkgroup, and VERBOSE_PREFIX_3.

Referenced by process_dahdi().

14022 {
14023    char *c, *chan;
14024    int x, start, finish;
14025    struct dahdi_pvt *tmp;
14026 #ifdef HAVE_PRI
14027    struct dahdi_pri *pri;
14028    int trunkgroup, y;
14029 #endif
14030    
14031    if ((reload == 0) && (conf->chan.sig < 0)) {
14032       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14033       return -1;
14034    }
14035 
14036    c = ast_strdupa(value);
14037 
14038 #ifdef HAVE_PRI
14039    pri = NULL;
14040    if (iscrv) {
14041       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14042          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
14043          return -1;
14044       }
14045       if (trunkgroup < 1) {
14046          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
14047          return -1;
14048       }
14049       c += y;
14050       for (y = 0; y < NUM_SPANS; y++) {
14051          if (pris[y].trunkgroup == trunkgroup) {
14052             pri = pris + y;
14053             break;
14054          }
14055       }
14056       if (!pri) {
14057          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
14058          return -1;
14059       }
14060    }
14061 #endif         
14062 
14063    while ((chan = strsep(&c, ","))) {
14064       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14065          /* Range */
14066       } else if (sscanf(chan, "%30d", &start)) {
14067          /* Just one */
14068          finish = start;
14069       } else if (!strcasecmp(chan, "pseudo")) {
14070          finish = start = CHAN_PSEUDO;
14071          if (found_pseudo)
14072             *found_pseudo = 1;
14073       } else {
14074          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14075          return -1;
14076       }
14077       if (finish < start) {
14078          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14079          x = finish;
14080          finish = start;
14081          start = x;
14082       }
14083 
14084       for (x = start; x <= finish; x++) {
14085 #ifdef HAVE_PRI
14086          tmp = mkintf(x, conf, pri, reload);
14087 #else       
14088          tmp = mkintf(x, conf, NULL, reload);
14089 #endif         
14090 
14091          if (tmp) {
14092             if (option_verbose > 2) {
14093 #ifdef HAVE_PRI
14094                if (pri)
14095                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14096                else
14097 #endif
14098                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14099             }
14100          } else {
14101             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14102                (reload == 1) ? "reconfigure" : "register", value);
14103             return -1;
14104          }
14105       }
14106 
14107 #ifdef HAVE_OPENR2
14108       if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
14109          mfcr2_cur_context_index++;
14110       }  
14111 #endif
14112 
14113    }
14114 
14115    return 0;
14116 }

static void build_status ( char *  s,
size_t  len,
int  status,
int  active 
) [static]

Definition at line 12571 of file chan_dahdi.c.

References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

12572 {
12573    if (!s || len < 1) {
12574       return;
12575    }
12576    s[0] = '\0';
12577    if (status & DCHAN_PROVISIONED)
12578       strncat(s, "Provisioned, ", len - strlen(s) - 1);
12579    if (!(status & DCHAN_NOTINALARM))
12580       strncat(s, "In Alarm, ", len - strlen(s) - 1);
12581    if (status & DCHAN_UP)
12582       strncat(s, "Up", len - strlen(s) - 1);
12583    else
12584       strncat(s, "Down", len - strlen(s) - 1);
12585    if (active)
12586       strncat(s, ", Active", len - strlen(s) - 1);
12587    else
12588       strncat(s, ", Standby", len - strlen(s) - 1);
12589    s[len - 1] = '\0';
12590 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 2620 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::dfd, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.

Referenced by ss_thread().

02621 {
02622    int res;
02623 
02624    /* Bump receive gain by 5.0db */
02625    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
02626    if (res) {
02627       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02628       return -1;
02629    }
02630 
02631    return 0;
02632 }

static int calc_energy ( const unsigned char *  buf,
int  len,
int  law 
) [static]

Definition at line 8461 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, ast_log(), AST_MULAW, LOG_WARNING, and option_verbose.

Referenced by do_monitor().

08462 {
08463    int x;
08464    int sum = 0;
08465    int ssum = 0, mean = 0;
08466 
08467    if (!len)
08468       return 0;
08469 
08470    /* First calc mean signal (DC offset) */
08471    for (x = 0; x < len; x++)
08472          ssum += (law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
08473 
08474    mean = ssum / len;   
08475 
08476    for (x = 0; x < len; x++) {
08477          sum += abs((law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])) - mean);
08478       if (option_verbose > 7)
08479             ast_log(LOG_WARNING, "x %i, bufx: %i sum %i, ssum %i\n", x, buf[x], sum, ssum);
08480    }
08481 
08482    if (option_verbose > 5)
08483          ast_log(LOG_WARNING, "mean %i, energy %i\n", mean, sum/len);
08484 
08485    return sum / len;
08486 }

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

Definition at line 9924 of file chan_dahdi.c.

References ast_log(), ast_malloc, ast_mutex_init(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, DAHDI_FILE_PSEUDO, dahdi_open(), dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, errno, iflist, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, dahdi_pvt::prev, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_request().

09925 {
09926    struct dahdi_pvt *p;
09927    struct dahdi_bufferinfo bi;
09928    int res;
09929    
09930    if ((p = ast_malloc(sizeof(*p)))) {
09931       memcpy(p, src, sizeof(struct dahdi_pvt));
09932       ast_mutex_init(&p->lock);
09933       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09934       /* Allocate a DAHDI structure */
09935       if (p->subs[SUB_REAL].dfd < 0) {
09936          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09937          destroy_dahdi_pvt(&p);
09938          return NULL;
09939       }
09940       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09941       if (!res) {
09942          bi.txbufpolicy = p->buf_policy;
09943          bi.rxbufpolicy = p->buf_policy;
09944          bi.numbufs = p->buf_no;
09945          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09946          if (res < 0) {
09947             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09948          }
09949       } else
09950          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09951    }
09952    p->destroy = 1;
09953    p->next = iflist;
09954    p->prev = NULL;
09955    iflist = p;
09956    if (iflist->next)
09957       iflist->next->prev = p;
09958    return p;
09959 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 5046 of file chan_dahdi.c.

References ast_log(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::master, option_verbose, SUB_REAL, dahdi_pvt::subs, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event().

05047 {
05048    struct dahdi_confinfo ci;
05049    /* Fine if we already have a master, etc */
05050    if (p->master || (p->confno > -1))
05051       return 0;
05052    memset(&ci, 0, sizeof(ci));
05053    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05054       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05055       return 0;
05056    }
05057    /* If we have no master and don't have a confno, then 
05058       if we're in a conference, it's probably a MeetMe room or
05059       some such, so don't let us 3-way out! */
05060    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05061       if (option_verbose > 2) 
05062          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
05063       return 1;
05064    }
05065    return 0;
05066 }

static char* complete_span_4 ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 12438 of file chan_dahdi.c.

References complete_span_helper().

12439 {
12440    return complete_span_helper(line,word,pos,state,3);
12441 }

static char* complete_span_5 ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 12443 of file chan_dahdi.c.

References complete_span_helper().

12444 {
12445    return complete_span_helper(line,word,pos,state,4);
12446 }

static char* complete_span_helper ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos 
) [static]

Definition at line 12419 of file chan_dahdi.c.

References asprintf, ast_log(), errno, LOG_WARNING, NUM_SPANS, and pris.

Referenced by complete_span_4(), and complete_span_5().

12420 {
12421    int which, span;
12422    char *ret = NULL;
12423 
12424    if (pos != rpos)
12425       return ret;
12426 
12427    for (which = span = 0; span < NUM_SPANS; span++) {
12428       if (pris[span].pri && ++which > state) {
12429          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
12430             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12431          }
12432          break;
12433       }
12434    }
12435    return ret;
12436 }

static int conf_add ( struct dahdi_pvt p,
struct dahdi_subchannel c,
int  index,
int  slavechannel 
) [static]

Definition at line 2262 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_DEBUG, and LOG_WARNING.

Referenced by update_conf().

02263 {
02264    /* If the conference already exists, and we're already in it
02265       don't bother doing anything */
02266    struct dahdi_confinfo zi;
02267    
02268    memset(&zi, 0, sizeof(zi));
02269    zi.chan = 0;
02270 
02271    if (slavechannel > 0) {
02272       /* If we have only one slave, do a digital mon */
02273       zi.confmode = DAHDI_CONF_DIGITALMON;
02274       zi.confno = slavechannel;
02275    } else {
02276       if (!index) {
02277          /* Real-side and pseudo-side both participate in conference */
02278          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02279             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02280       } else
02281          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02282       zi.confno = p->confno;
02283    }
02284    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02285       return 0;
02286    if (c->dfd < 0)
02287       return 0;
02288    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02289       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02290       return -1;
02291    }
02292    if (slavechannel < 1) {
02293       p->confno = zi.confno;
02294    }
02295    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02296    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02297    return 0;
02298 }

static int conf_del ( struct dahdi_pvt p,
struct dahdi_subchannel c,
int  index 
) [static]

Definition at line 2311 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), LOG_DEBUG, and LOG_WARNING.

Referenced by dahdi_unlink(), and update_conf().

02312 {
02313    struct dahdi_confinfo zi;
02314    if (/* Can't delete if there's no dfd */
02315       (c->dfd < 0) ||
02316       /* Don't delete from the conference if it's not our conference */
02317       !isourconf(p, c)
02318       /* Don't delete if we don't think it's conferenced at all (implied) */
02319       ) return 0;
02320    memset(&zi, 0, sizeof(zi));
02321    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02322       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02323       return -1;
02324    }
02325    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02326    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02327    return 0;
02328 }

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

Definition at line 3556 of file chan_dahdi.c.

References AST_APP_ARG, ast_check_hangup(), AST_CONTROL_HANGUP, AST_DECLARE_APP_ARGS, AST_FRAME_CONTROL, ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_true(), ast_waitfor(), ast_frame::frametype, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2call, parse(), dahdi_pvt::r2chan, ast_frame::subclass, ast_channel::tech, and ast_channel::tech_pvt.

Referenced by load_module(), and zap_accept_r2_call_exec().

03557 {
03558    /* data is whether to accept with charge or no charge */
03559    openr2_call_mode_t accept_mode;
03560    int res, timeout, maxloops;
03561    struct ast_frame *f;
03562    struct dahdi_pvt *p;
03563    char *parse;
03564    AST_DECLARE_APP_ARGS(args,
03565          AST_APP_ARG(charge);
03566    );
03567 
03568    if (ast_strlen_zero(data)) {
03569       ast_log(LOG_DEBUG, "No data sent to application!\n");
03570       return -1;
03571    }
03572 
03573    if (chan->tech != &dahdi_tech) {
03574       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03575       return -1;
03576    }
03577 
03578    p = (struct dahdi_pvt *)chan->tech_pvt;
03579    if (!p) {
03580       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03581       return -1;
03582    }
03583 
03584    parse = ast_strdupa(data);
03585    AST_STANDARD_APP_ARGS(args, parse);
03586 
03587    if (ast_strlen_zero(args.charge)) {
03588       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03589       return -1;
03590    }
03591 
03592    ast_mutex_lock(&p->lock);
03593    if (!p->mfcr2 || !p->mfcr2call) {
03594       ast_mutex_unlock(&p->lock);
03595       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03596       return -1;
03597    }
03598 
03599    if (p->mfcr2_call_accepted) {
03600       ast_mutex_unlock(&p->lock);
03601       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03602       return 0;
03603    }
03604    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03605    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03606       ast_mutex_unlock(&p->lock);
03607       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03608       return -1;
03609    }
03610    ast_mutex_unlock(&p->lock);
03611 
03612    res = 0;
03613    timeout = 100;
03614    maxloops = 50; /* wait up to 5 seconds */
03615    /* we need to read() until the call is accepted */
03616    while (maxloops > 0) {
03617       maxloops--;
03618       if (ast_check_hangup(chan)) {
03619          break;
03620       }
03621       res = ast_waitfor(chan, timeout);
03622       if (res < 0) {
03623          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03624          res = -1;
03625          break;
03626       }
03627       if (res == 0) {
03628          continue;
03629       }
03630       f = ast_read(chan);
03631       if (!f) {
03632          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03633          res = -1;
03634          break;
03635       }
03636       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03637          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03638          ast_frfree(f);
03639          res = -1;
03640          break;
03641       }
03642       ast_frfree(f);
03643       ast_mutex_lock(&p->lock);
03644       if (p->mfcr2_call_accepted) {
03645          ast_mutex_unlock(&p->lock);
03646          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03647          break;
03648       }
03649       ast_mutex_unlock(&p->lock);
03650    }
03651    if (res == -1) {
03652       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03653    }
03654    return res;
03655 }

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

Definition at line 13834 of file chan_dahdi.c.

References __action_dialoffhook().

13835 {
13836    return __action_dialoffhook(s, m, 0);
13837 }

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

Definition at line 13734 of file chan_dahdi.c.

References __action_dnd().

13735 {
13736    return __action_dnd(s, m, 0, 0);
13737 }

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

Definition at line 13724 of file chan_dahdi.c.

References __action_dnd().

13725 {
13726    return __action_dnd(s, m, 0, 1);
13727 }

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

Definition at line 13913 of file chan_dahdi.c.

References __action_restart().

13914 {
13915    return __action_restart(s, m, 0);
13916 }

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

Definition at line 13889 of file chan_dahdi.c.

References __action_showchannels().

13890 {
13891    return __action_showchannels(s, m, 0);
13892 }

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

Definition at line 13763 of file chan_dahdi.c.

References __action_transfer().

13764 {
13765    return __action_transfer(s, m, 0);
13766 }

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

Definition at line 13791 of file chan_dahdi.c.

References __action_transferhangup().

13792 {
13793    return __action_transferhangup(s, m, 0);
13794 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 4101 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::channel, DAHDI_CALL_LEVEL_CONNECT, dahdi_enable_ec(), dahdi_get_index, dahdi_r2_answer(), dahdi_set_hook(), dahdi_train_ec(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::hanguponpolarityswitch, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.

04102 {
04103    struct dahdi_pvt *p = ast->tech_pvt;
04104    int res = 0;
04105    int index;
04106    int oldstate = ast->_state;
04107    ast_setstate(ast, AST_STATE_UP);
04108    ast_mutex_lock(&p->lock);
04109    index = dahdi_get_index(ast, p, 0);
04110    if (index < 0)
04111       index = SUB_REAL;
04112    /* nothing to do if a radio channel */
04113    if ((p->radio || (p->oprmode < 0))) {
04114       ast_mutex_unlock(&p->lock);
04115       return 0;
04116    }
04117    switch (p->sig) {
04118    case SIG_FXSLS:
04119    case SIG_FXSGS:
04120    case SIG_FXSKS:
04121       p->ringt = 0;
04122       /* Fall through */
04123    case SIG_EM:
04124    case SIG_EM_E1:
04125    case SIG_EMWINK:
04126    case SIG_FEATD:
04127    case SIG_FEATDMF:
04128    case SIG_FEATDMF_TA:
04129    case SIG_E911:
04130    case SIG_FGC_CAMA:
04131    case SIG_FGC_CAMAMF:
04132    case SIG_FEATB:
04133    case SIG_SF:
04134    case SIG_SFWINK:
04135    case SIG_SF_FEATD:
04136    case SIG_SF_FEATDMF:
04137    case SIG_SF_FEATB:
04138    case SIG_FXOLS:
04139    case SIG_FXOGS:
04140    case SIG_FXOKS:
04141       /* Pick up the line */
04142       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
04143       if (p->hanguponpolarityswitch) {
04144          gettimeofday(&p->polaritydelaytv, NULL);
04145       }
04146       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04147       tone_zone_play_tone(p->subs[index].dfd, -1);
04148       p->dialing = 0;
04149       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04150          if (oldstate == AST_STATE_RINGING) {
04151             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
04152             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04153             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04154             p->owner = p->subs[SUB_REAL].owner;
04155          }
04156       }
04157       if (p->sig & __DAHDI_SIG_FXS) {
04158          dahdi_enable_ec(p);
04159          dahdi_train_ec(p);
04160       }
04161       break;
04162 #ifdef HAVE_PRI
04163    case SIG_PRI:
04164       /* Send a pri acknowledge */
04165       if (!pri_grab(p, p->pri)) {
04166          if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04167             p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04168          }
04169          p->dialing = 0;
04170          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04171          pri_rel(p->pri);
04172       } else {
04173          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04174          res = -1;
04175       }
04176       break;
04177 #endif
04178 
04179 #ifdef HAVE_OPENR2
04180    case SIG_MFCR2:
04181       if (!p->mfcr2_accept_on_offer) {
04182          /* the call was not accepted on offer, so it must be accepted now before answering,
04183             the answer will be executed when the callback on_call_accepted is executed */
04184          if (p->mfcr2_charge_calls) {
04185             ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04186             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04187          } else {
04188             ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04189             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04190          }
04191       } else {
04192          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04193          res = dahdi_r2_answer(p);
04194       }
04195       break;
04196 #endif
04197 
04198    case 0:
04199       ast_mutex_unlock(&p->lock);
04200       return 0;
04201    default:
04202       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04203       res = -1;
04204    }
04205    ast_mutex_unlock(&p->lock);
04206    return res;
04207 }

static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause ( int  cause  )  [static]

Definition at line 3662 of file chan_dahdi.c.

References AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INTERWORKING, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_log(), and LOG_DEBUG.

Referenced by dahdi_hangup().

03663 {
03664    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03665    switch (cause) {
03666    case AST_CAUSE_USER_BUSY:
03667    case AST_CAUSE_CALL_REJECTED:
03668    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
03669       r2cause = OR2_CAUSE_BUSY_NUMBER;
03670       break;
03671 
03672    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03673    case AST_CAUSE_SWITCH_CONGESTION:
03674       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03675       break;
03676 
03677    case AST_CAUSE_UNALLOCATED:
03678       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03679       break;
03680 
03681    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03682    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03683       r2cause = OR2_CAUSE_OUT_OF_ORDER;
03684       break;
03685 
03686    case AST_CAUSE_NO_ANSWER:
03687    case AST_CAUSE_NO_USER_RESPONSE:
03688       r2cause = OR2_CAUSE_NO_ANSWER;
03689       break;
03690 
03691    default:
03692       r2cause = OR2_CAUSE_NORMAL_CLEARING;
03693       break;
03694    }
03695    ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 
03696          r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03697    return r2cause;
03698 }

static enum ast_bridge_result dahdi_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 4597 of file chan_dahdi.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(), dahdi_pvt::call, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_link(), dahdi_unlink(), DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), ast_channel::fds, ast_frame::frametype, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pri::lock, dahdi_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, master, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::pulsedial, dahdi_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, update_conf(), and VERBOSE_PREFIX_3.

04598 {
04599    struct ast_channel *who;
04600    struct dahdi_pvt *p0, *p1, *op0, *op1;
04601    struct dahdi_pvt *master = NULL, *slave = NULL;
04602    struct ast_frame *f;
04603    int inconf = 0;
04604    int nothingok = 1;
04605    int ofd0, ofd1;
04606    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04607    int os0 = -1, os1 = -1;
04608    int priority = 0;
04609    struct ast_channel *oc0, *oc1;
04610    enum ast_bridge_result res;
04611 
04612 #ifdef PRI_2BCT
04613    int triedtopribridge = 0;
04614 #endif
04615 
04616    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
04617       There is code below to handle it properly until DTMF is actually seen,
04618       but due to currently unresolved issues it's ignored...
04619    */
04620 
04621    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04622       return AST_BRIDGE_FAILED_NOWARN;
04623 
04624    ast_mutex_lock(&c0->lock);
04625    while (ast_mutex_trylock(&c1->lock)) {
04626       DEADLOCK_AVOIDANCE(&c0->lock);
04627    }
04628 
04629    p0 = c0->tech_pvt;
04630    p1 = c1->tech_pvt;
04631    /* cant do pseudo-channels here */
04632    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04633       ast_mutex_unlock(&c0->lock);
04634       ast_mutex_unlock(&c1->lock);
04635       return AST_BRIDGE_FAILED_NOWARN;
04636    }
04637 
04638    oi0 = dahdi_get_index(c0, p0, 0);
04639    oi1 = dahdi_get_index(c1, p1, 0);
04640    if ((oi0 < 0) || (oi1 < 0)) {
04641       ast_mutex_unlock(&c0->lock);
04642       ast_mutex_unlock(&c1->lock);
04643       return AST_BRIDGE_FAILED;
04644    }
04645 
04646    op0 = p0 = c0->tech_pvt;
04647    op1 = p1 = c1->tech_pvt;
04648    ofd0 = c0->fds[0];
04649    ofd1 = c1->fds[0];
04650    oc0 = p0->owner;
04651    oc1 = p1->owner;
04652 
04653    if (ast_mutex_trylock(&p0->lock)) {
04654       /* Don't block, due to potential for deadlock */
04655       ast_mutex_unlock(&c0->lock);
04656       ast_mutex_unlock(&c1->lock);
04657       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04658       return AST_BRIDGE_RETRY;
04659    }
04660    if (ast_mutex_trylock(&p1->lock)) {
04661       /* Don't block, due to potential for deadlock */
04662       ast_mutex_unlock(&p0->lock);
04663       ast_mutex_unlock(&c0->lock);
04664       ast_mutex_unlock(&c1->lock);
04665       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04666       return AST_BRIDGE_RETRY;
04667    }
04668 
04669    if ((p0->callwaiting && p0->callwaitingcallerid)
04670       || (p1->callwaiting && p1->callwaitingcallerid)) {
04671       /*
04672        * Call Waiting Caller ID requires DTMF detection to know if it
04673        * can send the CID spill.
04674        *
04675        * For now, don't attempt to native bridge if either channel
04676        * needs DTMF detection.  There is code below to handle it
04677        * properly until DTMF is actually seen, but due to currently
04678        * unresolved issues it's ignored...
04679        */
04680       ast_mutex_unlock(&p0->lock);
04681       ast_mutex_unlock(&p1->lock);
04682       ast_mutex_unlock(&c0->lock);
04683       ast_mutex_unlock(&c1->lock);
04684       return AST_BRIDGE_FAILED_NOWARN;
04685    }
04686 
04687    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04688       if (p0->owner && p1->owner) {
04689          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
04690          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04691             master = p0;
04692             slave = p1;
04693             inconf = 1;
04694          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04695             master = p1;
04696             slave = p0;
04697             inconf = 1;
04698          } else {
04699             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
04700             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04701                p0->channel,
04702                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04703                p0->subs[SUB_REAL].inthreeway, p0->channel,
04704                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04705                p1->subs[SUB_REAL].inthreeway);
04706          }
04707          nothingok = 0;
04708       }
04709    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04710       if (p1->subs[SUB_THREEWAY].inthreeway) {
04711          master = p1;
04712          slave = p0;
04713          nothingok = 0;
04714       }
04715    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04716       if (p0->subs[SUB_THREEWAY].inthreeway) {
04717          master = p0;
04718          slave = p1;
04719          nothingok = 0;
04720       }
04721    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04722       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
04723          don't put us in anything */
04724       if (p1->subs[SUB_CALLWAIT].inthreeway) {
04725          master = p1;
04726          slave = p0;
04727          nothingok = 0;
04728       }
04729    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04730       /* Same as previous */
04731       if (p0->subs[SUB_CALLWAIT].inthreeway) {
04732          master = p0;
04733          slave = p1;
04734          nothingok = 0;
04735       }
04736    }
04737    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04738       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04739    if (master && slave) {
04740       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
04741          in an active threeway call with a channel that is ringing, we should
04742          indicate ringing. */
04743       if ((oi1 == SUB_THREEWAY) && 
04744           p1->subs[SUB_THREEWAY].inthreeway && 
04745           p1->subs[SUB_REAL].owner && 
04746           p1->subs[SUB_REAL].inthreeway && 
04747           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04748          ast_log(LOG_DEBUG,
04749             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
04750             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
04751          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04752          os1 = p1->subs[SUB_REAL].owner->_state;
04753       } else {
04754          ast_log(LOG_DEBUG, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
04755             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
04756          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04757       }
04758       if ((oi0 == SUB_THREEWAY) && 
04759           p0->subs[SUB_THREEWAY].inthreeway && 
04760           p0->subs[SUB_REAL].owner && 
04761           p0->subs[SUB_REAL].inthreeway && 
04762           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04763          ast_log(LOG_DEBUG,
04764             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
04765             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
04766          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04767          os0 = p0->subs[SUB_REAL].owner->_state;
04768       } else {
04769          ast_log(LOG_DEBUG, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
04770             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
04771          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
04772       }
04773       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04774          if (!p0->echocanbridged || !p1->echocanbridged) {
04775             /* Disable echo cancellation if appropriate */
04776             dahdi_disable_ec(p0);
04777             dahdi_disable_ec(p1);
04778          }
04779       }
04780       dahdi_link(slave, master);
04781       master->inconference = inconf;
04782    } else if (!nothingok)
04783       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04784 
04785    update_conf(p0);
04786    update_conf(p1);
04787    t0 = p0->subs[SUB_REAL].inthreeway;
04788    t1 = p1->subs[SUB_REAL].inthreeway;
04789 
04790    ast_mutex_unlock(&p0->lock);
04791    ast_mutex_unlock(&p1->lock);
04792 
04793    ast_mutex_unlock(&c0->lock);
04794    ast_mutex_unlock(&c1->lock);
04795 
04796    /* Native bridge failed */
04797    if ((!master || !slave) && !nothingok) {
04798       dahdi_enable_ec(p0);
04799       dahdi_enable_ec(p1);
04800       return AST_BRIDGE_FAILED;
04801    }
04802    
04803    if (option_verbose > 2) 
04804       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04805 
04806    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04807       disable_dtmf_detect(op0);
04808 
04809    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04810       disable_dtmf_detect(op1);
04811 
04812    for (;;) {
04813       struct ast_channel *c0_priority[2] = {c0, c1};
04814       struct ast_channel *c1_priority[2] = {c1, c0};
04815 
04816       /* Here's our main loop...  Start by locking things, looking for private parts, 
04817          and then balking if anything is wrong */
04818       ast_mutex_lock(&c0->lock);
04819       while (ast_mutex_trylock(&c1->lock)) {
04820          DEADLOCK_AVOIDANCE(&c0->lock);
04821       }
04822 
04823       p0 = c0->tech_pvt;
04824       p1 = c1->tech_pvt;
04825 
04826       if (op0 == p0)
04827          i0 = dahdi_get_index(c0, p0, 1);
04828       if (op1 == p1)
04829          i1 = dahdi_get_index(c1, p1, 1);
04830       ast_mutex_unlock(&c0->lock);
04831       ast_mutex_unlock(&c1->lock);
04832 
04833       if (!timeoutms || 
04834           (op0 != p0) ||
04835           (op1 != p1) || 
04836           (ofd0 != c0->fds[0]) || 
04837           (ofd1 != c1->fds[0]) ||
04838           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
04839           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
04840           (oc0 != p0->owner) || 
04841           (oc1 != p1->owner) ||
04842           (t0 != p0->subs[SUB_REAL].inthreeway) ||
04843           (t1 != p1->subs[SUB_REAL].inthreeway) ||
04844           (oi0 != i0) ||
04845           (oi1 != i1)) {
04846          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04847             op0->channel, oi0, op1->channel, oi1);
04848          res = AST_BRIDGE_RETRY;
04849          goto return_from_bridge;
04850       }
04851 
04852 #ifdef PRI_2BCT
04853       if (!triedtopribridge) {
04854          triedtopribridge = 1;
04855          if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
04856             ast_mutex_lock(&p0->pri->lock);
04857             if (p0->call && p1->call) {
04858                pri_channel_bridge(p0->call, p1->call);
04859             }
04860             ast_mutex_unlock(&p0->pri->lock);
04861          }
04862       }
04863 #endif
04864 
04865       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04866       if (!who) {
04867          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04868          continue;
04869       }
04870       f = ast_read(who);
04871       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04872          *fo = f;
04873          *rc = who;
04874          res = AST_BRIDGE_COMPLETE;
04875          goto return_from_bridge;
04876       }
04877       if (f->frametype == AST_FRAME_DTMF) {
04878          if ((who == c0) && p0->pulsedial) {
04879             ast_write(c1, f);
04880          } else if ((who == c1) && p1->pulsedial) {
04881             ast_write(c0, f);
04882          } else {
04883             *fo = f;
04884             *rc = who;
04885             res = AST_BRIDGE_COMPLETE;
04886             goto return_from_bridge;
04887          }
04888       }
04889       ast_frfree(f);
04890       
04891       /* Swap who gets priority */
04892       priority = !priority;
04893    }
04894 
04895 return_from_bridge:
04896    if (op0 == p0)
04897       dahdi_enable_ec(p0);
04898 
04899    if (op1 == p1)
04900       dahdi_enable_ec(p1);
04901 
04902    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04903       enable_dtmf_detect(op0);
04904 
04905    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04906       enable_dtmf_detect(op1);
04907 
04908    dahdi_unlink(slave, master, 1);
04909 
04910    return res;
04911 }

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

Definition at line 2816 of file chan_dahdi.c.

References ast_channel::_state, ast_callerid_generate(), ast_copy_string(), 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(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidrings, dahdi_pvt::cidspill, DAHDI_CALL_LEVEL_SETUP, dahdi_callwait(), dahdi_get_index, dahdi_r2_get_channel_category(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, free, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, MAX_CALLERID_SIZE, dahdi_pvt::mfcr2, dahdi_pri::nationalprefix, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pri::nodetype, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, PVT_TO_CHANNEL, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.

02817 {
02818    struct dahdi_pvt *p = ast->tech_pvt;
02819    int x, res, index,mysig;
02820    char *c, *n, *l;
02821 #ifdef HAVE_PRI
02822    char *s = NULL;
02823 #endif
02824    char dest[256]; /* must be same length as p->dialdest */
02825    ast_mutex_lock(&p->lock);
02826    ast_copy_string(dest, rdest, sizeof(dest));
02827    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02828    if ((ast->_state == AST_STATE_BUSY)) {
02829       p->subs[SUB_REAL].needbusy = 1;
02830       ast_mutex_unlock(&p->lock);
02831       return 0;
02832    }
02833    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02834       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02835       ast_mutex_unlock(&p->lock);
02836       return -1;
02837    }
02838    p->dialednone = 0;
02839    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02840    {
02841       /* Special pseudo -- automatically up */
02842       ast_setstate(ast, AST_STATE_UP); 
02843       ast_mutex_unlock(&p->lock);
02844       return 0;
02845    }
02846    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02847    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02848    if (res)
02849       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02850    p->outgoing = 1;
02851 
02852    if (IS_DIGITAL(ast->transfercapability)) {
02853       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02854    } else {
02855       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02856    }
02857 
02858    mysig = p->sig;
02859    if (p->outsigmod > -1)
02860       mysig = p->outsigmod;
02861 
02862    switch (mysig) {
02863    case SIG_FXOLS:
02864    case SIG_FXOGS:
02865    case SIG_FXOKS:
02866       if (p->owner == ast) {
02867          /* Normal ring, on hook */
02868          
02869          /* Don't send audio while on hook, until the call is answered */
02870          p->dialing = 1;
02871          if (p->use_callerid) {
02872             /* Generate the Caller-ID spill if desired */
02873             if (p->cidspill) {
02874                ast_log(LOG_WARNING, "cidspill already exists??\n");
02875                free(p->cidspill);
02876             }
02877             p->callwaitcas = 0;
02878             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02879                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02880                p->cidpos = 0;
02881                send_callerid(p);
02882             }
02883          }
02884          /* Choose proper cadence */
02885          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02886             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02887                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02888             p->cidrings = cidrings[p->distinctivering - 1];
02889          } else {
02890             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02891                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02892             p->cidrings = p->sendcalleridafter;
02893          }
02894 
02895          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02896          c = strchr(dest, '/');
02897          if (c)
02898             c++;
02899          if (c && (strlen(c) < p->stripmsd)) {
02900             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02901             c = NULL;
02902          }
02903          if (c) {
02904             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02905             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02906             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02907          } else {
02908             p->dop.dialstr[0] = '\0';
02909          }
02910          x = DAHDI_RING;
02911          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02912             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02913             ast_mutex_unlock(&p->lock);
02914             return -1;
02915          }
02916          p->dialing = 1;
02917       } else {
02918          /* Call waiting call */
02919          p->callwaitrings = 0;
02920          if (ast->cid.cid_num)
02921             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02922          else
02923             p->callwait_num[0] = '\0';
02924          if (ast->cid.cid_name)
02925             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02926          else
02927             p->callwait_name[0] = '\0';
02928          /* Call waiting tone instead */
02929          if (dahdi_callwait(ast)) {
02930             ast_mutex_unlock(&p->lock);
02931             return -1;
02932          }
02933          /* Make ring-back */
02934          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02935             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02936             
02937       }
02938       n = ast->cid.cid_name;
02939       l = ast->cid.cid_num;
02940       if (l)
02941          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02942       else
02943          p->lastcid_num[0] = '\0';
02944       if (n)
02945          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02946       else
02947          p->lastcid_name[0] = '\0';
02948       ast_setstate(ast, AST_STATE_RINGING);
02949       index = dahdi_get_index(ast, p, 0);
02950       if (index > -1) {
02951          p->subs[index].needringing = 1;
02952       }
02953       break;
02954    case SIG_FXSLS:
02955    case SIG_FXSGS:
02956    case SIG_FXSKS:
02957    case SIG_EMWINK:
02958    case SIG_EM:
02959    case SIG_EM_E1:
02960    case SIG_FEATD:
02961    case SIG_FEATDMF:
02962    case SIG_E911:
02963    case SIG_FGC_CAMA:
02964    case SIG_FGC_CAMAMF:
02965    case SIG_FEATB:
02966    case SIG_SFWINK:
02967    case SIG_SF:
02968    case SIG_SF_FEATD:
02969    case SIG_SF_FEATDMF:
02970    case SIG_FEATDMF_TA:
02971    case SIG_SF_FEATB:
02972       c = strchr(dest, '/');
02973       if (c)
02974          c++;
02975       else
02976          c = "";
02977       if (strlen(c) < p->stripmsd) {
02978          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02979          ast_mutex_unlock(&p->lock);
02980          return -1;
02981       }
02982 #ifdef HAVE_PRI
02983       /* Start the trunk, if not GR-303 */
02984       if (!p->pri) {
02985 #endif
02986          x = DAHDI_START;
02987          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02988          if (res < 0) {
02989             if (errno != EINPROGRESS) {
02990                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02991                ast_mutex_unlock(&p->lock);
02992                return -1;
02993             }
02994          }
02995 #ifdef HAVE_PRI
02996       }
02997 #endif
02998       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02999       p->dop.op = DAHDI_DIAL_OP_REPLACE;
03000 
03001       c += p->stripmsd;
03002 
03003       switch (mysig) {
03004       case SIG_FEATD:
03005          l = ast->cid.cid_num;
03006          if (l) 
03007             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03008          else
03009             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03010          break;
03011       case SIG_FEATDMF:
03012          l = ast->cid.cid_num;
03013          if (l) 
03014             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03015          else
03016             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03017          break;
03018       case SIG_FEATDMF_TA:
03019       {
03020          const char *cic, *ozz;
03021 
03022          /* If you have to go through a Tandem Access point you need to use this */
03023          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03024          if (!ozz)
03025             ozz = defaultozz;
03026          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03027          if (!cic)
03028             cic = defaultcic;
03029          if (!ozz || !cic) {
03030             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03031             ast_mutex_unlock(&p->lock);
03032             return -1;
03033          }
03034          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03035          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03036          p->whichwink = 0;
03037       }
03038          break;
03039       case SIG_E911:
03040          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03041          break;
03042       case SIG_FGC_CAMA:
03043          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03044          break;
03045       case SIG_FGC_CAMAMF:
03046       case SIG_FEATB:
03047          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03048          break;
03049       default:
03050          if (p->pulse)
03051             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03052          else
03053             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03054          break;
03055       }
03056 
03057       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03058          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03059          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03060          p->echorest[sizeof(p->echorest) - 1] = '\0';
03061          p->echobreak = 1;
03062          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03063       } else
03064          p->echobreak = 0;
03065       if (!res) {
03066          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03067             int saveerr = errno;
03068 
03069             x = DAHDI_ONHOOK;
03070             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03071             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03072             ast_mutex_unlock(&p->lock);
03073             return -1;
03074          }
03075       } else
03076          ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
03077       p->dialing = 1;
03078       if (ast_strlen_zero(c))
03079          p->dialednone = 1;
03080       ast_setstate(ast, AST_STATE_DIALING);
03081       break;
03082    case 0:
03083       /* Special pseudo -- automatically up*/
03084       ast_setstate(ast, AST_STATE_UP);
03085       break;      
03086    case SIG_PRI:
03087    case SIG_MFCR2:
03088       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
03089       p->dialdest[0] = '\0';
03090       p->dialing = 1;
03091       break;
03092    default:
03093       ast_log(LOG_DEBUG, "not yet implemented\n");
03094       ast_mutex_unlock(&p->lock);
03095       return -1;
03096    }
03097 
03098 #ifdef HAVE_OPENR2
03099    if (p->mfcr2) {
03100       int strip = p->stripmsd;
03101       int callres = 0;
03102       c = strchr(dest, '/');
03103       if (c) {
03104          c++;
03105       } else {
03106          c = dest;
03107       }
03108       if (!p->hidecallerid) {
03109          l = ast->cid.cid_num;
03110       } else {
03111          l = NULL;
03112       }
03113       if (strlen(c) < strip) {
03114          ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03115          strip = 0;
03116       }
03117       p->dialing = 1;
03118       callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03119       if (-1 == callres) {
03120          ast_mutex_unlock(&p->lock);
03121          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03122          return -1;
03123       }
03124       ast_setstate(ast, AST_STATE_DIALING);
03125    }
03126 #endif /* HAVE_OPENR2 */
03127 
03128 #ifdef HAVE_PRI
03129    if (p->pri) {
03130       struct pri_sr *sr;
03131 #ifdef SUPPORT_USERUSER
03132       const char *useruser;
03133 #endif
03134       int pridialplan;
03135       int dp_strip;
03136       int prilocaldialplan;
03137       int ldp_strip;
03138       int exclusive;
03139       const char *rr_str;
03140       int redirect_reason;
03141 
03142       c = strchr(dest, '/');
03143       if (c) {
03144          c++;
03145       } else {
03146          c = "";
03147       }
03148 
03149       l = NULL;
03150       n = NULL;
03151       if (!p->hidecallerid) {
03152          l = ast->cid.cid_num;
03153          if (!p->hidecalleridname) {
03154             n = ast->cid.cid_name;
03155          }
03156       }
03157 
03158 
03159       if (strlen(c) < p->stripmsd) {
03160          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03161          ast_mutex_unlock(&p->lock);
03162          return -1;
03163       }
03164       if (mysig != SIG_FXSKS) {
03165          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03166          s = strchr(c + p->stripmsd, 'w');
03167          if (s) {
03168             if (strlen(s) > 1)
03169                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03170             else
03171                p->dop.dialstr[0] = '\0';
03172             *s = '\0';
03173          } else {
03174             p->dop.dialstr[0] = '\0';
03175          }
03176       }
03177       if (pri_grab(p, p->pri)) {
03178          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03179          ast_mutex_unlock(&p->lock);
03180          return -1;
03181       }
03182       if (!(p->call = pri_new_call(p->pri->pri))) {
03183          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03184          pri_rel(p->pri);
03185          ast_mutex_unlock(&p->lock);
03186          return -1;
03187       }
03188       if (!(sr = pri_sr_new())) {
03189          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03190          pri_destroycall(p->pri->pri, p->call);
03191          p->call = NULL;
03192          pri_rel(p->pri);
03193          ast_mutex_unlock(&p->lock);
03194          return -1;
03195       }
03196       if (p->bearer || (mysig == SIG_FXSKS)) {
03197          if (p->bearer) {
03198             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);
03199             p->bearer->call = p->call;
03200          } else
03201             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03202          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03203       }
03204       p->digital = IS_DIGITAL(ast->transfercapability);
03205 
03206       /* Should the picked channel be used exclusively? */
03207       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03208          exclusive = 1;
03209       } else {
03210          exclusive = 0;
03211       }
03212       
03213       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03214       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
03215                (p->digital ? -1 : 
03216                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03217       if (p->pri->facilityenable)
03218          pri_facility_enable(p->pri->pri);
03219 
03220       if (option_verbose > 2)
03221          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03222       dp_strip = 0;
03223       pridialplan = p->pri->dialplan - 1;
03224       if (pridialplan == -2) { /* compute dynamically */
03225          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03226             dp_strip = strlen(p->pri->internationalprefix);
03227             pridialplan = PRI_INTERNATIONAL_ISDN;
03228          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03229             dp_strip = strlen(p->pri->nationalprefix);
03230             pridialplan = PRI_NATIONAL_ISDN;
03231          } else {
03232             pridialplan = PRI_LOCAL_ISDN;
03233          }
03234       }
03235       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03236 
03237       ldp_strip = 0;
03238       prilocaldialplan = p->pri->localdialplan - 1;
03239       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
03240          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03241             ldp_strip = strlen(p->pri->internationalprefix);
03242             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03243          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03244             ldp_strip = strlen(p->pri->nationalprefix);
03245             prilocaldialplan = PRI_NATIONAL_ISDN;
03246          } else {
03247             prilocaldialplan = PRI_LOCAL_ISDN;
03248          }
03249       }
03250       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03251          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03252       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03253          if (!strcasecmp(rr_str, "UNKNOWN"))
03254             redirect_reason = 0;
03255          else if (!strcasecmp(rr_str, "BUSY"))
03256             redirect_reason = 1;
03257          else if (!strcasecmp(rr_str, "NO_REPLY"))
03258             redirect_reason = 2;
03259          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03260             redirect_reason = 15;
03261          else
03262             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03263       } else
03264          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03265       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03266 
03267 #ifdef SUPPORT_USERUSER
03268       /* User-user info */
03269       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03270 
03271       if (useruser)
03272          pri_sr_set_useruser(sr, useruser);
03273 #endif
03274 
03275       if (pri_setup(p->pri->pri, p->call, sr)) {
03276          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
03277             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03278          pri_destroycall(p->pri->pri, p->call);
03279          p->call = NULL;
03280          pri_rel(p->pri);
03281          ast_mutex_unlock(&p->lock);
03282          pri_sr_free(sr);
03283          return -1;
03284       }
03285       p->call_level = DAHDI_CALL_LEVEL_SETUP;
03286       pri_sr_free(sr);
03287       ast_setstate(ast, AST_STATE_DIALING);
03288       pri_rel(p->pri);
03289    }
03290 #endif      
03291    ast_mutex_unlock(&p->lock);
03292    return 0;
03293 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 2783 of file chan_dahdi.c.

References ast_gen_cas(), AST_LAW, ast_log(), ast_malloc, dahdi_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, dahdi_pvt::callwaitingcallerid, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, free, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.

Referenced by dahdi_call(), and dahdi_read().

02784 {
02785    struct dahdi_pvt *p = ast->tech_pvt;
02786    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02787    if (p->cidspill) {
02788       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02789       free(p->cidspill);
02790    }
02791 
02792    /*
02793     * SAS: Subscriber Alert Signal, 440Hz for 300ms
02794     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
02795     */
02796    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02797       return -1;
02798    save_conference(p);
02799    /* Silence */
02800    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02801    if (!p->callwaitrings && p->callwaitingcallerid) {
02802       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02803       p->callwaitcas = 1;
02804       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02805    } else {
02806       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02807       p->callwaitcas = 0;
02808       p->cidlen = 2400 + READ_SIZE * 4;
02809    }
02810    p->cidpos = 0;
02811    send_callerid(p);
02812    
02813    return 0;
02814 }

static struct dahdi_chan_conf dahdi_chan_conf_default ( void   )  [static, read]

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

Definition at line 1048 of file chan_dahdi.c.

References CID_SIG_BELL, CID_START_RING, DEFAULT_CIDRINGS, dahdi_pri::nsf, and dahdi_chan_conf::pri.

Referenced by process_dahdi(), and setup_dahdi().

01048                                                             {
01049    /* recall that if a field is not included here it is initialized
01050     * to 0 or equivalent
01051     */
01052    struct dahdi_chan_conf conf = {
01053 #ifdef HAVE_PRI
01054       .pri = {
01055          .nsf = PRI_NSF_NONE,
01056          .switchtype = PRI_SWITCH_NI2,
01057          .dialplan = PRI_NATIONAL_ISDN + 1,
01058          .localdialplan = PRI_NATIONAL_ISDN + 1,
01059          .nodetype = PRI_CPE,
01060 
01061          .minunused = 2,
01062          .idleext = "",
01063          .idledial = "",
01064          .internationalprefix = "",
01065          .nationalprefix = "",
01066          .localprefix = "",
01067          .privateprefix = "",
01068          .unknownprefix = "",
01069 
01070          .resetinterval = 3600
01071       },
01072 #endif
01073       .chan = {
01074          .context = "default",
01075          .cid_num = "",
01076          .cid_name = "",
01077          .mohinterpret = "default",
01078          .mohsuggest = "",
01079          .transfertobusy = 1,
01080 
01081          .cid_signalling = CID_SIG_BELL,
01082          .cid_start = CID_START_RING,
01083          .dahditrcallerid = 0,
01084          .use_callerid = 1,
01085          .sig = -1,
01086          .outsigmod = -1,
01087 
01088          .tonezone = -1,
01089 
01090          .echocancel = 1,
01091 
01092          .busycount = 3,
01093          .busycompare = 0,
01094          .busytonelength = 0,
01095          .busyquietlength = 0,
01096          .busyfuzziness = 0,
01097          .silencethreshold = 0,
01098 
01099          .accountcode = "",
01100 
01101          .mailbox = "",
01102 
01103 
01104          .polarityonanswerdelay = 600,
01105 
01106          .sendcalleridafter = DEFAULT_CIDRINGS,
01107 
01108          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01109          .buf_no = numbufs,
01110       },
01111       .timing = {
01112          .prewinktime = -1,
01113          .preflashtime = -1,
01114          .winktime = -1,
01115          .flashtime = -1,
01116          .starttime = -1,
01117          .rxwinktime = -1,
01118          .rxflashtime = -1,
01119          .debouncetime = -1
01120       },
01121       .smdi_port = "/dev/ttyS0",
01122    };
01123 
01124    return conf;
01125 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 1924 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().

01925 {
01926    if (fd > 0)
01927       close(fd);
01928 }

static void dahdi_close_pri_fd ( struct dahdi_pri pri,
int  fd_num 
) [static]

Definition at line 1937 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

Referenced by __unload_module(), dahdi_restart(), and start_pri().

01938 {
01939    dahdi_close(pri->fds[fd_num]);
01940    pri->fds[fd_num] = -1;
01941 }

static void dahdi_close_sub ( struct dahdi_pvt chan_pvt,
int  sub_num 
) [static]

Definition at line 1930 of file chan_dahdi.c.

References dahdi_close(), dahdi_subchannel::dfd, and dahdi_pvt::subs.

Referenced by alloc_sub(), destroy_dahdi_pvt(), pri_fixup_principle(), and unalloc_sub().

01931 {
01932    dahdi_close(chan_pvt->subs[sub_num].dfd);
01933    chan_pvt->subs[sub_num].dfd = -1;
01934 }

static int dahdi_confmute ( struct dahdi_pvt p,
int  muted 
) [inline, static]

Definition at line 2664 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_dtmf(), dahdi_handle_event(), dahdi_hangup(), and dahdi_new().

02665 {
02666    int x, y, res;
02667    x = muted;
02668    if (p->sig == SIG_PRI) {
02669       y = 1;
02670       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02671       if (res)
02672          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02673    }
02674    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02675    if (res < 0)
02676       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02677    return res;
02678 }

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

Definition at line 13083 of file chan_dahdi.c.

References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.

13084 {
13085    int channel;
13086    
13087    if (argc != 4)
13088       return RESULT_SHOWUSAGE;
13089    
13090    channel = atoi(argv[3]);
13091 
13092    return dahdi_destroy_channel_bynum(channel);
13093 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 8489 of file chan_dahdi.c.

References ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, destroy_channel(), dahdi_subchannel::dfd, iflist, iflock, dahdi_pvt::next, dahdi_pvt::prev, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel(), and do_monitor().

08490 {
08491    struct dahdi_pvt *tmp = NULL;
08492    struct dahdi_pvt *prev = NULL;
08493 
08494    ast_mutex_lock(&iflock);
08495    tmp = iflist;
08496    while (tmp) {
08497       if (tmp->channel == channel) {
08498          int x = DAHDI_FLASH;
08499          ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
08500          destroy_channel(prev, tmp, 1);
08501          ast_mutex_unlock(&iflock);
08502          ast_module_unref(ast_module_info->self);
08503          return RESULT_SUCCESS;
08504       }
08505       prev = tmp;
08506       tmp = tmp->next;
08507    }
08508    ast_mutex_unlock(&iflock);
08509    return RESULT_FAILURE;
08510 }

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

Definition at line 2021 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, dahdi_pvt::call_level, DAHDI_CALL_LEVEL_CONNECT, DAHDI_CALL_LEVEL_OVERLAP, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_get_index, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, len(), dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

02022 {
02023    struct dahdi_pvt *pvt;
02024    int index;
02025    int dtmf = -1;
02026    
02027    pvt = chan->tech_pvt;
02028 
02029    ast_mutex_lock(&pvt->lock);
02030 
02031    index = dahdi_get_index(chan, pvt, 0);
02032 
02033    if ((index != SUB_REAL) || !pvt->owner)
02034       goto out;
02035 
02036 #ifdef HAVE_PRI
02037    if (pvt->sig == SIG_PRI
02038       && chan->_state == AST_STATE_DIALING) {
02039       if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
02040          unsigned int len;
02041 
02042          len = strlen(pvt->dialdest);
02043          if (len < sizeof(pvt->dialdest) - 1) {
02044             ast_log(LOG_DEBUG,
02045                "Queueing digit '%c' since setup_ack not yet received\n", digit);
02046             pvt->dialdest[len++] = digit;
02047             pvt->dialdest[len] = '\0';
02048          } else {
02049             ast_log(LOG_WARNING,
02050                "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
02051                pvt->span, digit);
02052          }
02053          goto out;
02054       }
02055       if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
02056          if (!pri_grab(pvt, pvt->pri)) {
02057             pri_information(pvt->pri->pri, pvt->call, digit);
02058             pri_rel(pvt->pri);
02059          } else {
02060             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02061          }
02062          goto out;
02063       }
02064       if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) {
02065          ast_log(LOG_WARNING,
02066             "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n",
02067             pvt->span, digit, pvt->call_level);
02068       }
02069    }
02070 #endif
02071    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02072       goto out;
02073 
02074    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02075       int res;
02076       struct dahdi_dialoperation zo = {
02077          .op = DAHDI_DIAL_OP_APPEND,
02078          .dialstr[0] = 'T',
02079          .dialstr[1] = digit,
02080          .dialstr[2] = 0,
02081       };
02082       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02083          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02084       else
02085          pvt->dialing = 1;
02086    } else {
02087       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
02088       pvt->dialing = 1;
02089       pvt->begindigit = digit;
02090    }
02091 
02092 out:
02093    ast_mutex_unlock(&pvt->lock);
02094 
02095    return 0;
02096 }

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

Definition at line 2098 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

02099 {
02100    struct dahdi_pvt *pvt;
02101    int res = 0;
02102    int index;
02103    int x;
02104    
02105    pvt = chan->tech_pvt;
02106 
02107    ast_mutex_lock(&pvt->lock);
02108    
02109    index = dahdi_get_index(chan, pvt, 0);
02110 
02111    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
02112       goto out;
02113 
02114 #ifdef HAVE_PRI
02115    /* This means that the digit was already sent via PRI signalling */
02116    if (pvt->sig == SIG_PRI && !pvt->begindigit)
02117       goto out;
02118 #endif
02119 
02120    if (pvt->begindigit) {
02121       x = -1;
02122       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
02123       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02124       pvt->dialing = 0;
02125       pvt->begindigit = 0;
02126    }
02127 
02128 out:
02129    ast_mutex_unlock(&pvt->lock);
02130 
02131    return res;
02132 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2495 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), and handle_init_event().

02496 {
02497    int x;
02498    int res;
02499    if (p->echocancel) {
02500       x = 0;
02501       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02502       if (res)
02503          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02504       else if (option_debug)
02505          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
02506    }
02507    p->echocanon = 0;
02508 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2445 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_setoption(), handle_init_event(), pri_dchannel(), and ss_thread().

02446 {
02447    int x;
02448    int res;
02449    if (!p)
02450       return;
02451    if (p->echocanon) {
02452       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
02453       return;
02454    }
02455    if (p->digital) {
02456       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
02457       return;
02458    }
02459    if (p->echocancel) {
02460       if (p->sig == SIG_PRI) {
02461          x = 1;
02462          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02463          if (res)
02464             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02465       }
02466       x = p->echocancel;
02467       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02468       if (res) 
02469          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02470       else {
02471          p->echocanon = 1;
02472          if (option_debug)
02473             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
02474       }
02475    } else if (option_debug)
02476       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
02477 }

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

Definition at line 6264 of file chan_dahdi.c.

References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, and ast_channel::tech_pvt.

06265 {
06266    struct dahdi_pvt *p = ast->tech_pvt;
06267    struct ast_frame *f;
06268    ast_mutex_lock(&p->lock);
06269    f = __dahdi_exception(ast);
06270    ast_mutex_unlock(&p->lock);
06271    return f;
06272 }

static int dahdi_fake_event ( struct dahdi_pvt p,
int  mode 
) [static]

Definition at line 13669 of file chan_dahdi.c.

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

Referenced by __action_transfer(), and __action_transferhangup().

13670 {
13671    if (p) {
13672       switch (mode) {
13673          case TRANSFER:
13674             p->fake_event = DAHDI_EVENT_WINKFLASH;
13675             break;
13676          case HANGUP:
13677             p->fake_event = DAHDI_EVENT_ONHOOK;
13678             break;
13679          default:
13680             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
13681       }
13682    }
13683    return 0;
13684 }

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

Definition at line 4913 of file chan_dahdi.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, dahdi_pvt::channel, dahdi_indicate(), dahdi_unlink(), dahdi_pvt::lock, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

04914 {
04915    struct dahdi_pvt *p = newchan->tech_pvt;
04916    int x;
04917    ast_mutex_lock(&p->lock);
04918    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04919    if (p->owner == oldchan) {
04920       p->owner = newchan;
04921    }
04922    for (x = 0; x < 3; x++)
04923       if (p->subs[x].owner == oldchan) {
04924          if (!x)
04925             dahdi_unlink(NULL, p, 0);
04926          p->subs[x].owner = newchan;
04927       }
04928    update_conf(p);
04929    ast_mutex_unlock(&p->lock);
04930    if (newchan->_state == AST_STATE_RINGING) 
04931       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04932    return 0;
04933 }

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

Definition at line 4395 of file chan_dahdi.c.

References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::rxgain, ast_channel::tech_pvt, and dahdi_pvt::txgain.

04396 {
04397    struct dahdi_pvt *p = chan->tech_pvt;
04398    int res = 0;
04399    
04400    if (!strcasecmp(data, "rxgain")) {
04401       ast_mutex_lock(&p->lock);
04402       snprintf(buf, len, "%f", p->rxgain);
04403       ast_mutex_unlock(&p->lock);   
04404    } else if (!strcasecmp(data, "txgain")) {
04405       ast_mutex_lock(&p->lock);
04406       snprintf(buf, len, "%f", p->txgain);
04407       ast_mutex_unlock(&p->lock);   
04408    } else {
04409       ast_copy_string(buf, "", len);
04410       res = -1;
04411    }
04412 
04413    return res;
04414 }

static int dahdi_func_write ( struct ast_channel chan,
char *  function,
char *  data,
const char *  value 
) [static]

Definition at line 4447 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

04448 {
04449    struct dahdi_pvt *p = chan->tech_pvt;
04450    int res = 0;
04451 
04452    if (!strcasecmp(data, "buffers")) {
04453       int num_bufs, policy;
04454 
04455       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
04456          struct dahdi_bufferinfo bi = {
04457             .txbufpolicy = policy,
04458             .rxbufpolicy = policy,
04459             .bufsize = p->bufsize,
04460             .numbufs = num_bufs,
04461          };
04462          int bpres;
04463 
04464          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04465             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
04466          } else {
04467             p->bufferoverrideinuse = 1;
04468          }
04469       } else {
04470          res = -1;
04471       }
04472    } else {
04473       res = -1;
04474    }
04475 
04476    return res;
04477 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 289 of file chan_dahdi.c.

Referenced by __dahdi_exception(), dahdi_handle_event(), do_monitor(), and ss_thread().

00290 {
00291    int j;
00292    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00293       return -1;
00294    return j;
00295 }

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

Definition at line 5102 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), ast_channel::exten, dahdi_subchannel::f, dahdi_pvt::faxhandled, ast_frame::frametype, free, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, option_debug, option_verbose, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event(), and dahdi_read().

05103 {
05104    struct dahdi_pvt *p = ast->tech_pvt;
05105    struct ast_frame *f = *dest;
05106 
05107    if (option_debug)
05108       ast_log(LOG_DEBUG, "%s DTMF digit: 0x%02X '%c' on %s\n",
05109          f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
05110          f->subclass, f->subclass, ast->name);
05111 
05112    if (p->confirmanswer) {
05113       if (f->frametype == AST_FRAME_DTMF_END) {
05114          if (option_debug)
05115             ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
05116          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
05117             of a DTMF digit */
05118          p->subs[index].f.frametype = AST_FRAME_CONTROL;
05119          p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05120          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
05121          p->confirmanswer = 0;
05122       } else {
05123          p->subs[index].f.frametype = AST_FRAME_NULL;
05124          p->subs[index].f.subclass = 0;
05125       }
05126       *dest = &p->subs[index].f;
05127    } else if (p->callwaitcas) {
05128       if (f->frametype == AST_FRAME_DTMF_END) {
05129          if ((f->subclass == 'A') || (f->subclass == 'D')) {
05130             if (option_debug)
05131                ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
05132             free(p->cidspill);
05133             p->cidspill = NULL;
05134             send_cwcidspill(p);
05135          }
05136          if ((f->subclass != 'm') && (f->subclass != 'u')) 
05137             p->callwaitcas = 0;
05138       }
05139       p->subs[index].f.frametype = AST_FRAME_NULL;
05140       p->subs[index].f.subclass = 0;
05141       *dest = &p->subs[index].f;
05142    } else if (f->subclass == 'f') {
05143       if (f->frametype == AST_FRAME_DTMF_END) {
05144          /* Fax tone -- Handle and return NULL */
05145          if ((p->callprogress & 0x6) && !p->faxhandled) {
05146             p->faxhandled = 1;
05147             if (strcmp(ast->exten, "fax")) {
05148                const char *target_context = S_OR(ast->macrocontext, ast->context);
05149 
05150                /* We need to unlock 'ast' here because ast_exists_extension has the
05151                 * potential to start autoservice on the channel. Such action is prone
05152                 * to deadlock.
05153                 */
05154                ast_mutex_unlock(&p->lock);
05155                ast_channel_unlock(ast);
05156                if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05157                   ast_channel_lock(ast);
05158                   ast_mutex_lock(&p->lock);
05159                   if (option_verbose > 2)
05160                      ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
05161                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
05162                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05163                   if (ast_async_goto(ast, target_context, "fax", 1))
05164                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05165                } else {
05166                   ast_channel_lock(ast);
05167                   ast_mutex_lock(&p->lock);
05168                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05169                }
05170             } else if (option_debug)
05171                ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
05172          } else if (option_debug)
05173             ast_log(LOG_DEBUG, "Fax already handled\n");
05174          dahdi_confmute(p, 0);
05175       }
05176       p->subs[index].f.frametype = AST_FRAME_NULL;
05177       p->subs[index].f.subclass = 0;
05178       *dest = &p->subs[index].f;
05179    } else if (f->subclass == 'm') {
05180       if (f->frametype == AST_FRAME_DTMF_END) {
05181          /* Confmute request */
05182          dahdi_confmute(p, 1);
05183       }
05184       p->subs[index].f.frametype = AST_FRAME_NULL;
05185       p->subs[index].f.subclass = 0;
05186       *dest = &p->subs[index].f;    
05187    } else if (f->subclass == 'u') {
05188       if (f->frametype == AST_FRAME_DTMF_END) {
05189          /* Unmute */
05190          dahdi_confmute(p, 0);
05191       }
05192       p->subs[index].f.frametype = AST_FRAME_NULL;
05193       p->subs[index].f.subclass = 0;
05194       *dest = &p->subs[index].f;    
05195    } else {
05196       if (f->frametype == AST_FRAME_DTMF_END) {
05197          dahdi_confmute(p, 0);
05198       }
05199    }
05200 }

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

Definition at line 5222 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_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_copy_string(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_hangup(), ast_log(), ast_mutex_unlock(), ast_null_frame, 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_tvdiff_ms(), ast_tvnow(), ast_verbose(), attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, dahdi_pvt::channel, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), DAHDI_EVENT_DTMFDOWN, DAHDI_EVENT_DTMFUP, dahdi_get_event(), dahdi_get_index, dahdi_handle_dtmf(), dahdi_lock_sub_owner(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, ast_channel::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, dahdi_subchannel::needanswer, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::resetting, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_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_MFCR2, 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, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), dahdi_pvt::unknown_alarm, update_conf(), VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

05223 {
05224    int res, x;
05225    int index, mysig;
05226    char *c;
05227    struct dahdi_pvt *p = ast->tech_pvt;
05228    pthread_t threadid;
05229    pthread_attr_t attr;
05230    struct ast_channel *chan;
05231    struct ast_frame *f;
05232 
05233    index = dahdi_get_index(ast, p, 0);
05234    if (index < 0) {
05235       return &ast_null_frame;
05236    }
05237    if (index != SUB_REAL) {
05238       ast_log(LOG_ERROR, "We got an event on a non real sub.  Fix it!\n");
05239    }
05240 
05241    mysig = p->sig;
05242    if (p->outsigmod > -1)
05243       mysig = p->outsigmod;
05244 
05245    p->subs[index].f.frametype = AST_FRAME_NULL;
05246    p->subs[index].f.subclass = 0;
05247    p->subs[index].f.datalen = 0;
05248    p->subs[index].f.samples = 0;
05249    p->subs[index].f.mallocd = 0;
05250    p->subs[index].f.offset = 0;
05251    p->subs[index].f.src = "dahdi_handle_event";
05252    p->subs[index].f.data = NULL;
05253    f = &p->subs[index].f;
05254 
05255    if (p->fake_event) {
05256       res = p->fake_event;
05257       p->fake_event = 0;
05258    } else
05259       res = dahdi_get_event(p->subs[index].dfd);
05260 
05261    if (option_debug)
05262       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
05263 
05264    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05265       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05266 
05267       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05268 #ifdef HAVE_PRI
05269       if (p->sig == SIG_PRI
05270          && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
05271          && p->pri
05272          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05273          /* absorb event */
05274       } else
05275 #endif
05276       {
05277          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
05278          p->subs[index].f.subclass = res & 0xff;
05279          dahdi_handle_dtmf(ast, index, &f);
05280       }
05281       return f;
05282    }
05283 
05284    if (res & DAHDI_EVENT_DTMFDOWN) {
05285       if (option_debug)
05286          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
05287 #ifdef HAVE_PRI
05288       if (p->sig == SIG_PRI
05289          && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
05290          && p->pri
05291          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05292          /* absorb event */
05293       } else
05294 #endif
05295       {
05296          /* Mute conference */
05297          dahdi_confmute(p, 1);
05298          p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
05299          p->subs[index].f.subclass = res & 0xff;
05300          dahdi_handle_dtmf(ast, index, &f);
05301       }
05302       return &p->subs[index].f;
05303    }
05304 
05305    switch (res) {
05306 #ifdef DAHDI_EVENT_EC_DISABLED
05307       case DAHDI_EVENT_EC_DISABLED:
05308          if (option_verbose > 2) 
05309             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05310          p->echocanon = 0;
05311          break;
05312 #endif
05313       case DAHDI_EVENT_BITSCHANGED:
05314 #ifdef HAVE_OPENR2
05315          if (p->sig != SIG_MFCR2) {
05316             ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05317          } else {
05318             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05319             openr2_chan_handle_cas(p->r2chan);
05320          }
05321 #else
05322          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05323 #endif
05324       case DAHDI_EVENT_PULSE_START:
05325          /* Stop tone if there's a pulse start and the PBX isn't started */
05326          if (!ast->pbx)
05327             tone_zone_play_tone(p->subs[index].dfd, -1);
05328          break;   
05329       case DAHDI_EVENT_DIALCOMPLETE:
05330 #ifdef HAVE_OPENR2
05331          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05332             /* we don't need to do anything for this event for R2 signaling 
05333                if the call is being setup */
05334             break;
05335          }
05336 #endif
05337          if (p->inalarm) break;
05338          if ((p->radio || (p->oprmode < 0))) break;
05339          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05340             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05341             return NULL;
05342          }
05343          if (!x) { /* if not still dialing in driver */
05344             dahdi_enable_ec(p);
05345             if (p->echobreak) {
05346                dahdi_train_ec(p);
05347                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05348                p->dop.op = DAHDI_DIAL_OP_REPLACE;
05349                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05350                p->echobreak = 0;
05351             } else {
05352                p->dialing = 0;
05353                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05354                   /* if thru with dialing after offhook */
05355                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05356                      ast_setstate(ast, AST_STATE_UP);
05357                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
05358                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05359                      break;
05360                   } else { /* if to state wait for offhook to dial rest */
05361                      /* we now wait for off hook */
05362                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05363                   }
05364                }
05365                if (ast->_state == AST_STATE_DIALING) {
05366                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05367                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05368                   } 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)))) {
05369                      ast_setstate(ast, AST_STATE_RINGING);
05370                   } else if (!p->answeronpolarityswitch) {
05371                      ast_setstate(ast, AST_STATE_UP);
05372                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
05373                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05374                      /* If aops=0 and hops=1, this is necessary */
05375                      p->polarity = POLARITY_REV;
05376                   } else {
05377                      /* Start clean, so we can catch the change to REV polarity when party answers */
05378                      p->polarity = POLARITY_IDLE;
05379                   }
05380                }
05381             }
05382          }
05383          break;
05384       case DAHDI_EVENT_ALARM:
05385 #ifdef HAVE_PRI
05386          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05387             /* T309 is not enabled : destroy calls when alarm occurs */
05388             if (p->call) {
05389                if (p->pri && p->pri->pri) {
05390                   pri_grab(p, p->pri);
05391                   pri_destroycall(p->pri->pri, p->call);
05392                   p->call = NULL;
05393                   pri_rel(p->pri);
05394                } else
05395                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05396             }
05397             if (p->owner)
05398                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05399          }
05400          if (p->bearer) {
05401             p->bearer->inalarm = 1;
05402             p->bearer->resetting = 0;
05403          } else
05404 #endif
05405          {
05406             p->inalarm = 1;
05407 #if defined(HAVE_PRI)
05408             p->resetting = 0;
05409 #endif   /* defined(HAVE_PRI) */
05410          }
05411          res = get_alarms(p);
05412          handle_alarms(p, res);
05413 #ifdef HAVE_PRI
05414          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05415             /* fall through intentionally */
05416          } else {
05417             break;
05418          }
05419 #endif
05420 
05421 #ifdef HAVE_OPENR2
05422          if (p->sig == SIG_MFCR2)
05423             break;
05424 #endif
05425 
05426       case DAHDI_EVENT_ONHOOK:
05427          if (p->radio) {
05428             p->subs[index].f.frametype = AST_FRAME_CONTROL;
05429             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05430             break;
05431          }
05432          if (p->oprmode < 0)
05433          {
05434             if (p->oprmode != -1) break;
05435             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05436             {
05437                /* Make sure it starts ringing */
05438                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05439                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05440                save_conference(p->oprpeer);
05441                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05442             }
05443             break;
05444          }
05445          switch (p->sig) {
05446          case SIG_FXOLS:
05447          case SIG_FXOGS:
05448          case SIG_FXOKS:
05449             p->onhooktime = time(NULL);
05450             p->msgstate = -1;
05451             /* Check for some special conditions regarding call waiting */
05452             if (index == SUB_REAL) {
05453                /* The normal line was hung up */
05454                if (p->subs[SUB_CALLWAIT].owner) {
05455                   /* Need to hold the lock for real-call, private, and call-waiting call */
05456                   dahdi_lock_sub_owner(p, SUB_CALLWAIT);
05457                   if (!p->subs[SUB_CALLWAIT].owner) {
05458                      /*
05459                       * The call waiting call dissappeared.
05460                       * This is now a normal hangup.
05461                       */
05462                      dahdi_disable_ec(p);
05463                      return NULL;
05464                   }
05465 
05466                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
05467                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05468                   if (option_verbose > 2) 
05469                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05470                   unalloc_sub(p, SUB_CALLWAIT); 
05471 #if 0
05472                   p->subs[index].needanswer = 0;
05473                   p->subs[index].needringing = 0;
05474 #endif                  
05475                   p->callwaitingrepeat = 0;
05476                   p->cidcwexpire = 0;
05477                   p->cid_suppress_expire = 0;
05478                   p->owner = NULL;
05479                   /* Don't start streaming audio yet if the incoming call isn't up yet */
05480                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05481                      p->dialing = 1;
05482                   /* Unlock the call-waiting call that we swapped to real-call. */
05483                   ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05484                   dahdi_ring_phone(p);
05485                } else if (p->subs[SUB_THREEWAY].owner) {
05486                   unsigned int mssinceflash;
05487 
05488                   /* Need to hold the lock for real-call, private, and 3-way call */
05489                   dahdi_lock_sub_owner(p, SUB_THREEWAY);
05490                   if (!p->subs[SUB_THREEWAY].owner) {
05491                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05492                      /* Just hangup */
05493                      return NULL;
05494                   }
05495                   if (p->owner != ast) {
05496                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05497                      ast_log(LOG_WARNING, "This isn't good...\n");
05498                      /* Just hangup */
05499                      return NULL;
05500                   }
05501 
05502                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05503                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05504                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
05505                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
05506                         hanging up.  Hangup both channels now */
05507                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05508                      ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05509                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05510                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05511                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05512                      if (p->transfer) {
05513                         /* In any case this isn't a threeway call anymore */
05514                         p->subs[SUB_REAL].inthreeway = 0;
05515                         p->subs[SUB_THREEWAY].inthreeway = 0;
05516                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
05517                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05518                            /* Swap subs and dis-own channel */
05519                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
05520                            /* Unlock the 3-way call that we swapped to real-call. */
05521                            ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05522                            p->owner = NULL;
05523                            /* Ring the phone */
05524                            dahdi_ring_phone(p);
05525                         } else {
05526                            res = attempt_transfer(p);
05527                            if (res < 0) {
05528                               /* Transfer attempt failed. */
05529                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05530                               ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05531                            } else if (res) {
05532                               /* Don't actually hang up at this point */
05533                               break;
05534                            }
05535                         }
05536                      } else {
05537                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05538                         ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05539                      }
05540                   } else {
05541                      /* Swap subs and dis-own channel */
05542                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05543                      /* Unlock the 3-way call that we swapped to real-call. */
05544                      ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05545                      p->owner = NULL;
05546                      /* Ring the phone */
05547                      dahdi_ring_phone(p);
05548                   }
05549                }
05550             } else {
05551                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05552             }
05553             /* Fall through */
05554          default:
05555             dahdi_disable_ec(p);
05556             return NULL;
05557          }
05558          break;
05559       case DAHDI_EVENT_RINGOFFHOOK:
05560          if (p->inalarm) break;
05561          if (p->oprmode < 0)
05562          {
05563             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05564             {
05565                /* Make sure it stops ringing */
05566                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05567                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05568                restore_conference(p->oprpeer);
05569             }
05570             break;
05571          }
05572          if (p->radio)
05573          {
05574             p->subs[index].f.frametype = AST_FRAME_CONTROL;
05575             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05576             break;
05577          }
05578          /* for E911, its supposed to wait for offhook then dial
05579             the second half of the dial string */
05580          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05581             c = strchr(p->dialdest, '/');
05582             if (c)
05583                c++;
05584             else
05585                c = p->dialdest;
05586             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05587             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05588             if (strlen(p->dop.dialstr) > 4) {
05589                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05590                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05591                p->echorest[sizeof(p->echorest) - 1] = '\0';
05592                p->echobreak = 1;
05593                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05594             } else
05595                p->echobreak = 0;
05596             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05597                int saveerr = errno;
05598 
05599                x = DAHDI_ONHOOK;
05600                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05601                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05602                return NULL;
05603                }
05604             p->dialing = 1;
05605             return &p->subs[index].f;
05606          }
05607          switch (p->sig) {
05608          case SIG_FXOLS:
05609          case SIG_FXOGS:
05610          case SIG_FXOKS:
05611             switch (ast->_state) {
05612             case AST_STATE_RINGING:
05613                dahdi_enable_ec(p);
05614                dahdi_train_ec(p);
05615                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05616                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05617                /* Make sure it stops ringing */
05618                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05619                p->subs[SUB_REAL].needringing = 0;
05620                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05621 
05622                /* Cancel any running CallerID spill */
05623                free(p->cidspill);
05624                p->cidspill = NULL;
05625                restore_conference(p);
05626 
05627                p->dialing = 0;
05628                p->callwaitcas = 0;
05629                if (p->confirmanswer) {
05630                   /* Ignore answer if "confirm answer" is enabled */
05631                   p->subs[index].f.frametype = AST_FRAME_NULL;
05632                   p->subs[index].f.subclass = 0;
05633                } else if (!ast_strlen_zero(p->dop.dialstr)) {
05634                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
05635                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05636                   if (res < 0) {
05637                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05638                      p->dop.dialstr[0] = '\0';
05639                      return NULL;
05640                   } else {
05641                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05642                      p->subs[index].f.frametype = AST_FRAME_NULL;
05643                      p->subs[index].f.subclass = 0;
05644                      p->dialing = 1;
05645                   }
05646                   p->dop.dialstr[0] = '\0';
05647                   ast_setstate(ast, AST_STATE_DIALING);
05648                } else
05649                   ast_setstate(ast, AST_STATE_UP);
05650                return &p->subs[index].f;
05651             case AST_STATE_DOWN:
05652                ast_setstate(ast, AST_STATE_RING);
05653                ast->rings = 1;
05654                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05655                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05656                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05657                return &p->subs[index].f;
05658             case AST_STATE_UP:
05659                /* Make sure it stops ringing */
05660                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05661                /* Okay -- probably call waiting*/
05662                if (ast_bridged_channel(p->owner))
05663                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05664                p->subs[index].needunhold = 1;
05665                break;
05666             case AST_STATE_RESERVED:
05667                /* Start up dialtone */
05668                if (has_voicemail(p))
05669                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05670                else
05671                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05672                break;
05673             default:
05674                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05675             }
05676             break;
05677          case SIG_FXSLS:
05678          case SIG_FXSGS:
05679          case SIG_FXSKS:
05680             if (ast->_state == AST_STATE_RING) {
05681                p->ringt = p->ringt_base;
05682             }
05683 
05684             /* Fall through */
05685          case SIG_EM:
05686          case SIG_EM_E1:
05687          case SIG_EMWINK:
05688          case SIG_FEATD:
05689          case SIG_FEATDMF:
05690          case SIG_FEATDMF_TA:
05691          case SIG_E911:
05692          case SIG_FGC_CAMA:
05693          case SIG_FGC_CAMAMF:
05694          case SIG_FEATB:
05695          case SIG_SF:
05696          case SIG_SFWINK:
05697          case SIG_SF_FEATD:
05698          case SIG_SF_FEATDMF:
05699          case SIG_SF_FEATB:
05700             if (ast->_state == AST_STATE_PRERING)
05701                ast_setstate(ast, AST_STATE_RING);
05702             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05703                if (option_debug)
05704                   ast_log(LOG_DEBUG, "Ring detected\n");
05705                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05706                p->subs[index].f.subclass = AST_CONTROL_RING;
05707             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05708                if (option_debug)
05709                   ast_log(LOG_DEBUG, "Line answered\n");
05710                if (p->confirmanswer) {
05711                   p->subs[index].f.frametype = AST_FRAME_NULL;
05712                   p->subs[index].f.subclass = 0;
05713                } else {
05714                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
05715                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05716                   ast_setstate(ast, AST_STATE_UP);
05717                }
05718             } else if (ast->_state != AST_STATE_RING)
05719                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05720             break;
05721          default:
05722             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05723          }
05724          break;
05725 #ifdef DAHDI_EVENT_RINGBEGIN
05726       case DAHDI_EVENT_RINGBEGIN:
05727          switch (p->sig) {
05728          case SIG_FXSLS:
05729          case SIG_FXSGS:
05730          case SIG_FXSKS:
05731             if (ast->_state == AST_STATE_RING) {
05732                p->ringt = p->ringt_base;
05733             }
05734             break;
05735          }
05736          break;
05737 #endif         
05738       case DAHDI_EVENT_RINGEROFF:
05739          if (p->inalarm) break;
05740          if ((p->radio || (p->oprmode < 0))) break;
05741          ast->rings++;
05742          if ((ast->rings > p->cidrings) && (p->cidspill)) {
05743             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
05744             free(p->cidspill);
05745             p->cidspill = NULL;
05746             p->callwaitcas = 0;
05747          }
05748          p->subs[index].f.frametype = AST_FRAME_CONTROL;
05749          p->subs[index].f.subclass = AST_CONTROL_RINGING;
05750          break;
05751       case DAHDI_EVENT_RINGERON:
05752          break;
05753       case DAHDI_EVENT_NOALARM:
05754          p->inalarm = 0;
05755 #ifdef HAVE_PRI
05756          p->resetting = 0;
05757          /* Extremely unlikely but just in case */
05758          if (p->bearer) {
05759             p->bearer->inalarm = 0;
05760             p->bearer->resetting = 0;
05761          }
05762 #endif            
05763          if (!p->unknown_alarm) {
05764             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05765             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05766                "Channel: %d\r\n", p->channel);
05767          } else {
05768             p->unknown_alarm = 0;
05769          }
05770          break;
05771       case DAHDI_EVENT_WINKFLASH:
05772          if (p->inalarm) break;
05773          if (p->radio) break;
05774          if (p->oprmode < 0) break;
05775          if (p->oprmode > 1)
05776          {
05777             struct dahdi_params par;
05778 
05779             memset(&par, 0, sizeof(par));
05780             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05781             {
05782                if (!par.rxisoffhook)
05783                {
05784                   /* Make sure it stops ringing */
05785                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05786                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05787                   save_conference(p);
05788                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05789                }
05790             }
05791             break;
05792          }
05793          /* Remember last time we got a flash-hook */
05794          gettimeofday(&p->flashtime, NULL);
05795          switch (mysig) {
05796          case SIG_FXOLS:
05797          case SIG_FXOGS:
05798          case SIG_FXOKS:
05799             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05800                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05801 
05802             /* Cancel any running CallerID spill */
05803             free(p->cidspill);
05804             p->cidspill = NULL;
05805             restore_conference(p);
05806             p->callwaitcas = 0;
05807 
05808             if (index != SUB_REAL) {
05809                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05810                goto winkflashdone;
05811             }
05812             
05813             if (p->subs[SUB_CALLWAIT].owner) {
05814                /* Need to hold the lock for real-call, private, and call-waiting call */
05815                dahdi_lock_sub_owner(p, SUB_CALLWAIT);
05816                if (!p->subs[SUB_CALLWAIT].owner) {
05817                   /*
05818                    * The call waiting call dissappeared.
05819                    * Let's just ignore this flash-hook.
05820                    */
05821                   ast_log(LOG_NOTICE, "Whoa, the call-waiting call disappeared.\n");
05822                   goto winkflashdone;
05823                }
05824 
05825                /* Swap to call-wait */
05826                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05827                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05828                p->owner = p->subs[SUB_REAL].owner;
05829                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05830                if (p->owner->_state == AST_STATE_RINGING) {
05831                   ast_setstate(p->owner, AST_STATE_UP);
05832                   p->subs[SUB_REAL].needanswer = 1;
05833                }
05834                p->callwaitingrepeat = 0;
05835                p->cidcwexpire = 0;
05836                p->cid_suppress_expire = 0;
05837 
05838                /* Start music on hold if appropriate */
05839                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05840                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05841                      S_OR(p->mohsuggest, NULL),
05842                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05843                }
05844                p->subs[SUB_CALLWAIT].needhold = 1;
05845                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05846                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05847                      S_OR(p->mohsuggest, NULL),
05848                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05849                }
05850                p->subs[SUB_REAL].needunhold = 1;
05851 
05852                /* Unlock the call-waiting call that we swapped to real-call. */
05853                ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
05854             } else if (!p->subs[SUB_THREEWAY].owner) {
05855                if (!p->threewaycalling) {
05856                   /* Just send a flash if no 3-way calling */
05857                   p->subs[SUB_REAL].needflash = 1;
05858                   goto winkflashdone;
05859                } else if (!check_for_conference(p)) {
05860                   char cid_num[256];
05861                   char cid_name[256];
05862 
05863                   cid_num[0] = 0;
05864                   cid_name[0] = 0;
05865                   if (p->dahditrcallerid && p->owner) {
05866                      if (p->owner->cid.cid_num)
05867                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05868                      if (p->owner->cid.cid_name)
05869                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05870                   }
05871                   /* XXX This section needs much more error checking!!! XXX */
05872                   /* Start a 3-way call if feasible */
05873                   if (!((ast->pbx) ||
05874                         (ast->_state == AST_STATE_UP) ||
05875                         (ast->_state == AST_STATE_RING))) {
05876                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05877                         goto winkflashdone;
05878                   }
05879                   if (alloc_sub(p, SUB_THREEWAY)) {
05880                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05881                      goto winkflashdone;
05882                   }
05883                   /* Make new channel */
05884                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05885                   if (!chan) {
05886                      ast_log(LOG_WARNING,
05887                         "Cannot allocate new call structure on channel %d\n",
05888                         p->channel);
05889                      unalloc_sub(p, SUB_THREEWAY);
05890                      goto winkflashdone;
05891                   }
05892                   if (p->dahditrcallerid) {
05893                      if (!p->origcid_num)
05894                         p->origcid_num = ast_strdup(p->cid_num);
05895                      if (!p->origcid_name)
05896                         p->origcid_name = ast_strdup(p->cid_name);
05897                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05898                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05899                   }
05900                   /* Swap things around between the three-way and real call */
05901                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
05902                   /* Disable echo canceller for better dialing */
05903                   dahdi_disable_ec(p);
05904                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05905                   if (res)
05906                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05907                   p->owner = chan;
05908                   pthread_attr_init(&attr);
05909                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05910                   if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05911                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05912                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05913                      dahdi_enable_ec(p);
05914                      ast_hangup(chan);
05915                   } else {
05916                      if (option_verbose > 2) 
05917                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05918                      /* Start music on hold if appropriate */
05919                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05920                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05921                            S_OR(p->mohsuggest, NULL),
05922                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05923                      }
05924                      p->subs[SUB_THREEWAY].needhold = 1;
05925                   }
05926                   pthread_attr_destroy(&attr);
05927                }
05928             } else {
05929                /* Already have a 3 way call */
05930                int orig_3way_sub;
05931 
05932                /* Need to hold the lock for real-call, private, and 3-way call */
05933                dahdi_lock_sub_owner(p, SUB_THREEWAY);
05934                if (!p->subs[SUB_THREEWAY].owner) {
05935                   /*
05936                    * The 3-way call dissappeared.
05937                    * Let's just ignore this flash-hook.
05938                    */
05939                   ast_log(LOG_NOTICE, "Whoa, the 3-way call disappeared.\n");
05940                   goto winkflashdone;
05941                }
05942                orig_3way_sub = SUB_THREEWAY;
05943 
05944                if (p->subs[SUB_THREEWAY].inthreeway) {
05945                   /* Call is already up, drop the last person */
05946                   if (option_debug)
05947                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05948                   /* If the primary call isn't answered yet, use it */
05949                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05950                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
05951                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05952                      orig_3way_sub = SUB_REAL;
05953                      p->owner = p->subs[SUB_REAL].owner;
05954                   }
05955                   /* Drop the last call and stop the conference */
05956                   if (option_verbose > 2)
05957                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05958                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05959                   p->subs[SUB_REAL].inthreeway = 0;
05960                   p->subs[SUB_THREEWAY].inthreeway = 0;
05961                } else {
05962                   /* Lets see what we're up to */
05963                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
05964                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05965                      if (option_verbose > 2) {
05966                         ast_verbose(VERBOSE_PREFIX_3 "Building conference call with %s and %s\n",
05967                            p->subs[SUB_THREEWAY].owner->name,
05968                            p->subs[SUB_REAL].owner->name);
05969                      }
05970                      /* Put them in the threeway, and flip */
05971                      p->subs[SUB_THREEWAY].inthreeway = 1;
05972                      p->subs[SUB_REAL].inthreeway = 1;
05973                      if (ast->_state == AST_STATE_UP) {
05974                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
05975                         orig_3way_sub = SUB_REAL;
05976                      }
05977                      if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) {
05978                         ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD);
05979                      }
05980                      p->subs[orig_3way_sub].needunhold = 1;
05981                      p->owner = p->subs[SUB_REAL].owner;
05982                   } else {
05983                      if (option_verbose > 2)
05984                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05985                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05986                      orig_3way_sub = SUB_REAL;
05987                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05988                      p->owner = p->subs[SUB_REAL].owner;
05989                      if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05990                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05991                      }
05992                      p->subs[SUB_REAL].needunhold = 1;
05993                      dahdi_enable_ec(p);
05994                   }
05995                      
05996                }
05997                ast_mutex_unlock(&p->subs[orig_3way_sub].owner->lock);
05998             }
05999 winkflashdone:
06000             update_conf(p);
06001             break;
06002          case SIG_EM:
06003          case SIG_EM_E1:
06004          case SIG_FEATD:
06005          case SIG_SF:
06006          case SIG_SFWINK:
06007          case SIG_SF_FEATD:
06008          case SIG_FXSLS:
06009          case SIG_FXSGS:
06010             if (p->dialing)
06011                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
06012             else
06013                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06014             break;
06015          case SIG_FEATDMF_TA:
06016             switch (p->whichwink) {
06017             case 0:
06018                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06019                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06020                break;
06021             case 1:
06022                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06023                break;
06024             case 2:
06025                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06026                return NULL;
06027             }
06028             p->whichwink++;
06029             /* Fall through */
06030          case SIG_FEATDMF:
06031          case SIG_E911:
06032          case SIG_FGC_CAMAMF:
06033          case SIG_FGC_CAMA:
06034          case SIG_FEATB:
06035          case SIG_SF_FEATDMF:
06036          case SIG_SF_FEATB:
06037          case SIG_EMWINK:
06038             /* FGD MF and EMWINK *Must* wait for wink */
06039             if (!ast_strlen_zero(p->dop.dialstr)) {
06040                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06041                if (res < 0) {
06042                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06043                   p->dop.dialstr[0] = '\0';
06044                   return NULL;
06045                } else 
06046                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
06047             }
06048             p->dop.dialstr[0] = '\0';
06049             break;
06050          default:
06051             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
06052          }
06053          break;
06054       case DAHDI_EVENT_HOOKCOMPLETE:
06055          if (p->inalarm) break;
06056          if ((p->radio || (p->oprmode < 0))) break;
06057          switch (mysig) {
06058          case SIG_FXSLS:  /* only interesting for FXS */
06059          case SIG_FXSGS:
06060          case SIG_FXSKS:
06061          case SIG_EM:
06062          case SIG_EM_E1:
06063          case SIG_EMWINK:
06064          case SIG_FEATD:
06065          case SIG_SF:
06066          case SIG_SFWINK:
06067          case SIG_SF_FEATD:
06068             if (!ast_strlen_zero(p->dop.dialstr)) {
06069                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06070                if (res < 0) {
06071                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06072                   p->dop.dialstr[0] = '\0';
06073                   return NULL;
06074                } else 
06075                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
06076             }
06077             p->dop.dialstr[0] = '\0';
06078             p->dop.op = DAHDI_DIAL_OP_REPLACE;
06079             break;
06080          case SIG_FEATDMF:
06081          case SIG_FEATDMF_TA:
06082          case SIG_E911:
06083          case SIG_FGC_CAMA:
06084          case SIG_FGC_CAMAMF:
06085          case SIG_FEATB:
06086          case SIG_SF_FEATDMF:
06087          case SIG_SF_FEATB:
06088             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06089             break;
06090          default:
06091             break;
06092          }
06093          break;
06094       case DAHDI_EVENT_POLARITY:
06095          /*
06096           * If we get a Polarity Switch event, check to see
06097           * if we should change the polarity state and
06098           * mark the channel as UP or if this is an indication
06099           * of remote end disconnect.
06100           */
06101          if (p->polarity == POLARITY_IDLE) {
06102             p->polarity = POLARITY_REV;
06103             if (p->answeronpolarityswitch &&
06104                 ((ast->_state == AST_STATE_DIALING) ||
06105                 (ast->_state == AST_STATE_RINGING))) {
06106                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
06107                ast_setstate(p->owner, AST_STATE_UP);
06108                if (p->hanguponpolarityswitch) {
06109                   gettimeofday(&p->polaritydelaytv, NULL);
06110                }
06111             } else
06112                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
06113          } 
06114          /* Removed else statement from here as it was preventing hangups from ever happening*/
06115          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
06116          if (p->hanguponpolarityswitch &&
06117             (p->polarityonanswerdelay > 0) &&
06118                 (p->polarity == POLARITY_REV) &&
06119             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
06120                                 /* Added log_debug information below to provide a better indication of what is going on */
06121             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) );
06122          
06123             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06124                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
06125                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06126                p->polarity = POLARITY_IDLE;
06127             } else {
06128                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);
06129             }
06130          } else {
06131             p->polarity = POLARITY_IDLE;
06132             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
06133          }
06134                         /* Added more log_debug information below to provide a better indication of what is going on */
06135          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) );
06136          break;
06137       default:
06138          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06139    }
06140    return &p->subs[index].f;
06141 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 3701 of file chan_dahdi.c.

References ast_channel::_state, dahdi_pvt::allocated, dahdi_pvt::alreadyhungup, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_dsp_digitmode(), ast_dsp_free(), ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verbose(), dahdi_pvt::bearer, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_ast_cause_to_r2_cause(), DAHDI_CALL_LEVEL_IDLE, dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index, dahdi_lock_sub_owner(), dahdi_r2_disconnect_call(), dahdi_set_hook(), dahdi_setlinear(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, free, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2call, dahdi_pvt::mohsuggest, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, POLARITY_IDLE, dahdi_pvt::prev, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::progress, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rdnis, dahdi_pvt::realcall, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, S_OR, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and VERBOSE_PREFIX_3.

03702 {
03703    int res;
03704    int index,x, law;
03705    /*static int restore_gains(struct dahdi_pvt *p);*/
03706    struct dahdi_pvt *p = ast->tech_pvt;
03707    struct dahdi_pvt *tmp = NULL;
03708    struct dahdi_pvt *prev = NULL;
03709    struct dahdi_params par;
03710 
03711    if (option_debug)
03712       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03713    if (!ast->tech_pvt) {
03714       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03715       return 0;
03716    }
03717    
03718    ast_mutex_lock(&p->lock);
03719    
03720    index = dahdi_get_index(ast, p, 1);
03721 
03722    if (p->sig == SIG_PRI) {
03723       x = 1;
03724       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03725       p->cid_num[0] = '\0';
03726       p->cid_name[0] = '\0';
03727    }
03728 
03729    x = 0;
03730    dahdi_confmute(p, 0);
03731    restore_gains(p);
03732    if (p->origcid_num) {
03733       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03734       free(p->origcid_num);
03735       p->origcid_num = NULL;
03736    }  
03737    if (p->origcid_name) {
03738       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03739       free(p->origcid_name);
03740       p->origcid_name = NULL;
03741    }  
03742    if (p->dsp)
03743       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03744    p->exten[0] = '\0';
03745 
03746    if (option_debug)
03747       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03748       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03749    p->ignoredtmf = 0;
03750    
03751    if (index > -1) {
03752       /* Real channel, do some fixup */
03753       p->subs[index].owner = NULL;
03754       p->subs[index].needanswer = 0;
03755       p->subs[index].needflash = 0;
03756       p->subs[index].needringing = 0;
03757       p->subs[index].needbusy = 0;
03758       p->subs[index].needcongestion = 0;
03759       p->subs[index].linear = 0;
03760       p->subs[index].needcallerid = 0;
03761       p->polarity = POLARITY_IDLE;
03762       dahdi_setlinear(p->subs[index].dfd, 0);
03763       switch (index) {
03764       case SUB_REAL:
03765          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03766             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03767             if (p->subs[SUB_CALLWAIT].inthreeway) {
03768                /* We had flipped over to answer a callwait and now it's gone */
03769                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03770                /* Move to the call-wait, but un-own us until they flip back. */
03771                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03772                unalloc_sub(p, SUB_CALLWAIT);
03773                p->owner = NULL;
03774             } else {
03775                /* The three way hung up, but we still have a call wait */
03776                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
03777                swap_subs(p, SUB_THREEWAY, SUB_REAL);
03778                unalloc_sub(p, SUB_THREEWAY);
03779                if (p->subs[SUB_REAL].inthreeway) {
03780                   /* This was part of a three way call.  Immediately make way for
03781                      another call */
03782                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03783                   p->subs[SUB_REAL].inthreeway = 0;
03784                   p->owner = p->subs[SUB_REAL].owner;
03785                } else {
03786                   /* This call hasn't been completed yet...  Set owner to NULL */
03787                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03788                   p->owner = NULL;
03789                }
03790             }
03791          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03792             /* Need to hold the lock for real-call, private, and call-waiting call */
03793             dahdi_lock_sub_owner(p, SUB_CALLWAIT);
03794             if (!p->subs[SUB_CALLWAIT].owner) {
03795                /* The call waiting call dissappeared. */
03796                p->owner = NULL;
03797                break;
03798             }
03799 
03800             /* Move to the call-wait and switch back to them. */
03801             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03802             unalloc_sub(p, SUB_CALLWAIT);
03803             p->owner = p->subs[SUB_REAL].owner;
03804             if (p->owner->_state != AST_STATE_UP)
03805                p->subs[SUB_REAL].needanswer = 1;
03806             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03807                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03808             /* Unlock the call-waiting call that we swapped to real-call. */
03809             ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03810          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03811             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03812             unalloc_sub(p, SUB_THREEWAY);
03813             if (p->subs[SUB_REAL].inthreeway) {
03814                /* This was part of a three way call.  Immediately make way for
03815                   another call */
03816                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03817                p->subs[SUB_REAL].inthreeway = 0;
03818                p->owner = p->subs[SUB_REAL].owner;
03819             } else {
03820                /* This call hasn't been completed yet...  Set owner to NULL */
03821                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03822                p->owner = NULL;
03823             }
03824          }
03825          break;
03826       case SUB_CALLWAIT:
03827          /* Ditch the holding callwait call, and immediately make it availabe */
03828          if (p->subs[SUB_CALLWAIT].inthreeway) {
03829             /* Need to hold the lock for call-waiting call, private, and 3-way call */
03830             dahdi_lock_sub_owner(p, SUB_THREEWAY);
03831 
03832             /* This is actually part of a three way, placed on hold.  Place the third part
03833                on music on hold now */
03834             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03835                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
03836                   S_OR(p->mohsuggest, NULL),
03837                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03838             }
03839             p->subs[SUB_THREEWAY].inthreeway = 0;
03840             /* Make it the call wait now */
03841             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03842             unalloc_sub(p, SUB_THREEWAY);
03843             if (p->subs[SUB_CALLWAIT].owner) {
03844                /* Unlock the 3-way call that we swapped to call-waiting call. */
03845                ast_mutex_unlock(&p->subs[SUB_CALLWAIT].owner->lock);
03846             }
03847          } else
03848             unalloc_sub(p, SUB_CALLWAIT);
03849          break;
03850       case SUB_THREEWAY:
03851          /* Need to hold the lock for 3-way call, private, and call-waiting call */
03852          dahdi_lock_sub_owner(p, SUB_CALLWAIT);
03853          if (p->subs[SUB_CALLWAIT].inthreeway) {
03854             /* The other party of the three way call is currently in a call-wait state.
03855                Start music on hold for them, and take the main guy out of the third call */
03856             p->subs[SUB_CALLWAIT].inthreeway = 0;
03857             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03858                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
03859                   S_OR(p->mohsuggest, NULL),
03860                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03861             }
03862          }
03863          if (p->subs[SUB_CALLWAIT].owner) {
03864             ast_mutex_unlock(&p->subs[SUB_CALLWAIT].owner->lock);
03865          }
03866          p->subs[SUB_REAL].inthreeway = 0;
03867          /* If this was part of a three way call index, let us make
03868             another three way call */
03869          unalloc_sub(p, SUB_THREEWAY);
03870          break;
03871       default:
03872          /*
03873           * Should never happen.
03874           * This wasn't any sort of call, so how are we an index?
03875           */
03876          ast_log(LOG_ERROR, "Index found but not any type of call?\n");
03877          break;
03878       }
03879    }
03880 
03881    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03882       p->ringt = 0;
03883       p->distinctivering = 0;
03884       p->confirmanswer = 0;
03885       p->cidrings = 1;
03886       p->outgoing = 0;
03887       p->digital = 0;
03888       p->faxhandled = 0;
03889       p->pulsedial = 0;
03890       p->onhooktime = time(NULL);
03891 #ifdef HAVE_PRI
03892       p->dialing = 0;
03893       p->progress = 0;
03894       p->call_level = DAHDI_CALL_LEVEL_IDLE;
03895 #endif      
03896       if (p->dsp) {
03897          ast_dsp_free(p->dsp);
03898          p->dsp = NULL;
03899       }
03900 
03901       if (p->bufferoverrideinuse) {
03902          /* faxbuffers are in use, revert them */
03903          struct dahdi_bufferinfo bi = {
03904             .txbufpolicy = p->buf_policy,
03905             .rxbufpolicy = p->buf_policy,
03906             .bufsize = p->bufsize,
03907             .numbufs = p->buf_no
03908          };
03909          int bpres;
03910 
03911          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
03912             ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
03913          }
03914          p->bufferoverrideinuse = 0;   
03915       }
03916 
03917       law = DAHDI_LAW_DEFAULT;
03918       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03919       if (res < 0) 
03920          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03921       /* Perform low level hangup if no owner left */
03922 
03923 #ifdef HAVE_OPENR2
03924       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03925          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03926          ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03927          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03928             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03929          } else {
03930             const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03931             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03932             openr2_call_disconnect_cause_t r2cause = r2cause_user
03933                                ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03934                                : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03935             dahdi_r2_disconnect_call(p, r2cause);
03936          }
03937       } else if (p->mfcr2call) {
03938          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03939          p->mfcr2call = 0;
03940       }
03941 #endif
03942 
03943 #if defined(HAVE_PRI)
03944       if (p->pri) {
03945 #ifdef SUPPORT_USERUSER
03946          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03947 #endif
03948 
03949          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
03950          pri_grab(p, p->pri);
03951          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03952             if (p->alreadyhungup) {
03953                ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
03954 
03955 #ifdef SUPPORT_USERUSER
03956                pri_call_set_useruser(p->call, useruser);
03957 #endif
03958 
03959                pri_hangup(p->pri->pri, p->call, -1);
03960                p->call = NULL;
03961                if (p->bearer)
03962                   p->bearer->call = NULL;
03963             } else {
03964                const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03965                int icause = ast->hangupcause ? ast->hangupcause : -1;
03966                ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03967 
03968 #ifdef SUPPORT_USERUSER
03969                pri_call_set_useruser(p->call, useruser);
03970 #endif
03971 
03972                p->alreadyhungup = 1;
03973                if (p->bearer)
03974                   p->bearer->alreadyhungup = 1;
03975                if (cause) {
03976                   if (atoi(cause))
03977                      icause = atoi(cause);
03978                }
03979                pri_hangup(p->pri->pri, p->call, icause);
03980             }
03981          } else {
03982             if (p->bearer)
03983                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03984             p->call = NULL;
03985          }
03986          p->allocated = 0;
03987          p->owner = NULL;
03988          pri_rel(p->pri);
03989          res = 0;
03990       } else
03991 #endif   /* defined(HAVE_PRI) */
03992       {
03993          p->owner = NULL;
03994       }
03995       if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03996          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03997       if (res < 0) {
03998          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03999       }
04000       switch (p->sig) {
04001       case SIG_FXOGS:
04002       case SIG_FXOLS:
04003       case SIG_FXOKS:
04004          memset(&par, 0, sizeof(par));
04005          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04006          if (!res) {
04007 #if 0
04008             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04009 #endif
04010             /* If they're off hook, try playing congestion */
04011             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04012                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04013             else
04014                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04015          }
04016          break;
04017       case SIG_FXSGS:
04018       case SIG_FXSLS:
04019       case SIG_FXSKS:
04020          /* Make sure we're not made available for at least two seconds assuming
04021             we were actually used for an inbound or outbound call. */
04022          if (ast->_state != AST_STATE_RESERVED) {
04023             time(&p->guardtime);
04024             p->guardtime += 2;
04025          }
04026          break;
04027       default:
04028          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04029       }
04030       free(p->cidspill);
04031       p->cidspill = NULL;
04032       if (p->sig)
04033          dahdi_disable_ec(p);
04034       x = 0;
04035       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04036       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04037       p->didtdd = 0;
04038       p->callwaitcas = 0;
04039       p->callwaiting = p->permcallwaiting;
04040       p->hidecallerid = p->permhidecallerid;
04041       p->dialing = 0;
04042       p->rdnis[0] = '\0';
04043       update_conf(p);
04044       reset_conf(p);
04045       /* Restore data mode */
04046       if (p->sig == SIG_PRI) {
04047          x = 0;
04048          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04049       }
04050 #ifdef HAVE_PRI
04051       if (p->bearer) {
04052          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
04053          /* Free up the bearer channel as well, and
04054             don't use its file descriptor anymore */
04055          update_conf(p->bearer);
04056          reset_conf(p->bearer);
04057          p->bearer->owner = NULL;
04058          p->bearer->realcall = NULL;
04059          p->bearer = NULL;
04060          p->subs[SUB_REAL].dfd = -1;
04061          p->pri = NULL;
04062       }
04063 #endif
04064       if (num_restart_pending == 0)
04065          restart_monitor();
04066    }
04067 
04068    p->callwaitingrepeat = 0;
04069    p->cidcwexpire = 0;
04070    p->cid_suppress_expire = 0;
04071    p->oprmode = 0;
04072    ast->tech_pvt = NULL;
04073    ast_mutex_unlock(&p->lock);
04074    if (option_verbose > 2) 
04075       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
04076 
04077    ast_mutex_lock(&iflock);
04078    if (p->restartpending) {
04079       num_restart_pending--;
04080    }
04081 
04082    tmp = iflist;
04083    prev = NULL;
04084    if (p->destroy) {
04085       while (tmp) {
04086          if (tmp == p) {
04087             destroy_channel(prev, tmp, 0);
04088             break;
04089          } else {
04090             prev = tmp;
04091             tmp = tmp->next;
04092          }
04093       }
04094    }
04095    ast_mutex_unlock(&iflock);
04096 
04097    ast_module_unref(ast_module_info->self);
04098    return 0;
04099 }

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

Definition at line 6762 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_pvt::call_level, DAHDI_CALL_LEVEL_ALERTING, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_get_index, dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mohinterpret, dahdi_pvt::outgoing, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::priindication_oob, dahdi_pvt::prioffset, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

Referenced by dahdi_fixup().

06763 {
06764    struct dahdi_pvt *p = chan->tech_pvt;
06765    int res=-1;
06766    int index;
06767    int func = DAHDI_FLASH;
06768    ast_mutex_lock(&p->lock);
06769    index = dahdi_get_index(chan, p, 0);
06770    ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06771 #ifdef HAVE_OPENR2
06772    if (p->mfcr2 && !p->mfcr2_call_accepted) {
06773       ast_mutex_unlock(&p->lock);
06774       /* if this an R2 call and the call is not yet accepted we don't want the 
06775          tone indications to mess up with the MF tones */
06776       return 0;
06777    }
06778 #endif
06779    if (index == SUB_REAL) {
06780       switch (condition) {
06781       case AST_CONTROL_BUSY:
06782 #ifdef HAVE_PRI
06783          if (p->sig == SIG_PRI) {
06784             if (p->priindication_oob) {
06785                chan->hangupcause = AST_CAUSE_USER_BUSY;
06786                chan->_softhangup |= AST_SOFTHANGUP_DEV;
06787                res = 0;
06788                break;
06789             }
06790             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06791             if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06792                chan->hangupcause = AST_CAUSE_USER_BUSY;
06793                p->progress = 1;/* No need to send plain PROGRESS after this. */
06794                if (p->pri && p->pri->pri) {
06795                   if (!pri_grab(p, p->pri)) {
06796                      pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06797                      pri_rel(p->pri);
06798                   } else {
06799                      ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06800                   }
06801                }
06802             }
06803             break;
06804          }
06805 #endif
06806          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06807          break;
06808       case AST_CONTROL_RINGING:
06809 #ifdef HAVE_PRI
06810          if (p->sig == SIG_PRI
06811             && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06812             p->call_level = DAHDI_CALL_LEVEL_ALERTING;
06813             if (p->pri && p->pri->pri) {
06814                if (!pri_grab(p, p->pri)) {
06815                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06816                   pri_rel(p->pri);
06817                } else {
06818                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06819                }
06820             }
06821          }
06822 #endif
06823          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06824          if (chan->_state != AST_STATE_UP) {
06825             if ((chan->_state != AST_STATE_RING) ||
06826                ((p->sig != SIG_FXSKS) &&
06827                 (p->sig != SIG_FXSLS) &&
06828                 (p->sig != SIG_FXSGS)))
06829                ast_setstate(chan, AST_STATE_RINGING);
06830          }
06831          break;
06832       case AST_CONTROL_PROCEEDING:
06833          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06834 #ifdef HAVE_PRI
06835          if (p->sig == SIG_PRI
06836             && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
06837             p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
06838             if (p->pri && p->pri->pri) {
06839                if (!pri_grab(p, p->pri)) {
06840                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06841                   pri_rel(p->pri);
06842                } else {
06843                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06844                }
06845             }
06846             p->dialing = 0;
06847          }
06848 #endif
06849          /* don't continue in ast_indicate */
06850          res = 0;
06851          break;
06852       case AST_CONTROL_PROGRESS:
06853          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06854 #ifdef HAVE_PRI
06855          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
06856          if (p->sig == SIG_PRI
06857             && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
06858             && !p->outgoing) {
06859             p->progress = 1;/* No need to send plain PROGRESS again. */
06860             if (p->pri && p->pri->pri) {
06861                if (!pri_grab(p, p->pri)) {
06862                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06863                   pri_rel(p->pri);
06864                } else {
06865                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06866                }
06867             }
06868          }
06869 #endif
06870          /* don't continue in ast_indicate */
06871          res = 0;
06872          break;
06873       case AST_CONTROL_CONGESTION:
06874 #ifdef HAVE_PRI
06875          if (p->sig == SIG_PRI) {
06876             if (p->priindication_oob) {
06877                /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
06878                switch (chan->hangupcause) {
06879                case AST_CAUSE_USER_BUSY:
06880                case AST_CAUSE_NORMAL_CLEARING:
06881                case 0:/* Cause has not been set. */
06882                   /* Supply a more appropriate cause. */
06883                   chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06884                   break;
06885                default:
06886                   break;
06887                }
06888                chan->_softhangup |= AST_SOFTHANGUP_DEV;
06889                res = 0;
06890                break;
06891             }
06892             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06893             if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
06894                /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
06895                switch (chan->hangupcause) {
06896                case AST_CAUSE_USER_BUSY:
06897                case AST_CAUSE_NORMAL_CLEARING:
06898                case 0:/* Cause has not been set. */
06899                   /* Supply a more appropriate cause. */
06900                   chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06901                   break;
06902                default:
06903                   break;
06904                }
06905                p->progress = 1;/* No need to send plain PROGRESS after this. */
06906                if (p->pri && p->pri->pri) {
06907                   if (!pri_grab(p, p->pri)) {
06908                      pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06909                      pri_rel(p->pri);
06910                   } else {
06911                      ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06912                   }
06913                }
06914             }
06915             break;
06916          }
06917 #endif
06918          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
06919          switch (chan->hangupcause) {
06920          case AST_CAUSE_USER_BUSY:
06921          case AST_CAUSE_NORMAL_CLEARING:
06922          case 0:/* Cause has not been set. */
06923             /* Supply a more appropriate cause. */
06924             chan->hangupcause = AST_CAUSE_CONGESTION;
06925             break;
06926          default:
06927             break;
06928          }
06929          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06930          break;
06931       case AST_CONTROL_HOLD:
06932 #ifdef HAVE_PRI
06933          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06934             if (!pri_grab(p, p->pri)) {
06935                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06936                pri_rel(p->pri);
06937             } else
06938                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06939          } else
06940 #endif
06941             ast_moh_start(chan, data, p->mohinterpret);
06942          break;
06943       case AST_CONTROL_UNHOLD:
06944 #ifdef HAVE_PRI
06945          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06946             if (!pri_grab(p, p->pri)) {
06947                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06948                pri_rel(p->pri);
06949             } else
06950                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06951          } else
06952 #endif
06953             ast_moh_stop(chan);
06954          break;
06955       case AST_CONTROL_RADIO_KEY:
06956          if (p->radio) 
06957              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06958          res = 0;
06959          break;
06960       case AST_CONTROL_RADIO_UNKEY:
06961          if (p->radio)
06962              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06963          res = 0;
06964          break;
06965       case AST_CONTROL_FLASH:
06966          /* flash hookswitch */
06967          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06968             /* Clear out the dial buffer */
06969             p->dop.dialstr[0] = '\0';
06970             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06971                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06972                   chan->name, strerror(errno));
06973             } else
06974                res = 0;
06975          } else
06976             res = 0;
06977          break;
06978       case AST_CONTROL_SRCUPDATE:
06979          res = 0;
06980          break;
06981       case -1:
06982          res = tone_zone_play_tone(p->subs[index].dfd, -1);
06983          break;
06984       }
06985    } else
06986       res = 0;
06987    ast_mutex_unlock(&p->lock);
06988    return res;
06989 }

static void dahdi_link ( struct dahdi_pvt slave,
struct dahdi_pvt master 
) [static]

Definition at line 4535 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

04535                                                                           {
04536    int x;
04537    if (!slave || !master) {
04538       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04539       return;
04540    }
04541    for (x = 0; x < MAX_SLAVES; x++) {
04542       if (!master->slaves[x]) {
04543          master->slaves[x] = slave;
04544          break;
04545       }
04546    }
04547    if (x >= MAX_SLAVES) {
04548       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04549       master->slaves[MAX_SLAVES - 1] = slave;
04550    }
04551    if (slave->master) 
04552       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04553    slave->master = master;
04554    
04555    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04556 }

static void dahdi_lock_sub_owner ( struct dahdi_pvt pvt,
int  sub_idx 
) [static]

Definition at line 1279 of file chan_dahdi.c.

References ast_mutex_trylock(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, ast_channel::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), dahdi_hangup(), and wakeup_sub().

01280 {
01281    for (;;) {
01282       if (!pvt->subs[sub_idx].owner) {
01283          /* No subchannel owner pointer */
01284          break;
01285       }
01286       if (!ast_mutex_trylock(&pvt->subs[sub_idx].owner->lock)) {
01287          /* Got subchannel owner lock */
01288          break;
01289       }
01290       /* We must unlock the private to avoid the possibility of a deadlock */
01291       DEADLOCK_AVOIDANCE(&pvt->lock);
01292    }
01293 }

static struct ast_channel * dahdi_new ( struct dahdi_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 6991 of file chan_dahdi.c.

References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, dahdi_pvt::alreadyhungup, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_copy_string(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, 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(), dahdi_pvt::bearer, dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, dahdi_pvt::cid_name, dahdi_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, dahdi_pvt::context, dahdi_chan_name, dahdi_chan_name_len, dahdi_confmute(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_channel::fds, free, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_recvd_category, dahdi_pvt::mfcr2call, ast_channel::nativeformats, NEED_MFDETECT, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, PRI_TRANS_CAP_DIGITAL, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, dahdi_pvt::silencethreshold, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, and ast_channel::writeformat.

Referenced by dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_offered(), dahdi_request(), do_monitor(), handle_init_event(), and pri_dchannel().

06992 {
06993    struct ast_channel *tmp;
06994    int deflaw;
06995    int res;
06996    int x,y;
06997    int features;
06998    char *b2 = NULL;
06999    struct dahdi_params ps;
07000    char chanprefix[*dahdi_chan_name_len + 4];
07001 
07002    if (i->subs[index].owner) {
07003       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
07004       return NULL;
07005    }
07006    y = 1;
07007    do {
07008       if (b2)
07009          free(b2);
07010 #ifdef HAVE_PRI
07011       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07012          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07013       else
07014 #endif
07015       if (i->channel == CHAN_PSEUDO)
07016          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
07017       else  
07018          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
07019       for (x = 0; x < 3; x++) {
07020          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
07021             break;
07022       }
07023       y++;
07024    } while (x < 3);
07025    strcpy(chanprefix, dahdi_chan_name);
07026    strcat(chanprefix, "/%s");
07027    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
07028    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
07029       free(b2);
07030    if (!tmp)
07031       return NULL;
07032    tmp->tech = chan_tech;
07033    memset(&ps, 0, sizeof(ps));
07034    ps.channo = i->channel;
07035    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07036    if (res) {
07037       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07038       ps.curlaw = DAHDI_LAW_MULAW;
07039    }
07040    if (ps.curlaw == DAHDI_LAW_ALAW)
07041       deflaw = AST_FORMAT_ALAW;
07042    else
07043       deflaw = AST_FORMAT_ULAW;
07044    if (law) {
07045       if (law == DAHDI_LAW_ALAW)
07046          deflaw = AST_FORMAT_ALAW;
07047       else
07048          deflaw = AST_FORMAT_ULAW;
07049    }
07050    tmp->fds[0] = i->subs[index].dfd;
07051    tmp->nativeformats = deflaw;
07052    /* Start out assuming ulaw since it's smaller :) */
07053    tmp->rawreadformat = deflaw;
07054    tmp->readformat = deflaw;
07055    tmp->rawwriteformat = deflaw;
07056    tmp->writeformat = deflaw;
07057    i->subs[index].linear = 0;
07058    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
07059    features = 0;
07060    if (index == SUB_REAL) {
07061       if (i->busydetect && CANBUSYDETECT(i))
07062          features |= DSP_FEATURE_BUSY_DETECT;
07063       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
07064          features |= DSP_FEATURE_CALL_PROGRESS;
07065       if ((!i->outgoing && (i->callprogress & 4)) || 
07066           (i->outgoing && (i->callprogress & 2))) {
07067          features |= DSP_FEATURE_FAX_DETECT;
07068       }
07069 #ifdef DAHDI_TONEDETECT
07070       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07071       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
07072 #endif      
07073          i->hardwaredtmf = 0;
07074          features |= DSP_FEATURE_DTMF_DETECT;
07075 #ifdef DAHDI_TONEDETECT
07076       } else if (NEED_MFDETECT(i)) {
07077          i->hardwaredtmf = 1;
07078          features |= DSP_FEATURE_DTMF_DETECT;
07079       }
07080 #endif
07081    }
07082    if (features) {
07083       if (i->dsp) {
07084          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
07085       } else {
07086          if (i->channel != CHAN_PSEUDO)
07087             i->dsp = ast_dsp_new();
07088          else
07089             i->dsp = NULL;
07090          if (i->dsp) {
07091             i->dsp_features = features;
07092 #ifdef HAVE_PRI
07093             /* We cannot do progress detection until receives PROGRESS message */
07094             if (i->outgoing && (i->sig == SIG_PRI)) {
07095                /* Remember requested DSP features, don't treat
07096                   talking as ANSWER */
07097                i->dsp_features = features & ~DSP_PROGRESS_TALK;
07098                features = 0;
07099             }
07100 #endif
07101             ast_dsp_set_features(i->dsp, features);
07102             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07103             if (!ast_strlen_zero(progzone))
07104                ast_dsp_set_call_progress_zone(i->dsp, progzone);
07105             if (i->busydetect && CANBUSYDETECT(i)) {
07106                if(i->silencethreshold > 0)
07107                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
07108                ast_dsp_set_busy_count(i->dsp, i->busycount);
07109                if(i->busytonelength > 0)
07110                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
07111                if((i->busytonelength == i->busyquietlength) && i->busycompare)
07112                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
07113             }
07114          }
07115       }
07116    }
07117       
07118    if (state == AST_STATE_RING)
07119       tmp->rings = 1;
07120    tmp->tech_pvt = i;
07121    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07122       /* Only FXO signalled stuff can be picked up */
07123       memcpy(&tmp->callgroup, i->callgroup, sizeof(tmp->callgroup));
07124       memcpy(&tmp->pickupgroup, i->pickupgroup, sizeof(tmp->pickupgroup));
07125    }
07126    if (!ast_strlen_zero(i->language))
07127       ast_string_field_set(tmp, language, i->language);
07128    if (!i->owner)
07129       i->owner = tmp;
07130    if (!ast_strlen_zero(i->accountcode))
07131       ast_string_field_set(tmp, accountcode, i->accountcode);
07132    if (i->amaflags)
07133       tmp->amaflags = i->amaflags;
07134    i->subs[index].owner = tmp;
07135    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07136    ast_string_field_set(tmp, call_forward, i->call_forward);
07137    /* If we've been told "no ADSI" then enforce it */
07138    if (!i->adsi)
07139       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07140    if (!ast_strlen_zero(i->exten))
07141       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07142    if (!ast_strlen_zero(i->rdnis))
07143       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07144    if (!ast_strlen_zero(i->dnid))
07145       tmp->cid.cid_dnid = ast_strdup(i->dnid);
07146 
07147    /* Don't use ast_set_callerid() here because it will
07148     * generate a needless NewCallerID event */
07149 #ifdef PRI_ANI
07150    if (!ast_strlen_zero(i->cid_ani))
07151       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07152    else  
07153       tmp->cid.cid_ani = ast_strdup(i->cid_num);
07154 #else
07155    tmp->cid.cid_ani = ast_strdup(i->cid_num);
07156 #endif
07157    tmp->cid.cid_pres = i->callingpres;
07158    tmp->cid.cid_ton = i->cid_ton;
07159 #ifdef HAVE_PRI
07160    tmp->transfercapability = transfercapability;
07161    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07162    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
07163       i->digital = 1;
07164    /* Assume calls are not idle calls unless we're told differently */
07165    i->isidlecall = 0;
07166    i->alreadyhungup = 0;
07167 #endif
07168    /* clear the fake event in case we posted one before we had ast_channel */
07169    i->fake_event = 0;
07170    /* Assure there is no confmute on this channel */
07171    dahdi_confmute(i, 0);
07172    /* Configure the new channel jb */
07173    ast_jb_configure(tmp, &global_jbconf);
07174    if (startpbx) {
07175 
07176 #ifdef HAVE_OPENR2
07177       if (i->mfcr2call) {
07178          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07179       }
07180 #endif
07181 
07182       if (ast_pbx_start(tmp)) {
07183          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07184          ast_hangup(tmp);
07185          i->owner = NULL;
07186          return NULL;
07187       }
07188    }
07189 
07190    ast_module_ref(ast_module_info->self);
07191    
07192    return tmp;
07193 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 1877 of file chan_dahdi.c.

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

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

01878 {
01879    int fd;
01880    int isnum;
01881    int chan = 0;
01882    int bs;
01883    int x;
01884    isnum = 1;
01885    for (x = 0; x < strlen(fn); x++) {
01886       if (!isdigit(fn[x])) {
01887          isnum = 0;
01888          break;
01889       }
01890    }
01891    if (isnum) {
01892       chan = atoi(fn);
01893       if (chan < 1) {
01894          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01895          return -1;
01896       }
01897       fn = DAHDI_FILE_CHANNEL;
01898    }
01899    fd = open(fn, O_RDWR | O_NONBLOCK);
01900    if (fd < 0) {
01901       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01902       return -1;
01903    }
01904    if (chan) {
01905       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01906          x = errno;
01907          close(fd);
01908          errno = x;
01909          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01910          return -1;
01911       }
01912    }
01913    bs = READ_SIZE;
01914    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01915       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01916       x = errno;
01917       close(fd);
01918       errno = x;
01919       return -1;
01920    }
01921    return fd;
01922 }

static void dahdi_pri_error ( struct pri *  pri,
char *  s 
) [static]

Definition at line 10879 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), errno, LOG_ERROR, LOG_WARNING, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.

Referenced by dahdi_restart(), and load_module().

10880 {
10881    int x, y;
10882    int dchan = -1, span = -1;
10883    int dchancount = 0;
10884 
10885    if (pri) {
10886       for (x = 0; x < NUM_SPANS; x++) {
10887          for (y = 0; y < NUM_DCHANS; y++) {
10888             if (pris[x].dchans[y])
10889                dchancount++;
10890 
10891             if (pris[x].dchans[y] == pri)
10892                dchan = y;
10893          }
10894          if (dchan >= 0) {
10895             span = x;
10896             break;
10897          }
10898          dchancount = 0;
10899       }
10900       if ((dchan >= 0) && (span >= 0)) {
10901          if (dchancount > 1)
10902             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10903          else
10904             ast_log(LOG_ERROR, "%s", s);
10905       } else
10906          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
10907    } else
10908       ast_log(LOG_ERROR, "%s", s);
10909 
10910    ast_mutex_lock(&pridebugfdlock);
10911 
10912    if (pridebugfd >= 0) {
10913       if (write(pridebugfd, s, strlen(s)) < 0) {
10914          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10915       }
10916    }
10917 
10918    ast_mutex_unlock(&pridebugfdlock);
10919 }

static void dahdi_pri_message ( struct pri *  pri,
char *  s 
) [static]

Definition at line 10837 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, LOG_ERROR, LOG_WARNING, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.

Referenced by dahdi_restart(), and load_module().

10838 {
10839    int x, y;
10840    int dchan = -1, span = -1;
10841    int dchancount = 0;
10842 
10843    if (pri) {
10844       for (x = 0; x < NUM_SPANS; x++) {
10845          for (y = 0; y < NUM_DCHANS; y++) {
10846             if (pris[x].dchans[y])
10847                dchancount++;
10848 
10849             if (pris[x].dchans[y] == pri)
10850                dchan = y;
10851          }
10852          if (dchan >= 0) {
10853             span = x;
10854             break;
10855          }
10856          dchancount = 0;
10857       }
10858       if ((dchan >= 0) && (span >= 0)) {
10859          if (dchancount > 1)
10860             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10861          else
10862             ast_verbose("%s", s);
10863       } else
10864          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
10865    } else
10866       ast_verbose("%s", s);
10867 
10868    ast_mutex_lock(&pridebugfdlock);
10869 
10870    if (pridebugfd >= 0) {
10871       if (write(pridebugfd, s, strlen(s)) < 0) {
10872          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10873       }
10874    }
10875 
10876    ast_mutex_unlock(&pridebugfdlock);
10877 }

static void dahdi_queue_frame ( struct dahdi_pvt p,
struct ast_frame f,
struct dahdi_pri pri 
) [static]

Definition at line 1313 of file chan_dahdi.c.

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

Referenced by __action_dialoffhook(), and pri_dchannel().

01317 {
01318    /* We must unlock the PRI to avoid the possibility of a deadlock */
01319 #ifdef HAVE_PRI
01320    if (pri)
01321       ast_mutex_unlock(&pri->lock);
01322 #endif      
01323    for (;;) {
01324       if (p->owner) {
01325          if (ast_mutex_trylock(&p->owner->lock)) {
01326             DEADLOCK_AVOIDANCE(&p->lock);
01327          } else {
01328             ast_queue_frame(p->owner, f);
01329             ast_mutex_unlock(&p->owner->lock);
01330             break;
01331          }
01332       } else
01333          break;
01334    }
01335 #ifdef HAVE_PRI
01336    if (pri)
01337       ast_mutex_lock(&pri->lock);
01338 #endif      
01339 }

static int16_t dahdi_r2_alaw_to_linear ( uint8_t  sample  )  [inline, static]

Definition at line 1830 of file chan_dahdi.c.

References AST_ALAW.

01831 {
01832    return AST_ALAW(sample);
01833 }

static int dahdi_r2_answer ( struct dahdi_pvt p  )  [static]

Definition at line 1375 of file chan_dahdi.c.

References ast_true(), dahdi_pvt::owner, pbx_builtin_getvar_helper(), and dahdi_pvt::r2chan.

Referenced by dahdi_answer(), and dahdi_r2_on_call_accepted().

01376 {
01377    int res = 0;
01378    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
01379     * and does not has support for openr2_chan_answer_call_with_mode
01380     *  */
01381 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01382    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01383    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01384    if (!double_answer) {
01385       /* this still can result in double answer if the channel context 
01386        * was configured that way */
01387       res = openr2_chan_answer_call(p->r2chan);
01388    } else if (wants_double_answer) {
01389       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01390    } else {
01391       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01392    } 
01393 #else
01394    res = openr2_chan_answer_call(p->r2chan);
01395 #endif
01396    return res;
01397 }

static void dahdi_r2_disconnect_call ( struct dahdi_pvt p,
openr2_call_disconnect_cause_t  cause 
) [static]

Definition at line 1488 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::lock, LOG_NOTICE, dahdi_pvt::mfcr2call, and dahdi_pvt::r2chan.

Referenced by dahdi_hangup(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_disconnect(), and dahdi_r2_on_call_offered().

01489 {
01490    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01491       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 
01492             p->channel, openr2_proto_get_disconnect_string(cause));
01493       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
01494       openr2_chan_set_idle(p->r2chan);
01495       ast_mutex_lock(&p->lock);
01496       p->mfcr2call = 0;
01497       ast_mutex_unlock(&p->lock);
01498    }
01499 }

static openr2_calling_party_category_t dahdi_r2_get_channel_category ( struct ast_channel c  )  [static]

Definition at line 1399 of file chan_dahdi.c.

References ast_log(), ast_strlen_zero(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_category, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.

Referenced by dahdi_call().

01400 {
01401    openr2_calling_party_category_t cat;
01402    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01403    struct dahdi_pvt *p = c->tech_pvt;
01404    if (ast_strlen_zero(catstr)) {
01405       ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n", 
01406             c->name, openr2_proto_get_category_string(p->mfcr2_category));
01407       return p->mfcr2_category;
01408    }
01409    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01410       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01411             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01412       return p->mfcr2_category;
01413    }
01414    ast_log(LOG_DEBUG, "Using category %s\n", catstr);
01415    return cat;
01416 }

static uint8_t dahdi_r2_linear_to_alaw ( int  sample  )  [inline, static]

Definition at line 1835 of file chan_dahdi.c.

References AST_LIN2A.

01836 {
01837    return AST_LIN2A(sample);
01838 }

static void dahdi_r2_on_ani_digit_received ( openr2_chan_t *  r2chan,
char  digit 
) [static]

Definition at line 1794 of file chan_dahdi.c.

References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.

01795 {
01796    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01797    p->cid_num[p->mfcr2_ani_index] = digit;
01798    p->cid_name[p->mfcr2_ani_index] = digit;
01799    p->mfcr2_ani_index++;
01800    p->cid_num[p->mfcr2_ani_index] = 0;
01801    p->cid_name[p->mfcr2_ani_index] = 0;
01802 }

static void dahdi_r2_on_billing_pulse_received ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1804 of file chan_dahdi.c.

References ast_log(), and LOG_NOTICE.

01805 {
01806    ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01807 }

static void dahdi_r2_on_call_accepted ( openr2_chan_t *  r2chan,
openr2_call_mode_t  mode 
) [static]

Definition at line 1562 of file chan_dahdi.c.

References ast_log(), AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_enable_ec(), dahdi_new(), dahdi_r2_answer(), dahdi_r2_disconnect_call(), dahdi_pvt::dialing, LOG_ERROR, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_call_accepted, dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.

01563 {
01564    struct dahdi_pvt *p = NULL;
01565    struct ast_channel *c = NULL;
01566    p = openr2_chan_get_client_data(r2chan);
01567    dahdi_enable_ec(p);
01568    p->mfcr2_call_accepted = 1;
01569    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01570       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01571       /* if accept on offer is not set, it means at this point the PBX thread is already
01572          launched and therefore this callback is being executed in the PBX thread rather than
01573          the monitor thread, don't launch any other thread, just disable the R2 reading and
01574          answer the call */
01575       if (!p->mfcr2_accept_on_offer) {
01576          openr2_chan_disable_read(r2chan);
01577          ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01578          dahdi_r2_answer(p);
01579          return;
01580       }
01581       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01582       if (c) {
01583          /* chan_dahdi will take care of reading from now on, tell the library to forget about it */
01584          openr2_chan_disable_read(r2chan);
01585       } else {
01586          ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01587          dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01588          return;
01589       }
01590    } else {
01591       ast_verbose("Call accepted on forward channel %d\n", p->channel);
01592       p->subs[SUB_REAL].needringing = 1;
01593       p->dialing = 0;
01594       /* chan_dahdi will take care of reading from now on, tell the library to forget about it */
01595       openr2_chan_disable_read(r2chan);
01596    }  
01597 }

static void dahdi_r2_on_call_answered ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1599 of file chan_dahdi.c.

References ast_verbose(), dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.

01600 {
01601    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01602    ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
01603    p->subs[SUB_REAL].needanswer = 1;
01604 }

static void dahdi_r2_on_call_disconnect ( openr2_chan_t *  r2chan,
openr2_call_disconnect_cause_t  cause 
) [static]

Definition at line 1632 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_BUSY, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NOTDEFINED, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_UNALLOCATED, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_verbose(), dahdi_r2_disconnect_call(), ast_channel::hangupcause, dahdi_pvt::lock, LOG_WARNING, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_pvt::owner, SUB_REAL, and dahdi_pvt::subs.

01633 {
01634    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01635    ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
01636    ast_mutex_lock(&p->lock);
01637    if (p->owner) {
01638       /* when we have an owner we don't call openr2_chan_disconnect_call here, that will
01639          be done in zt_hangup */
01640       if (p->owner->_state == AST_STATE_UP) {
01641          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01642          ast_mutex_unlock(&p->lock);
01643       } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01644          /* being the forward side we must report what happened to the call to whoever requested it */
01645          switch (cause) {
01646          case OR2_CAUSE_BUSY_NUMBER:
01647             p->owner->hangupcause = AST_CAUSE_BUSY;
01648             p->subs[SUB_REAL].needbusy = 1;
01649             break;
01650          case OR2_CAUSE_NUMBER_CHANGED:
01651             p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED;
01652             p->subs[SUB_REAL].needcongestion = 1;
01653             break;
01654          case OR2_CAUSE_NETWORK_CONGESTION:
01655             p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
01656             p->subs[SUB_REAL].needcongestion = 1;
01657             break;
01658          case OR2_CAUSE_OUT_OF_ORDER:
01659             p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01660             p->subs[SUB_REAL].needcongestion = 1;
01661             break;
01662          case OR2_CAUSE_UNALLOCATED_NUMBER:
01663             p->owner->hangupcause = AST_CAUSE_UNALLOCATED;
01664             p->subs[SUB_REAL].needcongestion = 1;
01665             break;
01666          case OR2_CAUSE_NO_ANSWER:
01667             p->owner->hangupcause = AST_CAUSE_NO_ANSWER;
01668             p->subs[SUB_REAL].needcongestion = 1;
01669             break;
01670          case OR2_CAUSE_UNSPECIFIED:
01671             p->owner->hangupcause = AST_CAUSE_NOTDEFINED;
01672             p->subs[SUB_REAL].needcongestion = 1;
01673             break;
01674          case OR2_CAUSE_NORMAL_CLEARING:
01675             p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01676             p->subs[SUB_REAL].needcongestion = 1;
01677             break;
01678          default:
01679             ast_log(LOG_WARNING, "Unhandled cause %d\n", cause);
01680          }
01681          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01682          ast_mutex_unlock(&p->lock);
01683       } else {
01684          ast_mutex_unlock(&p->lock);
01685          /* being the backward side and not UP yet, we only need to request hangup */
01686          /* TODO: what about doing this same thing when were AST_STATE_UP? */
01687          ast_queue_hangup(p->owner);
01688       }  
01689    } else {
01690       ast_mutex_unlock(&p->lock);
01691       /* no owner, therefore we can't use zt_hangup to disconnect, do it right now */
01692       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01693    }
01694 }

static void dahdi_r2_on_call_end ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1552 of file chan_dahdi.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.

01553 {
01554    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01555    ast_verbose("MFC/R2 call end on chan %d\n", p->channel);
01556    ast_mutex_lock(&p->lock);
01557    p->mfcr2call = 0;
01558    ast_mutex_unlock(&p->lock);
01559 }

static void dahdi_r2_on_call_init ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1418 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::exten, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, dahdi_pvt::mfcr2call, and dahdi_pvt::rdnis.

01419 {
01420    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01421    ast_mutex_lock(&p->lock);
01422    if (p->mfcr2call) {
01423       ast_mutex_unlock(&p->lock);
01424       /* TODO: This can happen when some other thread just finished zt_request requesting this very same
01425       interface but has not yet seized the line (zt_call), and the far end wins and seize the line,
01426       can we avoid this somehow?, at this point when zt_call send the seize, it is likely that since
01427       the other end will see our seize as a forced release and drop the call, we will see an invalid
01428       pattern that will be seen and treated as protocol error. */
01429       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01430       return;
01431    }
01432    p->mfcr2call = 1;
01433    /* better safe than sorry ... */
01434    p->cid_name[0] = 0;
01435    p->cid_num[0] = 0;
01436    p->rdnis[0] = 0;
01437    p->exten[0] = 0;
01438    p->mfcr2_ani_index = 0;
01439    p->mfcr2_dnis_index = 0;
01440    p->mfcr2_dnis_matched = 0;
01441    p->mfcr2_call_accepted = 0;
01442    ast_mutex_unlock(&p->lock);
01443    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01444 }

static void dahdi_r2_on_call_offered ( openr2_chan_t *  r2chan,
const char *  ani,
const char *  dnis,
openr2_calling_party_category_t  category 
) [static]

Definition at line 1501 of file chan_dahdi.c.

References ast_exists_extension(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_new(), dahdi_r2_disconnect_call(), dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_recvd_category, SUB_REAL, and dahdi_pvt::use_callerid.

01502 {
01503    struct dahdi_pvt *p;
01504    struct ast_channel *c;
01505    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 
01506          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
01507    p = openr2_chan_get_client_data(r2chan);
01508    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01509       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel);
01510       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01511       return;
01512    }
01513    ast_mutex_lock(&p->lock);
01514    p->mfcr2_recvd_category = category;
01515    /* if we're not supposed to use CID, clear whatever we have */
01516    if (!p->use_callerid) {
01517       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01518       p->cid_num[0] = 0;
01519    p->cid_name[0] = 0;
01520    }
01521    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
01522    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01523       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01524       p->exten[0] = 's';
01525       p->exten[1] = 0;
01526    }
01527    ast_mutex_unlock(&p->lock);
01528    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01529       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01530             p->channel, p->exten, p->context);
01531       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01532    } else {
01533       /* if the user does not want to accept on offer, then we should launch the PBX thread now */
01534       if (!p->mfcr2_accept_on_offer) {
01535          c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01536          if (!c) {
01537             ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01538             dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01539          }
01540          /* Don't disable reading since we still need to generate MF tone to accept
01541             the call or reject it and detect the tone off condition of the other end */
01542       } else if (p->mfcr2_charge_calls) {
01543          ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
01544          openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01545       } else {
01546          ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
01547          openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01548       }  
01549    }  
01550 }

static void dahdi_r2_on_call_read ( openr2_chan_t *  r2chan,
const unsigned char *  buf,
int  buflen 
) [static]

Definition at line 1606 of file chan_dahdi.c.

01607 {
01608    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01609 }

static void dahdi_r2_on_chan_log ( openr2_chan_t *  r2chan,
openr2_log_level_t  level,
const char *  fmt,
va_list  ap 
) [static]

Definition at line 1755 of file chan_dahdi.c.

References dahdi_r2_write_log().

Referenced by mkintf().

01756 {
01757    char logmsg[256];
01758    char completemsg[sizeof(logmsg)+50];
01759    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01760    snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
01761    dahdi_r2_write_log(level, completemsg);
01762 }

static void dahdi_r2_on_context_log ( openr2_context_t *  r2context,
openr2_log_level_t  level,
const char *  fmt,
va_list  ap 
) [static]

Definition at line 1744 of file chan_dahdi.c.

References dahdi_r2_write_log().

01745 {
01746    char logmsg[256];
01747    char completemsg[sizeof(logmsg)+50];
01748    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01749    snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
01750    dahdi_r2_write_log(level, completemsg);
01751 }

static int dahdi_r2_on_dnis_digit_received ( openr2_chan_t *  r2chan,
char  digit 
) [static]

Definition at line 1764 of file chan_dahdi.c.

References ast_exists_extension(), ast_matchmore_extension(), dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, and dahdi_pvt::rdnis.

01765 {
01766    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01767    /* if 'immediate' is set, let's stop requesting DNIS */
01768    if (p->immediate) {
01769       return 0;
01770    }
01771    p->exten[p->mfcr2_dnis_index] = digit;
01772    p->rdnis[p->mfcr2_dnis_index] = digit;
01773    p->mfcr2_dnis_index++;
01774    p->exten[p->mfcr2_dnis_index] = 0;
01775    p->rdnis[p->mfcr2_dnis_index] = 0;
01776    /*
01777    ast_log(LOG_DEBUG, "Got digit %c in dahdi, dnis so far: %s\n", digit, p->exten);
01778    int ret;
01779    ret = ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num);
01780    ast_log(LOG_DEBUG, "ast_exists_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret);
01781    ret = ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num);
01782    ast_log(LOG_DEBUG, "ast_matchmore_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret);
01783    */
01784    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
01785    if ((p->mfcr2_dnis_matched || 
01786        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
01787        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01788       return 0;
01789    }
01790    /* otherwise keep going */
01791    return 1;
01792 }

static void dahdi_r2_on_hardware_alarm ( openr2_chan_t *  r2chan,
int  alarm 
) [static]

Definition at line 1448 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, manager_event(), and dahdi_pvt::unknown_alarm.

01449 {
01450    int res;
01451    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01452    ast_mutex_lock(&p->lock);
01453    p->inalarm = alarm ? 1 : 0;
01454    if (p->inalarm) {
01455       res = get_alarms(p);
01456       /* unknown_alarm may be set here */
01457       handle_alarms(p, res);
01458    } else {
01459       if (!p->unknown_alarm) {
01460          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01461          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01462       } else {
01463          p->unknown_alarm = 0;
01464       }
01465    }
01466    ast_mutex_unlock(&p->lock);
01467    ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
01468 }

static void dahdi_r2_on_line_blocked ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1724 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_REMOTE_BLOCK, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::mfcr2block.

01725 {
01726    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01727    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel);
01728    ast_mutex_lock(&p->lock);
01729    p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK;
01730    ast_mutex_unlock(&p->lock);
01731 }

static void dahdi_r2_on_line_idle ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1733 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), DAHDI_R2_REMOTE_BLOCK, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::mfcr2block.

01734 {
01735    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01736    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01737    ast_mutex_lock(&p->lock);
01738    p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK;
01739    ast_mutex_unlock(&p->lock);
01740 }

static void dahdi_r2_on_os_error ( openr2_chan_t *  r2chan,
int  errorcode 
) [static]

Definition at line 1470 of file chan_dahdi.c.

References ast_log(), and LOG_ERROR.

01471 {
01472    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01473 }

static void dahdi_r2_on_protocol_error ( openr2_chan_t *  r2chan,
openr2_protocol_error_t  reason 
) [static]

Definition at line 1475 of file chan_dahdi.c.

References ast_channel::_softhangup, AST_CAUSE_PROTOCOL_ERROR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_DEV, ast_channel::hangupcause, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2call, and dahdi_pvt::owner.

01476 {
01477    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01478    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01479    if (p->owner) {
01480       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01481       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01482    } 
01483    ast_mutex_lock(&p->lock);
01484    p->mfcr2call = 0;
01485    ast_mutex_unlock(&p->lock);
01486 }

static void dahdi_r2_write_log ( openr2_log_level_t  level,
char *  logmessage 
) [static]

Definition at line 1696 of file chan_dahdi.c.

References ast_log(), ast_verbose(), LOG_DEBUG, LOG_ERROR, LOG_NOTICE, and LOG_WARNING.

Referenced by dahdi_r2_on_chan_log(), and dahdi_r2_on_context_log().

01697 {
01698    switch (level) {
01699    case OR2_LOG_NOTICE:
01700       ast_verbose("%s", logmessage);
01701       break;
01702    case OR2_LOG_WARNING:
01703       ast_log(LOG_WARNING, "%s", logmessage);
01704       break;
01705    case OR2_LOG_ERROR:
01706       ast_log(LOG_ERROR, "%s", logmessage);
01707       break;
01708    case OR2_LOG_STACK_TRACE:
01709    case OR2_LOG_MF_TRACE:
01710    case OR2_LOG_CAS_TRACE:
01711    case OR2_LOG_DEBUG:
01712    case OR2_LOG_EX_DEBUG:
01713       ast_log(LOG_DEBUG, "%s", logmessage);
01714       break;
01715    default:
01716       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01717       ast_log(LOG_NOTICE, "%s", logmessage);
01718       break;
01719    }
01720 }

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

Definition at line 6274 of file chan_dahdi.c.

References __dahdi_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_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), AST_LIN2MU, ast_log(), AST_MULAW, ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_PRERING, AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verbose(), dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::call_level, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHECK_BLOCKING, ast_channel::cid, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, dahdi_pvt::cid_suppress_expire, ast_callerid::cid_tns, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_callwait(), dahdi_get_index, dahdi_handle_dtmf(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, errno, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, dahdi_pvt::mfcr2, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, S_OR, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, dahdi_pvt::use_callerid, and VERBOSE_PREFIX_3.

06275 {
06276    struct dahdi_pvt *p;
06277    int res;
06278    int index;
06279    void *readbuf;
06280    struct ast_frame *f;
06281 
06282    /*
06283     * For analog channels, we must do deadlock avoidance because
06284     * analog ports can have more than one Asterisk channel using
06285     * the same private structure.
06286     */
06287    p = ast->tech_pvt;
06288    while (ast_mutex_trylock(&p->lock)) {
06289       DEADLOCK_AVOIDANCE(&ast->lock);
06290 
06291       /*
06292        * For PRI channels, we must refresh the private pointer because
06293        * the call could move to another B channel while the Asterisk
06294        * channel is unlocked.
06295        */
06296       p = ast->tech_pvt;
06297    }
06298 
06299    index = dahdi_get_index(ast, p, 0);
06300    
06301    /* Hang up if we don't really exist */
06302    if (index < 0) {
06303       ast_log(LOG_WARNING, "We don't exist?\n");
06304       ast_mutex_unlock(&p->lock);
06305       return NULL;
06306    }
06307    
06308    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06309       ast_mutex_unlock(&p->lock);
06310       return NULL;
06311    }
06312 
06313    p->subs[index].f.frametype = AST_FRAME_NULL;
06314    p->subs[index].f.datalen = 0;
06315    p->subs[index].f.samples = 0;
06316    p->subs[index].f.mallocd = 0;
06317    p->subs[index].f.offset = 0;
06318    p->subs[index].f.subclass = 0;
06319    p->subs[index].f.delivery = ast_tv(0,0);
06320    p->subs[index].f.src = "dahdi_read";
06321    p->subs[index].f.data = NULL;
06322    
06323    /* make sure it sends initial key state as first frame */
06324    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06325    {
06326       struct dahdi_params ps;
06327 
06328       memset(&ps, 0, sizeof(ps));
06329       ps.channo = p->channel;
06330       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06331          ast_mutex_unlock(&p->lock);
06332          return NULL;
06333       }
06334       p->firstradio = 1;
06335       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06336       if (ps.rxisoffhook)
06337       {
06338          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
06339       }
06340       else
06341       {
06342          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
06343       }
06344       ast_mutex_unlock(&p->lock);
06345       return &p->subs[index].f;
06346    }
06347    if (p->ringt == 1) {
06348       ast_mutex_unlock(&p->lock);
06349       return NULL;
06350    }
06351    else if (p->ringt > 0) 
06352       p->ringt--;
06353 
06354 #ifdef HAVE_OPENR2
06355    if (p->mfcr2) {
06356       openr2_chan_process_event(p->r2chan);
06357    }  
06358 #endif
06359    
06360    if (p->subs[index].needringing) {
06361       /* Send ringing frame if requested */
06362       p->subs[index].needringing = 0;
06363       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06364       p->subs[index].f.subclass = AST_CONTROL_RINGING;
06365       ast_setstate(ast, AST_STATE_RINGING);
06366       ast_mutex_unlock(&p->lock);
06367       return &p->subs[index].f;
06368    }
06369 
06370    if (p->subs[index].needbusy) {
06371       /* Send busy frame if requested */
06372       p->subs[index].needbusy = 0;
06373       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06374       p->subs[index].f.subclass = AST_CONTROL_BUSY;
06375       ast_mutex_unlock(&p->lock);
06376       return &p->subs[index].f;
06377    }
06378 
06379    if (p->subs[index].needcongestion) {
06380       /* Send congestion frame if requested */
06381       p->subs[index].needcongestion = 0;
06382       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06383       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
06384       ast_mutex_unlock(&p->lock);
06385       return &p->subs[index].f;
06386    }
06387 
06388    if (p->subs[index].needcallerid && !ast->cid.cid_tns) {
06389       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06390                      S_OR(p->lastcid_name, NULL),
06391                      S_OR(p->lastcid_num, NULL)
06392                      );
06393       p->subs[index].needcallerid = 0;
06394    }
06395    
06396    if (p->subs[index].needanswer) {
06397       /* Send answer frame if requested */
06398       p->subs[index].needanswer = 0;
06399       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06400       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06401       ast_mutex_unlock(&p->lock);
06402       return &p->subs[index].f;
06403    }  
06404 
06405 #ifdef HAVE_OPENR2
06406    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06407       /* openr2 took care of reading and handling any event 
06408         (needanswer, needbusy etc), if we continue we will read()
06409         twice, lets just return a null frame. This should only
06410         happen when openr2 is dialing out */
06411       p->subs[index].f.frametype = AST_FRAME_NULL;
06412       p->subs[index].f.subclass = 0;
06413       p->subs[index].f.samples = 0;
06414       p->subs[index].f.mallocd = 0;
06415       p->subs[index].f.offset = 0;
06416       p->subs[index].f.data = NULL;
06417       p->subs[index].f.datalen= 0;
06418       ast_mutex_unlock(&p->lock);
06419       return &p->subs[index].f;
06420    }
06421 #endif
06422 
06423    if (p->subs[index].needflash) {
06424       /* Send answer frame if requested */
06425       p->subs[index].needflash = 0;
06426       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06427       p->subs[index].f.subclass = AST_CONTROL_FLASH;
06428       ast_mutex_unlock(&p->lock);
06429       return &p->subs[index].f;
06430    }  
06431    
06432    if (p->subs[index].needhold) {
06433       /* Send answer frame if requested */
06434       p->subs[index].needhold = 0;
06435       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06436       p->subs[index].f.subclass = AST_CONTROL_HOLD;
06437       ast_mutex_unlock(&p->lock);
06438       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06439       return &p->subs[index].f;
06440    }  
06441    
06442    if (p->subs[index].needunhold) {
06443       /* Send answer frame if requested */
06444       p->subs[index].needunhold = 0;
06445       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06446       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06447       ast_mutex_unlock(&p->lock);
06448       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06449       return &p->subs[index].f;
06450    }  
06451    
06452    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06453       if (!p->subs[index].linear) {
06454          p->subs[index].linear = 1;
06455          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06456          if (res) 
06457             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06458       }
06459    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06460          (ast->rawreadformat == AST_FORMAT_ALAW)) {
06461       if (p->subs[index].linear) {
06462          p->subs[index].linear = 0;
06463          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06464          if (res) 
06465             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06466       }
06467    } else {
06468       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06469       ast_mutex_unlock(&p->lock);
06470       return NULL;
06471    }
06472    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06473    CHECK_BLOCKING(ast);
06474    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06475    ast_clear_flag(ast, AST_FLAG_BLOCKING);
06476 
06477       if (p->use_callerid && (ast->_state == AST_STATE_PRERING &&
06478                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
06479          //ast_log(LOG_NOTICE, "use_callerid %u, cid_start %i\n", p->use_callerid, p->cid_start);
06480          if (!p->subs[index].linear) {
06481                int x, samplin;
06482                int mean, ssum;
06483                
06484                /* First calc mean signal (DC offset) */
06485                for (x = 0, ssum = 0; x < READ_SIZE; x++) {
06486                      //ssum += (ast->rawreadformat == AST_FORMAT_ULAW ? AST_MULAW((u_char *)readbuf) : AST_ALAW((u_char *)readbuf[x]));
06487                      ssum += AST_MULAW(((u_char *)readbuf)[x]);
06488                      if (option_verbose > 5 && (x % 10 == 0))
06489                            ast_log(LOG_NOTICE, "dahdi_read ssum %i, mean %i \n", ssum, ssum / READ_SIZE);
06490                }
06491                mean = ssum / READ_SIZE;
06492 
06493                if (option_verbose > 5)
06494                      ast_log(LOG_WARNING, "dahdi_read channel %s, mean %i \n", ast->name, mean);
06495                if (ast->rawreadformat == AST_FORMAT_ULAW) {
06496                      for (x = 0; x < READ_SIZE; x++) {
06497                            samplin = AST_MULAW(((u_char *)readbuf)[x]);
06498                            if (option_verbose > 6 && (x % 10 == 0))
06499                                  ast_log(LOG_NOTICE, "dahdi_read,x %i, samporig %i samplin %i, samplinconv %i, xconv %i\n", x, ((u_char *)readbuf)[x], samplin, samplin - mean, AST_LIN2MU(samplin - mean));
06500                            ((u_char *)readbuf)[x] = AST_LIN2MU(samplin - mean);
06501                      }
06502                }
06503          }
06504       }
06505 
06506    /* Check for hangup */
06507    if (res < 0) {
06508       f = NULL;
06509       if (res == -1)  {
06510          if (errno == EAGAIN) {
06511             /* Return "NULL" frame if there is nobody there */
06512             ast_mutex_unlock(&p->lock);
06513             return &p->subs[index].f;
06514          } else if (errno == ELAST) {
06515             f = __dahdi_exception(ast);
06516          } else
06517             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06518       }
06519       ast_mutex_unlock(&p->lock);
06520       return f;
06521    }
06522    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06523       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06524       f = __dahdi_exception(ast);
06525       ast_mutex_unlock(&p->lock);
06526       return f;
06527    }
06528    if (p->tdd) { /* if in TDD mode, see if we receive that */
06529       int c;
06530 
06531       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06532       if (c < 0) {
06533          ast_log(LOG_DEBUG,"tdd_feed failed\n");
06534          ast_mutex_unlock(&p->lock);
06535          return NULL;
06536       }
06537       if (c) { /* if a char to return */
06538          p->subs[index].f.subclass = 0;
06539          p->subs[index].f.frametype = AST_FRAME_TEXT;
06540          p->subs[index].f.mallocd = 0;
06541          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06542          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06543          p->subs[index].f.datalen = 1;
06544          *((char *) p->subs[index].f.data) = c;
06545          ast_mutex_unlock(&p->lock);
06546          return &p->subs[index].f;
06547       }
06548    }
06549    if (index == SUB_REAL) {
06550       /* Ensure the CW timers decrement only on a single subchannel */
06551       if (p->cidcwexpire) {
06552          if (!--p->cidcwexpire) {
06553             /* Expired CID/CW */
06554             if (option_verbose > 2)
06555                ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06556             restore_conference(p);
06557          }
06558       }
06559       if (p->cid_suppress_expire) {
06560          --p->cid_suppress_expire;
06561       }
06562       if (p->callwaitingrepeat) {
06563          if (!--p->callwaitingrepeat) {
06564             /* Expired, Repeat callwaiting tone */
06565             ++p->callwaitrings;
06566             dahdi_callwait(ast);
06567          }
06568       }
06569    }
06570    if (p->subs[index].linear) {
06571       p->subs[index].f.datalen = READ_SIZE * 2;
06572    } else 
06573       p->subs[index].f.datalen = READ_SIZE;
06574 
06575    /* Handle CallerID Transmission */
06576    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06577       send_callerid(p);
06578    }
06579 
06580    p->subs[index].f.frametype = AST_FRAME_VOICE;
06581    p->subs[index].f.subclass = ast->rawreadformat;
06582    p->subs[index].f.samples = READ_SIZE;
06583    p->subs[index].f.mallocd = 0;
06584    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06585    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06586 #if 0
06587    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06588 #endif   
06589    if (p->dialing || /* Transmitting something */
06590       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
06591       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
06592       ) {
06593       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
06594          don't send anything */
06595       p->subs[index].f.frametype = AST_FRAME_NULL;
06596       p->subs[index].f.subclass = 0;
06597       p->subs[index].f.samples = 0;
06598       p->subs[index].f.mallocd = 0;
06599       p->subs[index].f.offset = 0;
06600       p->subs[index].f.data = NULL;
06601       p->subs[index].f.datalen= 0;
06602    }
06603    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
06604       /* Perform busy detection. etc on the dahdi line */
06605       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06606       if (f) {
06607          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06608             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06609                /* Treat this as a "hangup" instead of a "busy" on the assumption that
06610                   a busy  */
06611                f = NULL;
06612             }
06613          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
06614             || f->frametype == AST_FRAME_DTMF_END) {
06615 #ifdef HAVE_PRI
06616             if (p->sig == SIG_PRI
06617                && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06618                && p->pri
06619                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
06620                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06621                /* Don't accept in-band DTMF when in overlap dial mode */
06622                ast_log(LOG_DEBUG,
06623                   "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
06624                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
06625                   f->subclass, f->subclass, ast->name);
06626 
06627                f->frametype = AST_FRAME_NULL;
06628                f->subclass = 0;
06629             }
06630 #endif            
06631             /* DSP clears us of being pulse */
06632             p->pulsedial = 0;
06633          }
06634       }
06635    } else 
06636       f = &p->subs[index].f; 
06637 
06638    if (f) {
06639       switch (f->frametype) {
06640       case AST_FRAME_DTMF_BEGIN:
06641       case AST_FRAME_DTMF_END:
06642          dahdi_handle_dtmf(ast, index, &f);
06643          break;
06644       case AST_FRAME_VOICE:
06645          if (p->cidspill || p->cid_suppress_expire) {
06646             /* We are/were sending a caller id spill.  Suppress any echo. */
06647             p->subs[index].f.frametype = AST_FRAME_NULL;
06648             p->subs[index].f.subclass = 0;
06649             p->subs[index].f.samples = 0;
06650             p->subs[index].f.mallocd = 0;
06651             p->subs[index].f.offset = 0;
06652             p->subs[index].f.data = NULL;
06653             p->subs[index].f.datalen= 0;
06654          }
06655          break;
06656       default:
06657          break;
06658       }
06659    }
06660 
06661    /* If we have a fake_event, trigger exception to handle it */
06662    if (p->fake_event)
06663       ast_set_flag(ast, AST_FLAG_EXCEPTION);
06664 
06665    ast_mutex_unlock(&p->lock);
06666    return f;
06667 }

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

Definition at line 10014 of file chan_dahdi.c.

References alloc_sub(), dahdi_pvt::allocated, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_get_group(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, available(), dahdi_pvt::bearer, busy, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_new(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::distinctivering, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::lock, dahdi_pri::lock, lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pvt::next, NUM_SPANS, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, pri_assign_bearer(), pri_find_empty_chan(), pris, dahdi_pri::pvts, restart_monitor(), s, dahdi_pvt::sig, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI_LIB_HANDLE_CASES, dahdi_pri::span, strsep(), SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.

Referenced by pri_dchannel().

10015 {
10016    ast_group_t groupmatch;
10017    int channelmatch = -1;
10018    int roundrobin = 0;
10019    int callwait = 0;
10020    int busy = 0;
10021    struct dahdi_pvt *p;
10022    struct ast_channel *tmp = NULL;
10023    char *dest=NULL;
10024    int x;
10025    char *s;
10026    char opt=0;
10027    int res=0, y=0;
10028    int backwards = 0;
10029 #ifdef HAVE_PRI
10030    int crv;
10031    int bearer = -1;
10032    int trunkgroup;
10033    struct dahdi_pri *pri=NULL;
10034 #endif   
10035    struct dahdi_pvt *exit, *start, *end;
10036    ast_mutex_t *lock;
10037    int channelmatched = 0;
10038    int groupmatched = 0;
10039    
10040    memset(&groupmatch, 0, sizeof(groupmatch));
10041 
10042    /*
10043     * data is ---v
10044     * Dial(DAHDI/pseudo[/extension])
10045     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
10046     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
10047     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
10048     *
10049     * g - channel group allocation search forward
10050     * G - channel group allocation search backward
10051     * r - channel group allocation round robin search forward
10052     * R - channel group allocation round robin search backward
10053     *
10054     * c - Wait for DTMF digit to confirm answer
10055     * r<cadance#> - Set distintive ring cadance number
10056     * d - Force bearer capability for ISDN call to digital.
10057     */
10058 
10059    /* Assume we're locking the iflock */
10060    lock = &iflock;
10061    start = iflist;
10062    end = ifend;
10063    if (data) {
10064       dest = ast_strdupa((char *)data);
10065    } else {
10066       ast_log(LOG_WARNING, "Channel requested with no data\n");
10067       return NULL;
10068    }
10069    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
10070       char buf[12];
10071       /* Retrieve the group number */
10072       char *stringp;
10073 
10074       stringp = dest + 1;
10075       s = strsep(&stringp, "/");
10076       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10077          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
10078          return NULL;
10079       }
10080       sprintf(buf, "%d", x);
10081       ast_get_group(&groupmatch, buf);
10082       if (toupper(dest[0]) == 'G') {
10083          if (dest[0] == 'G') {
10084             backwards = 1;
10085             p = ifend;
10086          } else
10087             p = iflist;
10088       } else {
10089          if (dest[0] == 'R') {
10090             backwards = 1;
10091             p = round_robin[x]?round_robin[x]->prev:ifend;
10092             if (!p)
10093                p = ifend;
10094          } else {
10095             p = round_robin[x]?round_robin[x]->next:iflist;
10096             if (!p)
10097                p = iflist;
10098          }
10099          roundrobin = 1;
10100       }
10101    } else {
10102       char *stringp;
10103 
10104       stringp = dest;
10105       s = strsep(&stringp, "/");
10106       p = iflist;
10107       if (!strcasecmp(s, "pseudo")) {
10108          /* Special case for pseudo */
10109          x = CHAN_PSEUDO;
10110          channelmatch = x;
10111       } 
10112 #ifdef HAVE_PRI
10113       else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
10114          if ((trunkgroup < 1) || (crv < 1)) {
10115             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
10116             return NULL;
10117          }
10118          res--;
10119          for (x = 0; x < NUM_SPANS; x++) {
10120             if (pris[x].trunkgroup == trunkgroup) {
10121                pri = pris + x;
10122                lock = &pri->lock;
10123                start = pri->crvs;
10124                end = pri->crvend;
10125                break;
10126             }
10127          }
10128          if (!pri) {
10129             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
10130             return NULL;
10131          }
10132          channelmatch = crv;
10133          p = pris[x].crvs;
10134       }
10135 #endif   
10136       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10137          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
10138          return NULL;
10139       } else {
10140          channelmatch = x;
10141       }
10142    }
10143    /* Search for an unowned channel */
10144    ast_mutex_lock(lock);
10145    exit = p;
10146    while (p && !tmp) {
10147       if (roundrobin)
10148          round_robin[x] = p;
10149 
10150       if (p && available(p, channelmatch, &groupmatch, &busy, &channelmatched, &groupmatched)) {
10151          if (option_debug)
10152             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
10153             if (p->inalarm) 
10154                goto next;
10155 
10156          callwait = (p->owner != NULL);
10157 #ifdef HAVE_PRI
10158          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
10159             if (p->sig != SIG_FXSKS) {
10160                /* Gotta find an actual channel to use for this
10161                   CRV if this isn't a callwait */
10162                bearer = pri_find_empty_chan(pri, 0, -1);
10163                if (bearer < 0) {
10164                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
10165                   p = NULL;
10166                   break;
10167                }
10168                pri_assign_bearer(p, pri, pri->pvts[bearer]);
10169             } else {
10170                if (alloc_sub(p, 0)) {
10171                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
10172                   p = NULL;
10173                   break;
10174                } else
10175                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
10176                p->pri = pri;
10177             }
10178          }
10179 #endif
10180 
10181 #ifdef HAVE_OPENR2
10182          if (p->mfcr2) {
10183             ast_mutex_lock(&p->lock);
10184             if (p->mfcr2call) {
10185                ast_mutex_unlock(&p->lock);
10186                ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
10187                goto next;
10188             }
10189             if (p->mfcr2block) {
10190                ast_mutex_unlock(&p->lock);
10191                ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
10192                goto next;
10193             }
10194             p->mfcr2call = 1;
10195             ast_mutex_unlock(&p->lock);
10196          }
10197 #endif
10198 
10199          if (p->channel == CHAN_PSEUDO) {
10200             p = chandup(p);
10201             if (!p) {
10202                break;
10203             }
10204          }
10205          if (p->owner) {
10206             if (alloc_sub(p, SUB_CALLWAIT)) {
10207                p = NULL;
10208                break;
10209             }
10210          }
10211 #if defined(HAVE_PRI)
10212          switch (p->sig) {
10213          case SIG_GR303FXOKS:
10214          case SIG_GR303FXSKS:
10215          case SIG_PRI_LIB_HANDLE_CASES:
10216             /*
10217              * We already have the B channel reserved for this call.  We
10218              * just need to make sure that dahdi_hangup() has completed
10219              * cleaning up before continuing.
10220              */
10221             ast_mutex_lock(&p->lock);
10222             ast_mutex_unlock(&p->lock);
10223             break;
10224          default:
10225             break;
10226          }
10227 #endif   /* defined(HAVE_PRI) */
10228          p->outgoing = 1;
10229          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
10230          if (!tmp) {
10231             p->outgoing = 0;
10232 #if defined(HAVE_PRI)
10233             /*
10234              * This should be the last thing to clear when we are done with
10235              * the channel.
10236              */
10237             p->allocated = 0;
10238 #endif   /* defined(HAVE_PRI) */
10239          }
10240 #ifdef HAVE_PRI
10241          if (p->bearer) {
10242             /* Log owner to bearer channel, too */
10243             p->bearer->owner = tmp;
10244          }
10245 #endif         
10246          /* Make special notes */
10247          if (res > 1) {
10248             if (opt == 'c') {
10249                /* Confirm answer */
10250                p->confirmanswer = 1;
10251             } else if (opt == 'r') {
10252                /* Distinctive ring */
10253                if (res < 3)
10254                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
10255                else
10256                   p->distinctivering = y;
10257             } else if (opt == 'd') {
10258                /* If this is an ISDN call, make it digital */
10259                p->digital = 1;
10260                if (tmp)
10261                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
10262             } else {
10263                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
10264             }
10265          }
10266          /* Note if the call is a call waiting call */
10267          if (tmp && callwait)
10268             tmp->cdrflags |= AST_CDR_CALLWAIT;
10269          break;
10270       }
10271 next:
10272       if (backwards) {
10273          p = p->prev;
10274          if (!p)
10275             p = end;
10276       } else {
10277          p = p->next;
10278          if (!p)
10279             p = start;
10280       }
10281       /* stop when you roll to the one that we started from */
10282       if (p == exit)
10283          break;
10284    }
10285    ast_mutex_unlock(lock);
10286    restart_monitor();
10287    if (callwait)
10288       *cause = AST_CAUSE_BUSY;
10289    else if (!tmp) {
10290       if (channelmatched) {
10291          if (busy)
10292             *cause = AST_CAUSE_BUSY;
10293       } else if (groupmatched) {
10294          *cause = AST_CAUSE_CONGESTION;
10295       }
10296    }
10297       
10298    return tmp;
10299 }

static int dahdi_restart ( void   )  [static]

Definition at line 13124 of file chan_dahdi.c.

References ast_active_channels(), ast_cond_wait(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verbose(), dahdi_close_pri_fd(), dahdi_pri_error(), dahdi_pri_message(), dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, init_mfcr2_globals(), lock, LOG_DEBUG, LOG_WARNING, dahdi_pri::master, master, monlock, dahdi_pvt::next, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, option_debug, option_verbose, dahdi_pvt::owner, pris, r2links, restart_lock, setup_dahdi(), ss_thread_lock, SUB_REAL, and dahdi_pvt::subs.

Referenced by __action_restart(), and dahdi_restart_cmd().

13125 {
13126 
13127 #ifdef HAVE_OPENR2
13128    int r;
13129 #endif
13130   
13131 #if defined(HAVE_PRI)
13132    int i, j;
13133 #endif
13134    int cancel_code;
13135    struct dahdi_pvt *p;
13136 
13137    ast_mutex_lock(&restart_lock);
13138  
13139    if (option_verbose)
13140       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
13141    dahdi_softhangup_all();
13142    if (option_verbose > 3)
13143       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
13144 
13145 #ifdef HAVE_OPENR2
13146    for (r = 0; r < NUM_SPANS; r++) {
13147       if (r2links[r].master != AST_PTHREADT_NULL) {
13148          ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
13149          pthread_cancel(r2links[r].master);
13150          pthread_join(r2links[r].master, NULL);
13151          openr2_context_delete(r2links[r].protocol_context);
13152       }
13153    }
13154    init_mfcr2_globals();
13155 #endif
13156    
13157    #if defined(HAVE_PRI)
13158    for (i = 0; i < NUM_SPANS; i++) {
13159       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
13160          cancel_code = pthread_cancel(pris[i].master);
13161          pthread_kill(pris[i].master, SIGURG);
13162          if (option_debug > 3)
13163             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
13164             pthread_join(pris[i].master, NULL);
13165          if (option_debug > 3)
13166             ast_verbose("Joined thread of span %d\n", i);
13167       }
13168     }
13169    #endif
13170 
13171     ast_mutex_lock(&monlock);
13172     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13173       cancel_code = pthread_cancel(monitor_thread);
13174       pthread_kill(monitor_thread, SIGURG);
13175       if (option_debug > 3)
13176          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
13177         pthread_join(monitor_thread, NULL);
13178       if (option_debug > 3)
13179          ast_verbose("Joined monitor thread\n");
13180     }
13181    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
13182 
13183    ast_mutex_lock(&ss_thread_lock);
13184    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
13185       int x = DAHDI_FLASH;
13186       if (option_debug > 2)
13187          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
13188 
13189       for (p = iflist; p; p = p->next) {
13190          if (p->owner)
13191             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */    
13192       }
13193       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
13194    }
13195 
13196    /* ensure any created channels before monitor threads were stopped are hungup */
13197    dahdi_softhangup_all();
13198    if (option_verbose > 3)
13199       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
13200    destroy_all_channels();
13201    if (option_debug)
13202       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
13203 
13204     ast_mutex_unlock(&monlock);
13205 
13206    #ifdef HAVE_PRI
13207    for (i = 0; i < NUM_SPANS; i++) {
13208       for (j = 0; j < NUM_DCHANS; j++)
13209             dahdi_close_pri_fd(&(pris[i]), j);
13210    }
13211 
13212    memset(pris, 0, sizeof(pris));
13213    for (i = 0; i < NUM_SPANS; i++) {
13214       ast_mutex_init(&pris[i].lock);
13215       pris[i].offset = -1;
13216       pris[i].master = AST_PTHREADT_NULL;
13217       for (j = 0; j < NUM_DCHANS; j++)
13218          pris[i].fds[j] = -1;
13219    }
13220    pri_set_error(dahdi_pri_error);
13221    pri_set_message(dahdi_pri_message);
13222    #endif
13223 
13224    if (setup_dahdi(2) != 0) {
13225       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
13226       ast_mutex_unlock(&ss_thread_lock);
13227       return 1;
13228    }
13229    ast_mutex_unlock(&ss_thread_lock);
13230    ast_mutex_unlock(&restart_lock);
13231    return 0;
13232 }

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

Definition at line 13234 of file chan_dahdi.c.

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

13235 {
13236    if (argc != 2) {
13237       return RESULT_SHOWUSAGE;
13238    }
13239 
13240    if (dahdi_restart() != 0)
13241       return RESULT_FAILURE;
13242    return RESULT_SUCCESS;
13243 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 4935 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), and dahdi_handle_event().

04936 {
04937    int x;
04938    int res;
04939    /* Make sure our transmit state is on hook */
04940    x = 0;
04941    x = DAHDI_ONHOOK;
04942    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04943    do {
04944       x = DAHDI_RING;
04945       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04946       if (res) {
04947          switch (errno) {
04948          case EBUSY:
04949          case EINTR:
04950             /* Wait just in case */
04951             usleep(10000);
04952             continue;
04953          case EINPROGRESS:
04954             res = 0;
04955             break;
04956          default:
04957             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04958             res = 0;
04959          }
04960       }
04961    } while (res);
04962    return res;
04963 }

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

Definition at line 3445 of file chan_dahdi.c.

References send_keypad_facility_exec().

Referenced by load_module().

03446 {
03447    return send_keypad_facility_exec(chan, data);
03448 }

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

Definition at line 15184 of file chan_dahdi.c.

References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index, dahdi_subchannel::dfd, END_SILENCE_LEN, errno, free, HEADER_LEN, HEADER_MS, len(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::mate, option_debug, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.

15185 {
15186 #define  END_SILENCE_LEN 400
15187 #define  HEADER_MS 50
15188 #define  TRAILER_MS 5
15189 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15190 #define  ASCII_BYTES_PER_CHAR 80
15191 
15192    unsigned char *buf,*mybuf;
15193    struct dahdi_pvt *p = c->tech_pvt;
15194    struct pollfd fds[1];
15195    int size,res,fd,len,x;
15196    int bytes=0;
15197    /* Initial carrier (imaginary) */
15198    float cr = 1.0;
15199    float ci = 0.0;
15200    float scont = 0.0;
15201    int index;
15202 
15203    index = dahdi_get_index(c, p, 0);
15204    if (index < 0) {
15205       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
15206       return -1;
15207    }
15208    if (!text[0]) return(0); /* if nothing to send, dont */
15209    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
15210    if (p->mate) 
15211       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15212    else
15213       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15214    if (!buf)
15215       return -1;
15216    mybuf = buf;
15217    if (p->mate) {
15218       int codec = AST_LAW(p);
15219       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
15220          PUT_CLID_MARKMS;
15221       }
15222       /* Put actual message */
15223       for (x = 0; text[x]; x++) {
15224          PUT_CLID(text[x]);
15225       }
15226       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
15227          PUT_CLID_MARKMS;
15228       }
15229       len = bytes;
15230       buf = mybuf;
15231    } else {
15232       len = tdd_generate(p->tdd, buf, text);
15233       if (len < 1) {
15234          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15235          free(mybuf);
15236          return -1;
15237       }
15238    }
15239    memset(buf + len, 0x7f, END_SILENCE_LEN);
15240    len += END_SILENCE_LEN;
15241    fd = p->subs[index].dfd;
15242    while (len) {
15243       if (ast_check_hangup(c)) {
15244          free(mybuf);
15245          return -1;
15246       }
15247       size = len;
15248       if (size > READ_SIZE)
15249          size = READ_SIZE;
15250       fds[0].fd = fd;
15251       fds[0].events = POLLOUT | POLLPRI;
15252       fds[0].revents = 0;
15253       res = poll(fds, 1, -1);
15254       if (!res) {
15255          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
15256          continue;
15257       }
15258         /* if got exception */
15259       if (fds[0].revents & POLLPRI) {
15260          ast_free(mybuf);
15261          return -1;
15262       }
15263       if (!(fds[0].revents & POLLOUT)) {
15264          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
15265          continue;
15266       }
15267       res = write(fd, buf, size);
15268       if (res != size) {
15269          if (res == -1) {
15270             free(mybuf);
15271             return -1;
15272          }
15273          if (option_debug)
15274             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15275          break;
15276       }
15277       len -= size;
15278       buf += size;
15279    }
15280    free(mybuf);
15281    return(0);
15282 }

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

Definition at line 2647 of file chan_dahdi.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by __dahdi_exception(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), mkintf(), and ss_thread().

02648 {
02649    int x, res;
02650 
02651    x = hs;
02652    res = ioctl(fd, DAHDI_HOOK, &x);
02653 
02654    if (res < 0) {
02655       if (errno == EINPROGRESS)
02656          return 0;
02657       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02658       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02659    }
02660 
02661    return res;
02662 }

static int dahdi_setlaw ( int  dfd,
int  law 
) [static]

Definition at line 11021 of file chan_dahdi.c.

Referenced by pri_dchannel().

11022 {
11023    int res;
11024    res = ioctl(dfd, DAHDI_SETLAW, &law);
11025    if (res)
11026       return res;
11027    return 0;
11028 }

static int dahdi_setlinear ( int  dfd,
int  linear 
) [static]

Definition at line 1944 of file chan_dahdi.c.

Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().

01945 {
01946    int res;
01947    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01948    if (res)
01949       return res;
01950    return 0;
01951 }

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

Todo:
XXX This is an abuse of the stack!!

Definition at line 4209 of file chan_dahdi.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(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::law, len(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.

04210 {
04211    char *cp;
04212    signed char *scp;
04213    int x;
04214    int index;
04215    struct dahdi_pvt *p = chan->tech_pvt, *pp;
04216    struct oprmode *oprmode;
04217    
04218 
04219    /* all supported options require data */
04220    if (!data || (datalen < 1)) {
04221       errno = EINVAL;
04222       return -1;
04223    }
04224 
04225    switch (option) {
04226    case AST_OPTION_TXGAIN:
04227       scp = (signed char *) data;
04228       index = dahdi_get_index(chan, p, 0);
04229       if (index < 0) {
04230          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04231          return -1;
04232       }
04233       if (option_debug)
04234          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04235       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04236    case AST_OPTION_RXGAIN:
04237       scp = (signed char *) data;
04238       index = dahdi_get_index(chan, p, 0);
04239       if (index < 0) {
04240          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04241          return -1;
04242       }
04243       if (option_debug)
04244          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04245       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04246    case AST_OPTION_TONE_VERIFY:
04247       if (!p->dsp)
04248          break;
04249       cp = (char *) data;
04250       switch (*cp) {
04251       case 1:
04252          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04253          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
04254          break;
04255       case 2:
04256          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04257          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
04258          break;
04259       default:
04260          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04261          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
04262          break;
04263       }
04264       break;
04265    case AST_OPTION_TDD:
04266       /* turn on or off TDD */
04267       cp = (char *) data;
04268       p->mate = 0;
04269       if (!*cp) { /* turn it off */
04270          if (option_debug)
04271             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04272          if (p->tdd)
04273             tdd_free(p->tdd);
04274          p->tdd = 0;
04275          break;
04276       }
04277       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04278          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04279       dahdi_disable_ec(p);
04280       /* otherwise, turn it on */
04281       if (!p->didtdd) { /* if havent done it yet */
04282          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
04283          unsigned char *buf;
04284          int size, res, fd, len;
04285          struct pollfd fds[1];
04286 
04287          buf = mybuf;
04288          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
04289          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
04290          len = 40000;
04291          index = dahdi_get_index(chan, p, 0);
04292          if (index < 0) {
04293             ast_log(LOG_WARNING, "No index in TDD?\n");
04294             return -1;
04295          }
04296          fd = p->subs[index].dfd;
04297          while (len) {
04298             if (ast_check_hangup(chan))
04299                return -1;
04300             size = len;
04301             if (size > READ_SIZE)
04302                size = READ_SIZE;
04303             fds[0].fd = fd;
04304             fds[0].events = POLLPRI | POLLOUT;
04305             fds[0].revents = 0;
04306             res = poll(fds, 1, -1);
04307             if (!res) {
04308                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04309                continue;
04310             }
04311             /* if got exception */
04312             if (fds[0].revents & POLLPRI)
04313                return -1;
04314             if (!(fds[0].revents & POLLOUT)) {
04315                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04316                continue;
04317             }
04318             res = write(fd, buf, size);
04319             if (res != size) {
04320                if (res == -1) return -1;
04321                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04322                break;
04323             }
04324             len -= size;
04325             buf += size;
04326          }
04327          p->didtdd = 1; /* set to have done it now */    
04328       }
04329       if (*cp == 2) { /* Mate mode */
04330          if (p->tdd)
04331             tdd_free(p->tdd);
04332          p->tdd = 0;
04333          p->mate = 1;
04334          break;
04335       }     
04336       if (!p->tdd) { /* if we dont have one yet */
04337          p->tdd = tdd_new(); /* allocate one */
04338       }     
04339       break;
04340    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
04341       if (!p->dsp)
04342          break;
04343       cp = (char *) data;
04344       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04345          *cp ? "ON" : "OFF", (int) *cp, chan->name);
04346                 p->dtmfrelax = 0;
04347                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04348                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04349       break;
04350    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
04351       cp = (char *) data;
04352       if (!*cp) {    
04353          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04354          x = 0;
04355          dahdi_disable_ec(p);
04356       } else {    
04357          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04358          x = 1;
04359       }
04360       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04361          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04362       break;
04363    case AST_OPTION_OPRMODE:  /* Operator services mode */
04364       oprmode = (struct oprmode *) data;
04365       pp = oprmode->peer->tech_pvt;
04366       p->oprmode = pp->oprmode = 0;
04367       /* setup peers */
04368       p->oprpeer = pp;
04369       pp->oprpeer = p;
04370       /* setup modes, if any */
04371       if (oprmode->mode) 
04372       {
04373          pp->oprmode = oprmode->mode;
04374          p->oprmode = -oprmode->mode;
04375       }
04376       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04377          oprmode->mode, chan->name,oprmode->peer->name);;
04378       break;
04379    case AST_OPTION_ECHOCAN:
04380       cp = (char *) data;
04381       if (*cp) {
04382          ast_log(LOG_DEBUG, "Enabling echo cancellation on %s\n", chan->name);
04383          dahdi_enable_ec(p);
04384       } else {
04385          ast_log(LOG_DEBUG, "Disabling echo cancellation on %s\n", chan->name);
04386          dahdi_disable_ec(p);
04387       }
04388       break;
04389    }
04390    errno = 0;
04391 
04392    return 0;
04393 }

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

Definition at line 13306 of file chan_dahdi.c.

References dahdi_pvt::allocated, ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::bearer, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pri::crvs, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law, dahdi_subchannel::linear, dahdi_pri::lock, lock, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::master, MAX_SLAVES, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pvt::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, pris, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::resetting, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

13307 {
13308    int channel;
13309    struct dahdi_pvt *tmp = NULL;
13310    struct dahdi_confinfo ci;
13311    struct dahdi_params ps;
13312    int x;
13313    ast_mutex_t *lock;
13314    struct dahdi_pvt *start;
13315 #ifdef HAVE_PRI
13316    char *c;
13317    int trunkgroup;
13318    struct dahdi_pri *pri=NULL;
13319 #endif
13320 
13321    lock = &iflock;
13322    start = iflist;
13323 
13324    if (argc != 4)
13325       return RESULT_SHOWUSAGE;
13326 #ifdef HAVE_PRI
13327    if ((c = strchr(argv[3], ':'))) {
13328       if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
13329          return RESULT_SHOWUSAGE;
13330       if ((trunkgroup < 1) || (channel < 1))
13331          return RESULT_SHOWUSAGE;
13332       for (x = 0; x < NUM_SPANS; x++) {
13333          if (pris[x].trunkgroup == trunkgroup) {
13334             pri = pris + x;
13335             break;
13336          }
13337       }
13338       if (pri) {
13339          start = pri->crvs;
13340          lock = &pri->lock;
13341       } else {
13342          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13343          return RESULT_FAILURE;
13344       }
13345    } else
13346 #endif
13347       channel = atoi(argv[3]);
13348 
13349    ast_mutex_lock(lock);
13350    tmp = start;
13351    while (tmp) {
13352       if (tmp->channel == channel) {
13353 #ifdef HAVE_PRI
13354          if (pri) 
13355             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
13356          else
13357 #endif         
13358          ast_cli(fd, "Channel: %d\n", tmp->channel);
13359          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
13360          ast_cli(fd, "Span: %d\n", tmp->span);
13361          ast_cli(fd, "Extension: %s\n", tmp->exten);
13362          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
13363          ast_cli(fd, "Context: %s\n", tmp->context);
13364          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
13365          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
13366          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
13367          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
13368          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
13369          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
13370          ast_cli(fd, "Radio: %d\n", tmp->radio);
13371          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
13372          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)" : "");
13373          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)" : "");
13374          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)" : "");
13375          ast_cli(fd, "Confno: %d\n", tmp->confno);
13376          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
13377          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
13378          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
13379          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
13380          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
13381          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
13382          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
13383          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
13384          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
13385          if (tmp->master)
13386             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
13387          for (x = 0; x < MAX_SLAVES; x++) {
13388             if (tmp->slaves[x])
13389                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
13390          }
13391 
13392 #ifdef HAVE_OPENR2
13393          if (tmp->mfcr2) {
13394             char calldir[OR2_MAX_PATH];
13395             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
13396             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
13397             ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
13398             ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
13399             ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
13400             ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
13401             ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
13402             ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
13403             ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
13404             ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
13405             ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
13406             ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
13407 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13408             ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
13409             ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
13410 #endif
13411             ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
13412             ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
13413             ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
13414             ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
13415             ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
13416             ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
13417             ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
13418             ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
13419             ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
13420             ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
13421             ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
13422             ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
13423             ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
13424             ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
13425          }
13426 #endif
13427 
13428 #ifdef HAVE_PRI
13429          if (tmp->pri) {
13430             ast_cli(fd, "PRI Flags: ");
13431             if (tmp->resetting)
13432                ast_cli(fd, "Resetting ");
13433             if (tmp->call)
13434                ast_cli(fd, "Call ");
13435             if (tmp->bearer)
13436                ast_cli(fd, "Bearer ");
13437             if (tmp->allocated) {
13438                ast_cli(fd, "Allocated ");
13439             }
13440             ast_cli(fd, "\n");
13441             if (tmp->logicalspan) 
13442                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
13443             else
13444                ast_cli(fd, "PRI Logical Span: Implicit\n");
13445          }
13446 #endif
13447          memset(&ci, 0, sizeof(ci));
13448          ps.channo = tmp->channel;
13449          if (tmp->subs[SUB_REAL].dfd > -1) {
13450             memset(&ci, 0, sizeof(ci));
13451             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
13452                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
13453             }
13454 #ifdef DAHDI_GETCONFMUTE
13455             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
13456                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
13457             }
13458 #endif
13459             memset(&ps, 0, sizeof(ps));
13460             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
13461                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
13462             } else {
13463                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
13464             }
13465          }
13466          if (ISTRUNK(tmp)) {
13467             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
13468             if (!ast_strlen_zero(progzone))
13469                ast_cli(fd, "Progress Zone: %s\n", progzone);
13470             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
13471             if(tmp->busydetect) {
13472                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
13473                if(tmp->busytonelength > 0) {
13474                   ast_cli(fd, "Busy Pattern:\n");
13475                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
13476                   if (tmp->busyquietlength > 0) 
13477                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
13478                   else 
13479                      ast_cli(fd, " -- Detect Tone Only\n");
13480                   if(tmp->busyfuzziness > 0)
13481                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
13482                }
13483             }
13484          }
13485          ast_mutex_unlock(lock);
13486          return RESULT_SUCCESS;
13487       }
13488       tmp = tmp->next;
13489    }
13490    
13491    ast_cli(fd, "Unable to find given channel %d\n", channel);
13492    ast_mutex_unlock(lock);
13493    return RESULT_FAILURE;
13494 }

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

Definition at line 13245 of file chan_dahdi.c.

References ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_pri::crvs, dahdi_pvt::exten, FORMAT, FORMAT2, iflist, iflock, dahdi_pvt::language, dahdi_pri::lock, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, NUM_SPANS, pris, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

13246 {
13247 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
13248 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
13249    struct dahdi_pvt *tmp = NULL;
13250    char tmps[20] = "";
13251    ast_mutex_t *lock;
13252    struct dahdi_pvt *start;
13253 #ifdef HAVE_PRI
13254    int trunkgroup;
13255    struct dahdi_pri *pri = NULL;
13256    int x;
13257 #endif
13258 
13259    lock = &iflock;
13260    start = iflist;
13261 
13262 #ifdef HAVE_PRI
13263    if (argc == 4) {
13264       if ((trunkgroup = atoi(argv[3])) < 1)
13265          return RESULT_SHOWUSAGE;
13266       for (x = 0; x < NUM_SPANS; x++) {
13267          if (pris[x].trunkgroup == trunkgroup) {
13268             pri = pris + x;
13269             break;
13270          }
13271       }
13272       if (pri) {
13273          start = pri->crvs;
13274          lock = &pri->lock;
13275       } else {
13276          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13277          return RESULT_FAILURE;
13278       }
13279    } else
13280 #endif
13281    if (argc != 3)
13282       return RESULT_SHOWUSAGE;
13283 
13284    ast_mutex_lock(lock);
13285 #ifdef HAVE_PRI
13286    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
13287 #else
13288    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
13289 #endif   
13290    
13291    tmp = start;
13292    while (tmp) {
13293       if (tmp->channel > 0) {
13294          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
13295       } else
13296          ast_copy_string(tmps, "pseudo", sizeof(tmps));
13297       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
13298       tmp = tmp->next;
13299    }
13300    ast_mutex_unlock(lock);
13301    return RESULT_SUCCESS;
13302 #undef FORMAT
13303 #undef FORMAT2
13304 }

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

Definition at line 13527 of file chan_dahdi.c.

References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, DAHDI_NAME, errno, FORMAT, FORMAT2, LOG_WARNING, RESULT_FAILURE, RESULT_SUCCESS, and dahdi_pri::span.

13527                                                              {
13528    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
13529    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
13530 
13531    int span;
13532    int res;
13533    char alarms[50];
13534 
13535    int ctl;
13536    struct dahdi_spaninfo s;
13537 
13538    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
13539       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
13540       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
13541       return RESULT_FAILURE;
13542    }
13543    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
13544 
13545    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13546       s.spanno = span;
13547       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13548       if (res) {
13549          continue;
13550       }
13551       alarms[0] = '\0';
13552       if (s.alarms > 0) {
13553          if (s.alarms & DAHDI_ALARM_BLUE)
13554             strcat(alarms, "BLU/");
13555          if (s.alarms & DAHDI_ALARM_YELLOW)
13556             strcat(alarms, "YEL/");
13557          if (s.alarms & DAHDI_ALARM_RED)
13558             strcat(alarms, "RED/");
13559          if (s.alarms & DAHDI_ALARM_LOOPBACK)
13560             strcat(alarms, "LB/");
13561          if (s.alarms & DAHDI_ALARM_RECOVER)
13562             strcat(alarms, "REC/");
13563          if (s.alarms & DAHDI_ALARM_NOTOPEN)
13564             strcat(alarms, "NOP/");
13565          if (!strlen(alarms))
13566             strcat(alarms, "UUU/");
13567          if (strlen(alarms)) {
13568             /* Strip trailing / */
13569             alarms[strlen(alarms) - 1] = '\0';
13570          }
13571       } else {
13572          if (s.numchans)
13573             strcpy(alarms, "OK");
13574          else
13575             strcpy(alarms, "UNCONFIGURED");
13576       }
13577 
13578       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
13579    }
13580    close(ctl);
13581 
13582    return RESULT_SUCCESS;
13583 #undef FORMAT
13584 #undef FORMAT2
13585 }

static char* dahdi_sig2str ( int  sig  )  [static]

Definition at line 2198 of file chan_dahdi.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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

02199 {
02200    static char buf[256];
02201    switch (sig) {
02202    case SIG_EM:
02203       return "E & M Immediate";
02204    case SIG_EMWINK:
02205       return "E & M Wink";
02206    case SIG_EM_E1:
02207       return "E & M E1";
02208    case SIG_FEATD:
02209       return "Feature Group D (DTMF)";
02210    case SIG_FEATDMF:
02211       return "Feature Group D (MF)";
02212    case SIG_FEATDMF_TA:
02213       return "Feature Groud D (MF) Tandem Access";
02214    case SIG_FEATB:
02215       return "Feature Group B (MF)";
02216    case SIG_E911:
02217       return "E911 (MF)";
02218    case SIG_FGC_CAMA:
02219       return "FGC/CAMA (Dialpulse)";
02220    case SIG_FGC_CAMAMF:
02221       return "FGC/CAMA (MF)";
02222    case SIG_FXSLS:
02223       return "FXS Loopstart";
02224    case SIG_FXSGS:
02225       return "FXS Groundstart";
02226    case SIG_FXSKS:
02227       return "FXS Kewlstart";
02228    case SIG_FXOLS:
02229       return "FXO Loopstart";
02230    case SIG_FXOGS:
02231       return "FXO Groundstart";
02232    case SIG_FXOKS:
02233       return "FXO Kewlstart";
02234    case SIG_PRI:
02235       return "ISDN PRI";
02236    case SIG_MFCR2:
02237       return "MFC/R2";
02238    case SIG_SF:
02239       return "SF (Tone) Immediate";
02240    case SIG_SFWINK:
02241       return "SF (Tone) Wink";
02242    case SIG_SF_FEATD:
02243       return "SF (Tone) with Feature Group D (DTMF)";
02244    case SIG_SF_FEATDMF:
02245       return "SF (Tone) with Feature Group D (MF)";
02246    case SIG_SF_FEATB:
02247       return "SF (Tone) with Feature Group B (MF)";
02248    case SIG_GR303FXOKS:
02249       return "GR-303 with FXOKS";
02250    case SIG_GR303FXSKS:
02251       return "GR-303 with FXSKS";
02252    case 0:
02253       return "Pseudo";
02254    default:
02255       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02256       return buf;
02257    }
02258 }

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 13095 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_verbose(), iflist, iflock, dahdi_pvt::lock, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

13096 {
13097    struct dahdi_pvt *p;
13098 retry:
13099    ast_mutex_lock(&iflock);
13100     for (p = iflist; p; p = p->next) {
13101       ast_mutex_lock(&p->lock);
13102         if (p->owner && !p->restartpending) {
13103          if (ast_channel_trylock(p->owner)) {
13104             if (option_debug > 2)
13105                ast_verbose("Avoiding deadlock\n");
13106             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
13107             ast_mutex_unlock(&p->lock);
13108             ast_mutex_unlock(&iflock);
13109             goto retry;
13110          }
13111          if (option_debug > 2)
13112             ast_verbose("Softhanging up on %s\n", p->owner->name);
13113          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
13114          p->restartpending = 1;
13115          num_restart_pending++;
13116          ast_channel_unlock(p->owner);
13117       }
13118       ast_mutex_unlock(&p->lock);
13119     }
13120    ast_mutex_unlock(&iflock);
13121 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2479 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, LOG_DEBUG, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_answer(), and dahdi_handle_event().

02480 {
02481    int x;
02482    int res;
02483    if (p && p->echocancel && p->echotraining) {
02484       x = p->echotraining;
02485       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02486       if (res)
02487          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02488       else {
02489          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
02490       }
02491    } else
02492       ast_log(LOG_DEBUG, "No echo training requested\n");
02493 }

static void dahdi_unlink ( struct dahdi_pvt slave,
struct dahdi_pvt master,
int  needlock 
) [static]

Definition at line 4479 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_fixup().

04480 {
04481    /* Unlink a specific slave or all slaves/masters from a given master */
04482    int x;
04483    int hasslaves;
04484    if (!master)
04485       return;
04486    if (needlock) {
04487       ast_mutex_lock(&master->lock);
04488       if (slave) {
04489          while (ast_mutex_trylock(&slave->lock)) {
04490             DEADLOCK_AVOIDANCE(&master->lock);
04491          }
04492       }
04493    }
04494    hasslaves = 0;
04495    for (x = 0; x < MAX_SLAVES; x++) {
04496       if (master->slaves[x]) {
04497          if (!slave || (master->slaves[x] == slave)) {
04498             /* Take slave out of the conference */
04499             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04500             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04501             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04502             master->slaves[x]->master = NULL;
04503             master->slaves[x] = NULL;
04504          } else
04505             hasslaves = 1;
04506       }
04507       if (!hasslaves)
04508          master->inconference = 0;
04509    }
04510    if (!slave) {
04511       if (master->master) {
04512          /* Take master out of the conference */
04513          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04514          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04515          hasslaves = 0;
04516          for (x = 0; x < MAX_SLAVES; x++) {
04517             if (master->master->slaves[x] == master)
04518                master->master->slaves[x] = NULL;
04519             else if (master->master->slaves[x])
04520                hasslaves = 1;
04521          }
04522          if (!hasslaves)
04523             master->master->inconference = 0;
04524       }
04525       master->master = NULL;
04526    }
04527    update_conf(master);
04528    if (needlock) {
04529       if (slave)
04530          ast_mutex_unlock(&slave->lock);
04531       ast_mutex_unlock(&master->lock);
04532    }
04533 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 298 of file chan_dahdi.c.

Referenced by ss_thread().

00299 {
00300    int i, j = 0;
00301    i = DAHDI_IOMUX_SIGEVENT;
00302    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00303       return -1;
00304    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00305       return -1;
00306    return j;
00307 }

static int dahdi_wink ( struct dahdi_pvt p,
int  index 
) [static]

Definition at line 7215 of file chan_dahdi.c.

References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.

Referenced by ss_thread().

07216 {
07217    int j;
07218    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
07219    for (;;)
07220    {
07221          /* set bits of interest */
07222       j = DAHDI_IOMUX_SIGEVENT;
07223           /* wait for some happening */
07224       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07225          /* exit loop if we have it */
07226       if (j & DAHDI_IOMUX_SIGEVENT) break;
07227    }
07228      /* get the event info */
07229    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07230    return 0;
07231 }

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

Definition at line 6692 of file chan_dahdi.c.

References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, errno, ast_frame::frametype, dahdi_subchannel::linear, LOG_DEBUG, LOG_WARNING, my_dahdi_write(), option_debug, dahdi_pvt::owner, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

06693 {
06694    struct dahdi_pvt *p = ast->tech_pvt;
06695    int res;
06696    int index;
06697    index = dahdi_get_index(ast, p, 0);
06698    if (index < 0) {
06699       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06700       return -1;
06701    }
06702 
06703    /* Write a frame of (presumably voice) data */
06704    if (frame->frametype != AST_FRAME_VOICE) {
06705       if (frame->frametype != AST_FRAME_IMAGE)
06706          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06707       return 0;
06708    }
06709    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06710        (frame->subclass != AST_FORMAT_ULAW) &&
06711        (frame->subclass != AST_FORMAT_ALAW)) {
06712       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06713       return -1;
06714    }
06715    if (p->dialing) {
06716       if (option_debug)
06717          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06718       return 0;
06719    }
06720    if (!p->owner) {
06721       if (option_debug)
06722          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06723       return 0;
06724    }
06725    if (p->cidspill) {
06726       if (option_debug) {
06727          ast_log(LOG_DEBUG,
06728             "Dropping frame since I've still got a callerid spill on %s...\n",
06729             ast->name);
06730       }
06731       return 0;
06732    }
06733    /* Return if it's not valid data */
06734    if (!frame->data || !frame->datalen)
06735       return 0;
06736 
06737    if (frame->subclass == AST_FORMAT_SLINEAR) {
06738       if (!p->subs[index].linear) {
06739          p->subs[index].linear = 1;
06740          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06741          if (res)
06742             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06743       }
06744       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06745    } else {
06746       /* x-law already */
06747       if (p->subs[index].linear) {
06748          p->subs[index].linear = 0;
06749          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06750          if (res)
06751             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06752       }
06753       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06754    }
06755    if (res < 0) {
06756       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06757       return -1;
06758    } 
06759    return 0;
06760 }

static void destroy_all_channels ( void   )  [static]

Definition at line 3365 of file chan_dahdi.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, destroy_dahdi_pvt(), iflist, iflock, dahdi_pvt::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by __unload_module(), and dahdi_restart().

03366 {
03367    int x;
03368    struct dahdi_pvt *p, *pl;
03369 
03370    while (num_restart_pending) {
03371       usleep(1);
03372    }
03373 
03374    ast_mutex_lock(&iflock);
03375    /* Destroy all the interfaces and free their memory */
03376    p = iflist;
03377    while (p) {
03378       pl = p;
03379       p = p->next;
03380       x = pl->channel;
03381       /* Free associated memory */
03382       destroy_dahdi_pvt(&pl);
03383       if (option_verbose > 2) 
03384          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03385    }
03386    iflist = NULL;
03387    ifcount = 0;
03388    ast_mutex_unlock(&iflock);
03389 }

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

Definition at line 3315 of file chan_dahdi.c.

References destroy_dahdi_pvt(), iflist, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::prev, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().

03316 {
03317    int owned = 0;
03318    int i = 0;
03319 
03320    if (!now) {
03321       if (cur->owner) {
03322          owned = 1;
03323       }
03324 
03325       for (i = 0; i < 3; i++) {
03326          if (cur->subs[i].owner) {
03327             owned = 1;
03328          }
03329       }
03330       if (!owned) {
03331          if (prev) {
03332             prev->next = cur->next;
03333             if (prev->next)
03334                prev->next->prev = prev;
03335             else
03336                ifend = prev;
03337          } else {
03338             iflist = cur->next;
03339             if (iflist)
03340                iflist->prev = NULL;
03341             else
03342                ifend = NULL;
03343          }
03344          destroy_dahdi_pvt(&cur);
03345       }
03346    } else {
03347       if (prev) {
03348          prev->next = cur->next;
03349          if (prev->next)
03350             prev->next->prev = prev;
03351          else
03352             ifend = prev;
03353       } else {
03354          iflist = cur->next;
03355          if (iflist)
03356             iflist->prev = NULL;
03357          else
03358             ifend = NULL;
03359       }
03360       destroy_dahdi_pvt(&cur);
03361    }
03362    return 0;
03363 }

static void destroy_dahdi_pvt ( struct dahdi_pvt **  pvt  )  [static]

Definition at line 3295 of file chan_dahdi.c.

References ast_mutex_destroy(), ast_smdi_interface_unref(), dahdi_pvt::cidspill, dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, and dahdi_pvt::use_smdi.

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

03296 {
03297    struct dahdi_pvt *p = *pvt;
03298    /* Remove channel from the list */
03299    if (p->prev)
03300       p->prev->next = p->next;
03301    if (p->next)
03302       p->next->prev = p->prev;
03303 
03304    free(p->cidspill);
03305    if (p->use_smdi)
03306       ast_smdi_interface_unref(p->smdi_iface);
03307    ast_mutex_destroy(&p->lock);
03308    dahdi_close_sub(p, SUB_REAL);
03309    if (p->owner)
03310       p->owner->tech_pvt = NULL;
03311    free(p);
03312    *pvt = NULL;
03313 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 2189 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

02190 {
02191    if (dialplan == -1) {
02192       return("Dynamically set dialplan in ISDN");
02193    }
02194    return (pri_plan2str(dialplan));
02195 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 2005 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

02006 {
02007    if (isdigit(digit))
02008       return DAHDI_TONE_DTMF_BASE + (digit - '0');
02009    else if (digit >= 'A' && digit <= 'D')
02010       return DAHDI_TONE_DTMF_A + (digit - 'A');
02011    else if (digit >= 'a' && digit <= 'd')
02012       return DAHDI_TONE_DTMF_A + (digit - 'a');
02013    else if (digit == '*')
02014       return DAHDI_TONE_DTMF_s;
02015    else if (digit == '#')
02016       return DAHDI_TONE_DTMF_p;
02017    else
02018       return -1;
02019 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 4558 of file chan_dahdi.c.

References ast_dsp_set_features(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_bridge().

04559 {
04560 #ifdef DAHDI_TONEDETECT
04561    int val;
04562 #endif
04563 
04564    p->ignoredtmf = 1;
04565 
04566 #ifdef DAHDI_TONEDETECT
04567    val = 0;
04568    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04569 #endif      
04570    if (!p->hardwaredtmf && p->dsp) {
04571       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04572       ast_dsp_set_features(p->dsp, p->dsp_features);
04573    }
04574 }

static void* do_idle_thread ( void *  vchan  )  [static]

Definition at line 10782 of file chan_dahdi.c.

References ast_call(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_verbose(), ast_waitfor(), dahdi_pvt::channel, ast_channel::context, ast_channel::exten, ast_frame::frametype, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, LOG_WARNING, option_verbose, dahdi_pvt::pri, ast_channel::priority, ast_frame::subclass, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

Referenced by pri_dchannel().

10783 {
10784    struct ast_channel *chan = vchan;
10785    struct dahdi_pvt *pvt = chan->tech_pvt;
10786    struct ast_frame *f;
10787    char ex[80];
10788    /* Wait up to 30 seconds for an answer */
10789    int newms, ms = 30000;
10790    if (option_verbose > 2) 
10791       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
10792    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10793    if (ast_call(chan, ex, 0)) {
10794       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10795       ast_hangup(chan);
10796       return NULL;
10797    }
10798    while ((newms = ast_waitfor(chan, ms)) > 0) {
10799       f = ast_read(chan);
10800       if (!f) {
10801          /* Got hangup */
10802          break;
10803       }
10804       if (f->frametype == AST_FRAME_CONTROL) {
10805          switch (f->subclass) {
10806          case AST_CONTROL_ANSWER:
10807             /* Launch the PBX */
10808             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10809             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10810             chan->priority = 1;
10811             if (option_verbose > 3) 
10812                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10813             ast_pbx_run(chan);
10814             /* It's already hungup, return immediately */
10815             return NULL;
10816          case AST_CONTROL_BUSY:
10817             if (option_verbose > 3) 
10818                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
10819             break;
10820          case AST_CONTROL_CONGESTION:
10821             if (option_verbose > 3) 
10822                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
10823             break;
10824          };
10825       }
10826       ast_frfree(f);
10827       ms = newms;
10828    }
10829    /* Hangup the channel since nothing happend */
10830    ast_hangup(chan);
10831    return NULL;
10832 }

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

Definition at line 8729 of file chan_dahdi.c.

References ast_app_has_voicemail(), ast_callerid_vmwi_generate(), ast_calloc, ast_fdisset(), AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, AST_STATE_PRERING, ast_strlen_zero(), calc_energy(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_get_event(), dahdi_new(), dahdi_subchannel::dfd, dahdi_pvt::dtmfcid_delay, dahdi_pvt::dtmfcid_holdoff_state, errno, event2str(), free, handle_init_event(), iflist, iflock, last, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mailbox, MAX_CALLERID_SIZE, dahdi_pvt::msgstate, dahdi_pvt::next, dahdi_pvt::onhooktime, option_debug, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, ss_thread(), SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

08730 {
08731    int count, res, res2, spoint, pollres=0;
08732    struct dahdi_pvt *i;
08733    struct dahdi_pvt *last = NULL;
08734    struct dahdi_pvt *doomed;
08735    time_t thispass = 0, lastpass = 0;
08736    int found;
08737    char buf[1024];
08738    struct pollfd *pfds=NULL;
08739    int lastalloc = -1;
08740    /* This thread monitors all the frame relay interfaces which are not yet in use
08741       (and thus do not have a separate thread) indefinitely */
08742    /* From here on out, we die whenever asked */
08743 #if 0
08744    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08745       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08746       return NULL;
08747    }
08748    ast_log(LOG_DEBUG, "Monitor starting...\n");
08749 #endif
08750    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08751 
08752    for (;;) {
08753       /* Lock the interface list */
08754       ast_mutex_lock(&iflock);
08755       if (!pfds || (lastalloc != ifcount)) {
08756          if (pfds) {
08757             free(pfds);
08758             pfds = NULL;
08759          }
08760          if (ifcount) {
08761             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08762                ast_mutex_unlock(&iflock);
08763                return NULL;
08764             }
08765          }
08766          lastalloc = ifcount;
08767       }
08768       /* Build the stuff we're going to poll on, that is the socket of every
08769          dahdi_pvt that does not have an associated owner channel */
08770       count = 0;
08771       i = iflist;
08772       while (i) {
08773          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08774             if (!i->owner && !i->subs[SUB_REAL].owner) {
08775                /* This needs to be watched, as it lacks an owner */
08776                pfds[count].fd = i->subs[SUB_REAL].dfd;
08777                pfds[count].events = POLLPRI;
08778                pfds[count].revents = 0;
08779                /* Message waiting or r2 channels also get watched for reading */
08780                if (i->cidspill ||
08781                    (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
08782                   pfds[count].events |= POLLIN;
08783                }
08784                count++;
08785             }
08786          }
08787          i = i->next;
08788       }
08789       /* Okay, now that we know what to do, release the interface lock */
08790       ast_mutex_unlock(&iflock);
08791       
08792       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08793       pthread_testcancel();
08794       /* Wait at least a second for something to happen */
08795       res = poll(pfds, count, 1000);
08796       pthread_testcancel();
08797       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08798 
08799       /* Okay, poll has finished.  Let's see what happened.  */
08800       if (res < 0) {
08801          if ((errno != EAGAIN) && (errno != EINTR))
08802             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08803          continue;
08804       }
08805       /* Alright, lock the interface list again, and let's look and see what has
08806          happened */
08807       ast_mutex_lock(&iflock);
08808       found = 0;
08809       spoint = 0;
08810       lastpass = thispass;
08811       thispass = time(NULL);
08812       doomed = NULL;
08813       for (i = iflist;; i = i->next) {
08814          if (doomed) {
08815             int res;
08816             res = dahdi_destroy_channel_bynum(doomed->channel);
08817             if (!res) {
08818                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08819             }
08820             doomed = NULL;
08821          }
08822          if (!i) {
08823             break;
08824          }
08825          if (thispass != lastpass) {
08826             if (!found && ((i == last) || ((i == iflist) && !last))) {
08827                last = i;
08828                if (last) {
08829                   if (!last->cidspill
08830                      && !last->owner
08831                      && !ast_strlen_zero(last->mailbox)
08832                      && (thispass - last->onhooktime > 3)
08833                      && (last->sig & __DAHDI_SIG_FXO)) {
08834                      res = ast_app_has_voicemail(last->mailbox, NULL);
08835                      if (last->msgstate != res) {
08836                         int x;
08837                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08838                         x = DAHDI_FLUSH_BOTH;
08839                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08840                         if (res2)
08841                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08842                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08843                            /* Turn on on hook transfer for 4 seconds */
08844                            x = 4000;
08845                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08846                            last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08847                            last->cidpos = 0;
08848                            last->msgstate = res;
08849                            last->onhooktime = thispass;
08850                         }
08851                         found ++;
08852                      }
08853                   }
08854                   last = last->next;
08855                }
08856             }
08857          }
08858          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08859             if (i->radio && !i->owner)
08860             {
08861                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08862                if (res)
08863                {
08864                   if (option_debug)
08865                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08866                   /* Don't hold iflock while handling init events */
08867                   ast_mutex_unlock(&iflock);
08868                   doomed = handle_init_event(i, res);
08869                   ast_mutex_lock(&iflock);   
08870                }
08871                continue;
08872             }              
08873             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08874             if (pollres & POLLIN) {
08875                if (i->owner || i->subs[SUB_REAL].owner) {
08876 #ifdef HAVE_PRI
08877                   if (!i->pri)
08878 #endif                  
08879                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08880                   continue;
08881                }
08882                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08883                if (res > 0) {
08884                   /* We read some number of bytes.  Write an equal amount of data */
08885                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
08886                   if (i->cid_start == CID_START_DTMF_NOALERT) {
08887                      int energy;
08888                      struct timeval now;
08889                      /* State machine dtmfcid_holdoff_state allows for the line to settle
08890                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again
08891                      */
08892                      if (1 == i->dtmfcid_holdoff_state) {
08893                         gettimeofday(&i->dtmfcid_delay, NULL);
08894                         i->dtmfcid_holdoff_state = 2;
08895                      } else if (2 == i->dtmfcid_holdoff_state) {
08896                         gettimeofday(&now, NULL);
08897                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
08898                            i->dtmfcid_holdoff_state = 0;
08899                         }
08900                      } else {
08901                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
08902                         if (energy > dtmfcid_level) {
08903                            pthread_t threadid;
08904                            struct ast_channel *chan;
08905                            ast_mutex_unlock(&iflock);
08906                            chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08907                            if (!chan) {
08908                               ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08909                            } else {
08910                               pthread_attr_t attr;
08911                               pthread_attr_init(&attr);
08912                               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08913                               res = ast_pthread_create(&threadid, &attr, ss_thread, chan);
08914                               if (res) {
08915                                  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08916                               } else {
08917                                  i->dtmfcid_holdoff_state = 1;
08918                               }
08919                            }
08920                            ast_mutex_lock(&iflock);
08921                         }
08922                      }
08923                   }
08924                } else {
08925                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08926                }
08927             }
08928             if (pollres & POLLPRI) {
08929                if (i->owner || i->subs[SUB_REAL].owner) {
08930 #ifdef HAVE_PRI
08931                   if (!i->pri)
08932 #endif                  
08933                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08934                   continue;
08935                }
08936                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08937                if (option_debug)
08938                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08939                /* Don't hold iflock while handling init events */
08940                ast_mutex_unlock(&iflock);
08941                doomed = handle_init_event(i, res);
08942                ast_mutex_lock(&iflock);   
08943             }
08944          }
08945       }
08946       ast_mutex_unlock(&iflock);
08947    }
08948    /* Never reached */
08949    return NULL;
08950    
08951 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 4576 of file chan_dahdi.c.

References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_bridge().

04577 {
04578 #ifdef DAHDI_TONEDETECT
04579    int val;
04580 #endif
04581 
04582    if (p->channel == CHAN_PSEUDO)
04583       return;
04584 
04585    p->ignoredtmf = 0;
04586 
04587 #ifdef DAHDI_TONEDETECT
04588    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04589    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04590 #endif      
04591    if (!p->hardwaredtmf && p->dsp) {
04592       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04593       ast_dsp_set_features(p->dsp, p->dsp_features);
04594    }
04595 }

static char* event2str ( int  event  )  [static]

Definition at line 2179 of file chan_dahdi.c.

Referenced by __dahdi_exception(), dahdi_handle_event(), do_monitor(), pri_dchannel(), and ss_thread().

02180 {
02181    static char buf[256];
02182    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
02183       return events[event];
02184    sprintf(buf, "Event %d", event); /* safe */
02185    return buf;
02186 }

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

Definition at line 2544 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

02545 {
02546    int j;
02547    int k;
02548    float linear_gain = pow(10.0, gain / 20.0);
02549 
02550    switch (law) {
02551    case DAHDI_LAW_ALAW:
02552       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02553          if (gain) {
02554             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02555             if (k > 32767) k = 32767;
02556             if (k < -32767) k = -32767;
02557             g->rxgain[j] = AST_LIN2A(k);
02558          } else {
02559             g->rxgain[j] = j;
02560          }
02561       }
02562       break;
02563    case DAHDI_LAW_MULAW:
02564       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02565          if (gain) {
02566             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02567             if (k > 32767) k = 32767;
02568             if (k < -32767) k = -32767;
02569             g->rxgain[j] = AST_LIN2MU(k);
02570          } else {
02571             g->rxgain[j] = j;
02572          }
02573       }
02574       break;
02575    }
02576 }

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

Definition at line 2510 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

02511 {
02512    int j;
02513    int k;
02514    float linear_gain = pow(10.0, gain / 20.0);
02515 
02516    switch (law) {
02517    case DAHDI_LAW_ALAW:
02518       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02519          if (gain) {
02520             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02521             if (k > 32767) k = 32767;
02522             if (k < -32767) k = -32767;
02523             g->txgain[j] = AST_LIN2A(k);
02524          } else {
02525             g->txgain[j] = j;
02526          }
02527       }
02528       break;
02529    case DAHDI_LAW_MULAW:
02530       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02531          if (gain) {
02532             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02533             if (k > 32767) k = 32767;
02534             if (k < -32767) k = -32767;
02535             g->txgain[j] = AST_LIN2MU(k);
02536          } else {
02537             g->txgain[j] = j;
02538          }
02539       }
02540       break;
02541    }
02542 }

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

Definition at line 13685 of file chan_dahdi.c.

References dahdi_pvt::channel, iflist, and dahdi_pvt::next.

Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().

13686 {
13687    struct dahdi_pvt *p = iflist;
13688    while (p) {
13689       if (p->channel == channel) {
13690          break;
13691       }
13692       p = p->next;
13693    }
13694    return p;
13695 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 5068 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.

Referenced by __action_showchannels(), dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), handle_init_event(), and mkintf().

05069 {
05070    int res;
05071    struct dahdi_spaninfo zi;
05072 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
05073    /*
05074     * The conditional compilation is needed only in asterisk-1.4 for
05075     * backward compatibility with old zaptel drivers that don't have
05076     * a DAHDI_PARAMS.chan_alarms field.
05077     */
05078    struct dahdi_params params;
05079 #endif
05080 
05081    memset(&zi, 0, sizeof(zi));
05082    zi.spanno = p->span;
05083 
05084    /* First check for span alarms */
05085    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
05086       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05087       return 0;
05088    }
05089    if (zi.alarms != DAHDI_ALARM_NONE)
05090       return zi.alarms;
05091 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
05092    /* No alarms on the span. Check for channel alarms. */
05093    memset(&params, 0, sizeof(params));
05094    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
05095       return params.chan_alarms;
05096    /* ioctl failed */
05097    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05098 #endif
05099    return DAHDI_ALARM_NONE;
05100 }

static void handle_alarms ( struct dahdi_pvt p,
int  alarms 
) [static]

Definition at line 5202 of file chan_dahdi.c.

References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, LOG_WARNING, manager_event(), and dahdi_pvt::unknown_alarm.

Referenced by dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), handle_init_event(), and mkintf().

05203 {
05204    const char *alarm_str = alarm2str(alarms);
05205    
05206    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
05207     * doesn't know what to do with it.  Don't confuse users with log messages. */
05208    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
05209       p->unknown_alarm = 1;
05210       return;
05211    } else {
05212       p->unknown_alarm = 0;
05213    }
05214    
05215    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05216    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05217             "Alarm: %s\r\n"
05218             "Channel: %d\r\n",
05219             alarm_str, p->channel);
05220 }

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

Definition at line 13500 of file chan_dahdi.c.

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

13501 {
13502    int i, j;
13503    for (i = 0; i < num_cadence; i++) {
13504       char output[1024];
13505       char tmp[16], tmp2[64];
13506       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13507       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13508 
13509       for (j = 0; j < 16; j++) {
13510          if (cadences[i].ringcadence[j] == 0)
13511             break;
13512          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13513          if (cidrings[i] * 2 - 1 == j)
13514             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13515          else
13516             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13517          if (j != 0)
13518             strncat(output, ",", sizeof(output) - strlen(output) - 1);
13519          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13520       }
13521       ast_cli(fd,"%s\n",output);
13522    }
13523    return 0;
13524 }

static struct dahdi_pvt* handle_init_event ( struct dahdi_pvt i,
int  event 
) [static, read]

Definition at line 8512 of file chan_dahdi.c.

References ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, dahdi_pvt::cidspill, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), dahdi_subchannel::dfd, errno, EVENT_FLAG_SYSTEM, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, LOG_WARNING, manager_event(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::resetting, restore_conference(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_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, dahdi_pvt::subs, dahdi_pvt::unknown_alarm, and VERBOSE_PREFIX_2.

Referenced by do_monitor().

08513 {
08514    int res;
08515    pthread_t threadid;
08516    pthread_attr_t attr;
08517    struct ast_channel *chan;
08518    pthread_attr_init(&attr);
08519    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08520    /* Handle an event on a given channel for the monitor thread. */
08521    switch (event) {
08522    case DAHDI_EVENT_NONE:
08523    case DAHDI_EVENT_BITSCHANGED:
08524       break;
08525    case DAHDI_EVENT_WINKFLASH:
08526    case DAHDI_EVENT_RINGOFFHOOK:
08527       if (i->inalarm) break;
08528       if (i->radio) break;
08529       /* Got a ring/answer.  What kind of channel are we? */
08530       switch (i->sig) {
08531       case SIG_FXOLS:
08532       case SIG_FXOGS:
08533       case SIG_FXOKS:
08534          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08535          if (res && (errno == EBUSY))
08536             break;
08537 
08538          /* Cancel VMWI spill */
08539          free(i->cidspill);
08540          i->cidspill = NULL;
08541          restore_conference(i);
08542 
08543          if (i->immediate) {
08544             dahdi_enable_ec(i);
08545             /* The channel is immediately up.  Start right away */
08546             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08547             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08548             if (!chan) {
08549                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08550                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08551                if (res < 0)
08552                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08553             }
08554          } else {
08555             /* Check for callerid, digits, etc */
08556             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08557             if (chan) {
08558                if (has_voicemail(i))
08559                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08560                else
08561                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08562                if (res < 0) 
08563                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08564                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08565                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08566                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08567                   if (res < 0)
08568                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08569                   ast_hangup(chan);
08570                }
08571             } else
08572                ast_log(LOG_WARNING, "Unable to create channel\n");
08573          }
08574          break;
08575       case SIG_FXSLS:
08576       case SIG_FXSGS:
08577       case SIG_FXSKS:
08578             i->ringt = i->ringt_base;
08579             /* Fall through */
08580       case SIG_EMWINK:
08581       case SIG_FEATD:
08582       case SIG_FEATDMF:
08583       case SIG_FEATDMF_TA:
08584       case SIG_E911:
08585       case SIG_FGC_CAMA:
08586       case SIG_FGC_CAMAMF:
08587       case SIG_FEATB:
08588       case SIG_EM:
08589       case SIG_EM_E1:
08590       case SIG_SFWINK:
08591       case SIG_SF_FEATD:
08592       case SIG_SF_FEATDMF:
08593       case SIG_SF_FEATB:
08594       case SIG_SF:
08595             /* Check for callerid, digits, etc */
08596             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08597             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08598                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08599                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08600                if (res < 0)
08601                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08602                ast_hangup(chan);
08603             } else if (!chan) {
08604                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08605             }
08606             break;
08607       default:
08608          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08609          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08610          if (res < 0)
08611                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08612          pthread_attr_destroy(&attr);
08613          return NULL;
08614       }
08615       break;
08616    case DAHDI_EVENT_NOALARM:
08617       i->inalarm = 0;
08618 #if defined(HAVE_PRI)
08619       i->resetting = 0;
08620 #endif   /* defined(HAVE_PRI) */
08621       if (!i->unknown_alarm) {
08622          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08623          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08624                   "Channel: %d\r\n", i->channel);
08625       } else {
08626          i->unknown_alarm = 0;
08627       }
08628       break;
08629    case DAHDI_EVENT_ALARM:
08630       i->inalarm = 1;
08631 #if defined(HAVE_PRI)
08632       i->resetting = 0;
08633 #endif   /* defined(HAVE_PRI) */
08634       res = get_alarms(i);
08635       handle_alarms(i, res);
08636       /* fall thru intentionally */
08637    case DAHDI_EVENT_ONHOOK:
08638       if (i->radio)
08639          break;
08640       /* Back on hook.  Hang up. */
08641       switch (i->sig) {
08642       case SIG_FXOLS:
08643       case SIG_FXOGS:
08644       case SIG_FEATD:
08645       case SIG_FEATDMF:
08646       case SIG_FEATDMF_TA:
08647       case SIG_E911:
08648       case SIG_FGC_CAMA:
08649       case SIG_FGC_CAMAMF:
08650       case SIG_FEATB:
08651       case SIG_EM:
08652       case SIG_EM_E1:
08653       case SIG_EMWINK:
08654       case SIG_SF_FEATD:
08655       case SIG_SF_FEATDMF:
08656       case SIG_SF_FEATB:
08657       case SIG_SF:
08658       case SIG_SFWINK:
08659       case SIG_FXSLS:
08660       case SIG_FXSGS:
08661       case SIG_FXSKS:
08662       case SIG_GR303FXSKS:
08663          dahdi_disable_ec(i);
08664          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08665          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08666          break;
08667       case SIG_GR303FXOKS:
08668       case SIG_FXOKS:
08669          dahdi_disable_ec(i);
08670          /* Diddle the battery for the zhone */
08671 #ifdef ZHONE_HACK
08672          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08673          usleep(1);
08674 #endif         
08675          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08676          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08677          break;
08678       case SIG_PRI:
08679          dahdi_disable_ec(i);
08680          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08681          break;
08682       default:
08683          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08684          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08685          pthread_attr_destroy(&attr);
08686          return NULL;
08687       }
08688       break;
08689    case DAHDI_EVENT_POLARITY:
08690       switch (i->sig) {
08691       case SIG_FXSLS:
08692       case SIG_FXSKS:
08693       case SIG_FXSGS:
08694          /* We have already got a PR before the channel was 
08695             created, but it wasn't handled. We need polarity 
08696             to be REV for remote hangup detection to work. 
08697             At least in Spain */
08698          if (i->hanguponpolarityswitch)
08699             i->polarity = POLARITY_REV;
08700 
08701          if (i->cid_start == CID_START_POLARITY) {
08702             i->polarity = POLARITY_REV;
08703             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08704                    "CID detection on channel %d\n",
08705                    i->channel);
08706             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08707             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08708                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08709             }
08710          }
08711          break;
08712       default:
08713          ast_log(LOG_WARNING, "handle_init_event detected "
08714             "polarity reversal on non-FXO (SIG_FXS) "
08715             "interface %d\n", i->channel);
08716       }
08717       break;
08718    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
08719       ast_log(LOG_NOTICE, 
08720             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
08721             i->channel);
08722       pthread_attr_destroy(&attr);
08723       return i;
08724    }
08725    pthread_attr_destroy(&attr);
08726    return NULL;
08727 }

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

Definition at line 12902 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), dahdi_pvt::channel, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

12903 {
12904    struct dahdi_pvt *p = NULL;
12905    int channo = 0;
12906    if (argc < 4) {
12907       return RESULT_SHOWUSAGE;
12908    }
12909    channo = (argc == 5) ? atoi(argv[4]) : -1;
12910    ast_mutex_lock(&iflock);
12911    p = iflist;
12912    while (p) {
12913       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12914          p = p->next;
12915          continue;
12916       }
12917       if ((channo != -1) && (p->channel != channo )) {
12918          p = p->next;
12919          continue;
12920       }
12921       if (ast_true(argv[3])) {
12922          openr2_chan_enable_call_files(p->r2chan);
12923       } else {
12924          openr2_chan_disable_call_files(p->r2chan);
12925       }
12926       if (channo != -1) {
12927          if (ast_true(argv[3])) {
12928             ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
12929          } else {
12930             ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
12931          }
12932          break;
12933       } else {
12934          p = p->next;
12935       }
12936    }
12937    if ((channo != -1) && !p) {
12938       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12939    }
12940    if (channo == -1) {
12941       if (ast_true(argv[3])) {
12942          ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
12943       } else {
12944          ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
12945       }  
12946    }
12947    ast_mutex_unlock(&iflock);
12948    return RESULT_SUCCESS;
12949 }  

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

Definition at line 12986 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, iflist, iflock, dahdi_pvt::lock, dahdi_pvt::mfcr2block, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

12987 {
12988    struct dahdi_pvt *p = NULL;
12989    int channo = 0;
12990    channo = (argc == 4) ? atoi(argv[3]) : -1;
12991    ast_mutex_lock(&iflock);
12992    p = iflist;
12993    while (p) {
12994       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12995          p = p->next;
12996          continue;
12997       }
12998       if ((channo != -1) && (p->channel != channo )) {
12999          p = p->next;
13000          continue;
13001       }
13002       if (!openr2_chan_set_blocked(p->r2chan)) {
13003          ast_mutex_lock(&p->lock);
13004          p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
13005          ast_mutex_unlock(&p->lock);
13006       } else {
13007          ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
13008       }
13009       if (channo != -1) {
13010          break;
13011       } else {
13012          p = p->next;
13013       }
13014    }
13015    if ((channo != -1) && !p) {
13016       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
13017    }
13018    ast_mutex_unlock(&iflock);
13019    return RESULT_SUCCESS;
13020 }

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

Definition at line 12843 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, dahdi_pvt::channel, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

12844 {
12845    struct dahdi_pvt *p = NULL;
12846    int channo = 0;
12847    char *toklevel = NULL;
12848    char *saveptr = NULL;
12849    char *logval = NULL;
12850    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
12851    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
12852    if (argc < 4) {
12853       return RESULT_SHOWUSAGE;
12854    }
12855    channo = (argc == 5) ? atoi(argv[4]) : -1;
12856    logval = ast_strdupa(argv[3]);
12857    toklevel = strtok_r(logval, ",", &saveptr);
12858    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
12859       ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
12860       return RESULT_FAILURE;
12861    } else if (OR2_LOG_NOTHING == tmplevel) {
12862       loglevel = tmplevel;
12863    } else {
12864       loglevel |= tmplevel;
12865       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
12866          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
12867             ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
12868             continue;
12869          }
12870          loglevel |= tmplevel;
12871       }
12872    }
12873    ast_mutex_lock(&iflock);
12874    p = iflist;
12875    while (p) {
12876       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12877          p = p->next;
12878          continue;
12879       }
12880       if ((channo != -1) && (p->channel != channo )) {
12881          p = p->next;
12882          continue;
12883       }
12884       openr2_chan_set_log_level(p->r2chan, loglevel);
12885       if (channo != -1) {
12886          ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
12887          break;
12888       } else {
12889          p = p->next;
12890       }
12891    }
12892    if ((channo != -1) && !p) {
12893       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12894    }
12895    if (channo == -1) {
12896       ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
12897    }
12898    ast_mutex_unlock(&iflock);
12899    return RESULT_SUCCESS;
12900 }

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

Definition at line 12951 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, iflist, iflock, dahdi_pvt::lock, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

12952 {
12953    struct dahdi_pvt *p = NULL;
12954    int channo = 0;
12955    channo = (argc == 4) ? atoi(argv[3]) : -1;
12956    ast_mutex_lock(&iflock);
12957    p = iflist;
12958    while (p) {
12959       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12960          p = p->next;
12961          continue;
12962       }
12963       if ((channo != -1) && (p->channel != channo )) {
12964          p = p->next;
12965          continue;
12966       }
12967       if (!openr2_chan_set_idle(p->r2chan)) {
12968          ast_mutex_lock(&p->lock);
12969          p->mfcr2call = 0;
12970          p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
12971          ast_mutex_unlock(&p->lock);
12972       }
12973       if (channo != -1) {
12974          break;
12975       } else {
12976          p = p->next;
12977       }
12978    }
12979    if ((channo != -1) && !p) {
12980       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
12981    }
12982    ast_mutex_unlock(&iflock);
12983    return RESULT_SUCCESS;
12984 }

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

Definition at line 12768 of file chan_dahdi.c.

References ast_cli(), ast_get_group(), ast_have_common_group(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::context, FORMAT, dahdi_pvt::group, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

12769 {
12770 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
12771    int filtertype = 0;
12772    int targetnum = 0;
12773    char channo[5];
12774    char anino[5];
12775    char dnisno[5];
12776    struct dahdi_pvt *p;
12777    openr2_context_t *r2context;
12778    openr2_variant_t r2variant;
12779    if (!((argc == 3) || (argc == 5))) {
12780       return RESULT_SHOWUSAGE;
12781    }
12782    if (argc == 5) {
12783       if (!strcasecmp(argv[3], "group")) {
12784          targetnum = atoi(argv[4]);
12785          if ((targetnum < 0) || (targetnum > 63))
12786             return RESULT_SHOWUSAGE;
12787          targetnum = 1 << targetnum;
12788          filtertype = 1;
12789       } else if (!strcasecmp(argv[3], "context")) {
12790          filtertype = 2;
12791       } else {
12792          return RESULT_SHOWUSAGE;
12793       }
12794    }
12795    ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
12796    ast_mutex_lock(&iflock);
12797    p = iflist;
12798    while (p) {
12799       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
12800          p = p->next;
12801          continue;
12802       }
12803       if (filtertype) {
12804          char buf[12];
12805          ast_group_t targetgrp;
12806 
12807          switch(filtertype) {
12808          case 1: /* mfcr2 show channels group <group> */
12809             sprintf(buf, "%d", targetnum);
12810             memset(&targetgrp, 0, sizeof(targetgrp));
12811             ast_get_group(&targetgrp, buf);
12812             if (!ast_have_common_group(&p->group, &targetgrp)) {
12813                p = p->next;
12814                continue;
12815             }
12816             break;
12817          case 2: /* mfcr2 show channels context <context> */
12818             if (strcasecmp(p->context, argv[4])) {
12819                p= p->next;
12820                continue;
12821             }
12822             break;
12823          default:
12824             ;
12825          }
12826       }
12827       r2context = openr2_chan_get_context(p->r2chan);
12828       r2variant = openr2_context_get_variant(r2context);
12829       snprintf(channo, sizeof(channo), "%d", p->channel);
12830       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
12831       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
12832       ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 
12833             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",  
12834             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
12835             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
12836       p = p->next;
12837    }
12838    ast_mutex_unlock(&iflock);
12839    return RESULT_SUCCESS;
12840 #undef FORMAT
12841 }

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

Definition at line 12750 of file chan_dahdi.c.

References ast_cli(), country, FORMAT, name, RESULT_FAILURE, and RESULT_SUCCESS.

12751 {
12752 #define FORMAT "%4s %40s\n"
12753    int numvariants = 0;
12754    int i;
12755    const openr2_variant_entry_t *variants;
12756    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
12757       ast_cli(fd, "Failed to get list of variants.\n");
12758       return RESULT_FAILURE;
12759    }
12760    ast_cli(fd, FORMAT, "Variant Code", "Country");
12761    for (i = 0; i < numvariants; i++) {
12762       ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
12763    }
12764    return RESULT_SUCCESS;
12765 #undef FORMAT
12766 }  

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

Definition at line 12744 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

12745 {
12746    ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
12747    return RESULT_SUCCESS;
12748 }

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

Definition at line 12495 of file chan_dahdi.c.

References ast_cli(), NUM_DCHANS, NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

12496 {
12497    int span;
12498    int x;
12499    if (argc < 4) {
12500       return RESULT_SHOWUSAGE;
12501    }
12502    span = atoi(argv[3]);
12503    if ((span < 1) || (span > NUM_SPANS)) {
12504       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
12505       return RESULT_SUCCESS;
12506    }
12507    if (!pris[span-1].pri) {
12508       ast_cli(fd, "No PRI running on span %d\n", span);
12509       return RESULT_SUCCESS;
12510    }
12511    for (x = 0; x < NUM_DCHANS; x++) {
12512       if (pris[span-1].dchans[x])
12513          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12514                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12515                                                PRI_DEBUG_Q921_STATE);
12516    }
12517    ast_cli(fd, "Enabled debugging on span %d\n", span);
12518    return RESULT_SUCCESS;
12519 }

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

Definition at line 12523 of file chan_dahdi.c.

References ast_cli(), NUM_DCHANS, NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

12524 {
12525    int span;
12526    int x;
12527    if (argc < 5)
12528       return RESULT_SHOWUSAGE;
12529    span = atoi(argv[4]);
12530    if ((span < 1) || (span > NUM_SPANS)) {
12531       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
12532       return RESULT_SUCCESS;
12533    }
12534    if (!pris[span-1].pri) {
12535       ast_cli(fd, "No PRI running on span %d\n", span);
12536       return RESULT_SUCCESS;
12537    }
12538    for (x = 0; x < NUM_DCHANS; x++) {
12539       if (pris[span-1].dchans[x])
12540          pri_set_debug(pris[span-1].dchans[x], 0);
12541    }
12542    ast_cli(fd, "Disabled debugging on span %d\n", span);
12543    return RESULT_SUCCESS;
12544 }

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

Definition at line 12546 of file chan_dahdi.c.

References ast_cli(), NUM_DCHANS, NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

12547 {
12548    int span;
12549    int x;
12550    if (argc < 5)
12551       return RESULT_SHOWUSAGE;
12552    span = atoi(argv[4]);
12553    if ((span < 1) || (span > NUM_SPANS)) {
12554       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
12555       return RESULT_SUCCESS;
12556    }
12557    if (!pris[span-1].pri) {
12558       ast_cli(fd, "No PRI running on span %d\n", span);
12559       return RESULT_SUCCESS;
12560    }
12561    for (x = 0; x < NUM_DCHANS; x++) {
12562       if (pris[span-1].dchans[x])
12563          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12564                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12565                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12566    }
12567    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12568    return RESULT_SUCCESS;
12569 }

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

Definition at line 12448 of file chan_dahdi.c.

References ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), pridebugfdlock, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

12449 {
12450    int myfd;
12451 
12452    if (!strncasecmp(argv[1], "set", 3)) {
12453       if (argc < 5) 
12454          return RESULT_SHOWUSAGE;
12455 
12456       if (ast_strlen_zero(argv[4]))
12457          return RESULT_SHOWUSAGE;
12458 
12459       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
12460       if (myfd < 0) {
12461          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
12462          return RESULT_SUCCESS;
12463       }
12464 
12465       ast_mutex_lock(&pridebugfdlock);
12466 
12467       if (pridebugfd >= 0)
12468          close(pridebugfd);
12469 
12470       pridebugfd = myfd;
12471       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
12472       
12473       ast_mutex_unlock(&pridebugfdlock);
12474 
12475       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
12476    } else {
12477       /* Assume it is unset */
12478       ast_mutex_lock(&pridebugfdlock);
12479       close(pridebugfd);
12480       pridebugfd = -1;
12481       ast_cli(fd, "PRI debug output to file disabled\n");
12482       ast_mutex_unlock(&pridebugfdlock);
12483    }
12484 
12485    return RESULT_SUCCESS;
12486 }

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

Definition at line 12654 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_DCHANS, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.

12655 {
12656    int x;
12657    int span;
12658    int count=0;
12659    int debug=0;
12660 
12661    for (span = 0; span < NUM_SPANS; span++) {
12662            if (pris[span].pri) {
12663          for (x = 0; x < NUM_DCHANS; x++) {
12664             debug = 0;
12665                if (pris[span].dchans[x]) {
12666                   debug = pri_get_debug(pris[span].dchans[x]);
12667                ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
12668                count++;
12669             }
12670          }
12671       }
12672 
12673    }
12674    ast_mutex_lock(&pridebugfdlock);
12675    if (pridebugfd >= 0) 
12676       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
12677    ast_mutex_unlock(&pridebugfdlock);
12678        
12679    if (!count) 
12680       ast_cli(fd, "No debug set or no PRI running\n");
12681    return RESULT_SUCCESS;
12682 }

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

Definition at line 12613 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), build_status(), DAHDI_OVERLAPDIAL_INCOMING, free, lock, NUM_DCHANS, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

12614 {
12615    int span;
12616    int x;
12617    char status[256];
12618    if (argc < 4)
12619       return RESULT_SHOWUSAGE;
12620    span = atoi(argv[3]);
12621    if ((span < 1) || (span > NUM_SPANS)) {
12622       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
12623       return RESULT_SUCCESS;
12624    }
12625    if (!pris[span-1].pri) {
12626       ast_cli(fd, "No PRI running on span %d\n", span);
12627       return RESULT_SUCCESS;
12628    }
12629    for (x = 0; x < NUM_DCHANS; x++) {
12630       if (pris[span-1].dchannels[x]) {
12631 #ifdef PRI_DUMP_INFO_STR
12632          char *info_str = NULL;
12633 #endif
12634          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12635          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12636          ast_cli(fd, "Status: %s\n", status);
12637          ast_mutex_lock(&pris[span - 1].lock);
12638 #ifdef PRI_DUMP_INFO_STR
12639          info_str = pri_dump_info_str(pris[span-1].pri);
12640          if (info_str) {
12641             ast_cli(fd, "%s", info_str);
12642             free(info_str);
12643          }
12644 #else
12645          pri_dump_info(pris[span-1].pri);
12646 #endif
12647          ast_mutex_unlock(&pris[span - 1].lock);
12648          ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12649       }
12650    }
12651    return RESULT_SUCCESS;
12652 }

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

Definition at line 12592 of file chan_dahdi.c.

References ast_cli(), build_status(), NUM_DCHANS, NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

12593 {
12594    int span;
12595    int x;
12596    char status[256];
12597    if (argc != 3)
12598       return RESULT_SHOWUSAGE;
12599 
12600    for (span = 0; span < NUM_SPANS; span++) {
12601       if (pris[span].pri) {
12602          for (x = 0; x < NUM_DCHANS; x++) {
12603             if (pris[span].dchannels[x]) {
12604                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12605                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12606             }
12607          }
12608       }
12609    }
12610    return RESULT_SUCCESS;
12611 }

static int handle_pri_version ( int  fd,
int  agc,
char *  argv[] 
) [static]

Definition at line 12489 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

12489                                                              {
12490    ast_cli(fd, "libpri version: %s\n", pri_get_version());
12491    return RESULT_SUCCESS;
12492 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 2742 of file chan_dahdi.c.

References ast_app_has_voicemail(), and dahdi_pvt::mailbox.

Referenced by dahdi_handle_event(), and handle_init_event().

02743 {
02744 
02745    return ast_app_has_voicemail(p->mailbox, NULL);
02746 }

static void init_mfcr2_globals ( void   )  [static]

Definition at line 1343 of file chan_dahdi.c.

References AST_PTHREADT_NULL, dahdi_mfcr2::master, NUM_SPANS, and r2links.

Referenced by dahdi_restart(), and load_module().

01344 {
01345    int r;
01346    mfcr2_cur_context_index = 0;
01347    mfcr2_cur_variant = OR2_VAR_UNKNOWN;
01348    mfcr2_cur_mfback_timeout = -1;
01349    mfcr2_cur_metering_pulse_timeout = -1;
01350    mfcr2_cur_max_ani = 10;
01351    mfcr2_cur_max_dnis = 4;
01352    mfcr2_cur_get_ani_first = -1;
01353 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01354    mfcr2_cur_dtmf_dialing = -1;
01355    mfcr2_cur_dtmf_detection = -1;
01356    mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
01357    mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
01358 #endif
01359    mfcr2_cur_skip_category = -1;
01360    mfcr2_cur_call_files = 0;
01361    mfcr2_cur_allow_collect_calls = 0;
01362    mfcr2_cur_forced_release = 0;
01363    mfcr2_cur_double_answer = 0;
01364    mfcr2_cur_immediate_accept = -1;
01365    mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
01366    mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
01367    memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir));
01368    memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file));
01369    memset(r2links, 0, sizeof(r2links));
01370    for (r = 0; r < NUM_SPANS; r++) {
01371       r2links[r].master = AST_PTHREADT_NULL;
01372    }
01373 }

static int isourconf ( struct dahdi_pvt p,
struct dahdi_subchannel c 
) [static]

Definition at line 2300 of file chan_dahdi.c.

References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.

Referenced by conf_del().

02301 {
02302    /* If they're listening to our channel, they're ours */  
02303    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02304       return 1;
02305    /* If they're a talker on our (allocated) conference, they're ours */
02306    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02307       return 1;
02308    return 0;
02309 }

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

Definition at line 2330 of file chan_dahdi.c.

References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_pvt::law, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.

Referenced by update_conf().

02331 {
02332    int x;
02333    int useslavenative;
02334    struct dahdi_pvt *slave = NULL;
02335    /* Start out optimistic */
02336    useslavenative = 1;
02337    /* Update conference state in a stateless fashion */
02338    for (x = 0; x < 3; x++) {
02339       /* Any three-way calling makes slave native mode *definitely* out
02340          of the question */
02341       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02342          useslavenative = 0;
02343    }
02344    /* If we don't have any 3-way calls, check to see if we have
02345       precisely one slave */
02346    if (useslavenative) {
02347       for (x = 0; x < MAX_SLAVES; x++) {
02348          if (p->slaves[x]) {
02349             if (slave) {
02350                /* Whoops already have a slave!  No 
02351                   slave native and stop right away */
02352                slave = NULL;
02353                useslavenative = 0;
02354                break;
02355             } else {
02356                /* We have one slave so far */
02357                slave = p->slaves[x];
02358             }
02359          }
02360       }
02361    }
02362    /* If no slave, slave native definitely out */
02363    if (!slave)
02364       useslavenative = 0;
02365    else if (slave->law != p->law) {
02366       useslavenative = 0;
02367       slave = NULL;
02368    }
02369    if (out)
02370       *out = slave;
02371    return useslavenative;
02372 }

static int load_module ( void   )  [static]

Definition at line 15111 of file chan_dahdi.c.

References __unload_module(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application(), ast_string_field_init, ast_string_field_set, CHAN_DAHDI_PLUS_ZAP_MODE, dahdi_accept_r2_call_exec(), dahdi_chan_mode, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), init_mfcr2_globals(), inuse, local_astman_register, lock, LOG_ERROR, dahdi_pri::master, name, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, setup_dahdi(), ast_channel_tech::type, zap_accept_r2_call_exec(), and zap_send_keypad_facility_exec().

15112 {
15113    int res;
15114 
15115 #ifdef HAVE_PRI
15116    int y,i;
15117    memset(pris, 0, sizeof(pris));
15118    for (y = 0; y < NUM_SPANS; y++) {
15119       ast_mutex_init(&pris[y].lock);
15120       pris[y].offset = -1;
15121       pris[y].master = AST_PTHREADT_NULL;
15122       for (i = 0; i < NUM_DCHANS; i++)
15123          pris[y].fds[i] = -1;
15124    }
15125    pri_set_error(dahdi_pri_error);
15126    pri_set_message(dahdi_pri_message);
15127    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15128       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15129          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15130    }
15131    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
15132       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
15133 #endif
15134 
15135 #ifdef HAVE_OPENR2
15136    init_mfcr2_globals();
15137    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15138       ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
15139          dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
15140    }
15141    ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
15142       zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
15143 #endif
15144 
15145    if ((res = setup_dahdi(0))) {
15146       return AST_MODULE_LOAD_DECLINE;
15147    }
15148    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
15149       chan_tech = &dahdi_tech;
15150    } else {
15151       chan_tech = &zap_tech;
15152    }
15153    if (ast_channel_register(chan_tech)) {
15154       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
15155       __unload_module();
15156       return -1;
15157    }
15158 #ifdef HAVE_PRI
15159    ast_string_field_init(&inuse, 16);
15160    ast_string_field_set(&inuse, name, "GR-303InUse");
15161    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
15162 #endif   
15163 
15164 #ifdef HAVE_OPENR2
15165    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
15166 #endif
15167 
15168    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
15169    
15170    memset(round_robin, 0, sizeof(round_robin));
15171    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
15172    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
15173    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
15174    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
15175    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
15176    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
15177    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
15178 
15179    ast_cond_init(&ss_thread_complete, NULL);
15180 
15181    return res;
15182 }

static struct dahdi_mfcr2* mfcr2_get_context ( int  id  )  [static, read]

Definition at line 8985 of file chan_dahdi.c.

References ast_log(), LOG_ERROR, and r2links.

Referenced by mkintf().

08986 {
08987    if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08988       ast_log(LOG_ERROR, "No more R2 links available!.\n");
08989       return NULL;
08990    }
08991    return &r2links[id];
08992 }

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

Definition at line 10302 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, dahdi_subchannel::dfd, errno, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, dahdi_pvt::r2chan, SUB_REAL, and dahdi_pvt::subs.

Referenced by setup_dahdi().

10303 {
10304    struct dahdi_pvt *p;
10305    struct dahdi_mfcr2 *mfcr2 = data;
10306    /* we should be using pthread_key_create
10307       and allocate pollers dynamically.
10308       I think do_monitor() could be leaking, since it
10309       could be cancelled at any time and is not
10310       using thread keys, why?, */
10311    struct pollfd pollers[mfcr2->numchans];
10312    int maxsleep = 20;
10313    int res = 0;
10314    int i = 0;
10315    int pollsize = 0;
10316    int oldstate = 0;
10317    int was_idle = 0;
10318    int quit_loop = 0;
10319    /* now that we're ready to get calls, unblock our side and
10320       get current line state */
10321    for (i = 0; i < mfcr2->numchans; i++) {
10322       p = mfcr2->pvts[i];
10323       pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
10324       if (openr2_chan_set_idle(p->r2chan)) {
10325          ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
10326       } else {
10327          ast_mutex_lock(&p->lock);
10328          mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
10329          mfcr2->pvts[i]->mfcr2call = 0;
10330          ast_mutex_unlock(&p->lock);
10331       }
10332       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
10333    }
10334    while(1) {
10335       /* we trust here that the mfcr2 channel list will not ever change once
10336          the module is loaded */
10337       pollsize = 0;
10338       for (i = 0; i < mfcr2->numchans; i++) {
10339          pollers[i].events = 0;
10340          pollers[i].revents = 0;
10341          if (mfcr2->pvts[i]->owner) {
10342             continue;
10343          }
10344          if (!mfcr2->pvts[i]->r2chan) {
10345             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
10346             quit_loop = 1;
10347             break;
10348          }
10349          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
10350          pollers[i].events = POLLIN | POLLPRI;
10351          pollsize++;
10352       }
10353       if (quit_loop) {
10354          break;
10355       }
10356 
10357       if (pollsize == 0) {
10358          if (!was_idle) {
10359             ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
10360             was_idle = 1;
10361          }
10362          poll(NULL, 0, maxsleep);
10363          continue;
10364       }
10365       was_idle = 0;
10366 
10367       /* probably poll() is a valid cancel point, lets just be on the safe side
10368          by calling pthread_testcancel */
10369       pthread_testcancel();
10370       res = poll(pollers, mfcr2->numchans, maxsleep);
10371       pthread_testcancel();
10372       if ((res < 0) && (errno != EINTR)) {
10373          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
10374          break;
10375       } 
10376       /* do we want to allow to cancel while processing events? */
10377       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
10378       for (i = 0; i < mfcr2->numchans; i++) {
10379          if ((pollers[i].revents & POLLPRI) || (pollers[i].revents & POLLIN)) {
10380             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
10381          }
10382       }
10383       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
10384    }
10385    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
10386    return 0;
10387 }

static struct dahdi_pvt* mkintf ( int  channel,
const struct dahdi_chan_conf conf,
struct dahdi_pri pri,
int  reloading 
) [static, read]

Definition at line 9118 of file chan_dahdi.c.

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_calloc, ast_config_AST_LOG_DIR, ast_copy_string(), ast_dsp_digitmode(), ast_log(), ast_mutex_init(), ast_smdi_interface_find(), ast_strlen_zero(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_SMDI, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, dahdi_pvt::cid_ton, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), DAHDI_R2_LOCAL_BLOCK, dahdi_r2_on_chan_log(), DAHDI_R2_REMOTE_BLOCK, dahdi_set_hook(), dahdi_pvt::dahditrcallerid, dahdi_pvt::defcontext, dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, dahdi_pri::dialplan, dialplan2str(), drings, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::firstradio, free, get_alarms(), dahdi_pvt::group, handle_alarms(), dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, iflist, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::language, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pri::localprefix, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::mailbox, MAX_CHANNELS, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_category, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_forced_release, mfcr2_get_context(), dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, dahdi_pri::nationalprefix, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, NUM_SPANS, dahdi_mfcr2::numchans, dahdi_pri::numchans, offset, dahdi_pvt::onhooktime, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_chan_conf::pri, pri_is_up(), pri_resolve_span(), dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, dahdi_pri::privateprefix, dahdi_pvt::propconfno, dahdi_mfcr2::protocol_context, dahdi_pvt::pulse, dahdi_mfcr2::pvts, dahdi_pri::pvts, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pri::resetinterval, dahdi_pvt::resetting, dahdi_pvt::restrictcid, dahdi_pvt::ringt_base, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::silencethreshold, dahdi_pvt::smdi_iface, dahdi_chan_conf::smdi_port, dahdi_pvt::span, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pvt::unknown_alarm, dahdi_pri::unknownprefix, update_conf(), dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.

Referenced by build_channels(), and process_dahdi().

09119 {
09120    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
09121    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
09122    char fn[80];
09123 #if 1
09124    struct dahdi_bufferinfo bi;
09125 #endif
09126    int res;
09127    int span=0;
09128    int here = 0;
09129    int x;
09130    struct dahdi_pvt **wlist;
09131    struct dahdi_pvt **wend;
09132    struct dahdi_params p;
09133 
09134    wlist = &iflist;
09135    wend = &ifend;
09136 
09137 #ifdef HAVE_PRI
09138    if (pri) {
09139       wlist = &pri->crvs;
09140       wend = &pri->crvend;
09141    }
09142 #endif
09143 
09144    tmp2 = *wlist;
09145    prev = NULL;
09146 
09147    while (tmp2) {
09148       if (!tmp2->destroy) {
09149          if (tmp2->channel == channel) {
09150             tmp = tmp2;
09151             here = 1;
09152             break;
09153          }
09154          if (tmp2->channel > channel) {
09155             break;
09156          }
09157       }
09158       prev = tmp2;
09159       tmp2 = tmp2->next;
09160    }
09161 
09162    if (!here && reloading != 1) {
09163       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
09164          if (tmp)
09165             free(tmp);
09166          return NULL;
09167       }
09168       ast_mutex_init(&tmp->lock);
09169       ifcount++;
09170       for (x = 0; x < 3; x++)
09171          tmp->subs[x].dfd = -1;
09172       tmp->channel = channel;
09173       tmp->priindication_oob = conf->chan.priindication_oob;
09174    }
09175 
09176    if (tmp) {
09177       int chan_sig = conf->chan.sig;
09178       if (!here) {
09179          if ((channel != CHAN_PSEUDO) && !pri) {
09180             int count = 0;
09181             snprintf(fn, sizeof(fn), "%d", channel);
09182             /* Open non-blocking */
09183             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
09184             while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
09185                usleep(1);
09186                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
09187                count++;
09188             }
09189             /* Allocate a DAHDI structure */
09190             if (tmp->subs[SUB_REAL].dfd < 0) {
09191                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);
09192                destroy_dahdi_pvt(&tmp);
09193                return NULL;
09194             }
09195             memset(&p, 0, sizeof(p));
09196             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09197             if (res < 0) {
09198                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
09199                destroy_dahdi_pvt(&tmp);
09200                return NULL;
09201             }
09202             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
09203                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));
09204                destroy_dahdi_pvt(&tmp);
09205                return NULL;
09206             }
09207             tmp->law = p.curlaw;
09208             tmp->span = p.spanno;
09209             span = p.spanno - 1;
09210          } else {
09211             if (channel == CHAN_PSEUDO)
09212                chan_sig = 0;
09213             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
09214                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
09215                return NULL;
09216             }
09217          }
09218          tmp->outsigmod = conf->chan.outsigmod;
09219 
09220 #ifdef HAVE_PRI
09221          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
09222             int offset;
09223             int myswitchtype;
09224             int matchesdchan;
09225             int x,y;
09226             offset = 0;
09227             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
09228                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
09229                destroy_dahdi_pvt(&tmp);
09230                return NULL;
09231             }
09232             if (span >= NUM_SPANS) {
09233                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
09234                destroy_dahdi_pvt(&tmp);
09235                return NULL;
09236             } else {
09237                struct dahdi_spaninfo si;
09238                si.spanno = 0;
09239                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
09240                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
09241                   destroy_dahdi_pvt(&tmp);
09242                   return NULL;
09243                }
09244                /* Store the logical span first based upon the real span */
09245                tmp->logicalspan = pris[span].prilogicalspan;
09246                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
09247                if (span < 0) {
09248                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
09249                   destroy_dahdi_pvt(&tmp);
09250                   return NULL;
09251                }
09252                if (chan_sig == SIG_PRI)
09253                   myswitchtype = conf->pri.switchtype;
09254                else
09255                   myswitchtype = PRI_SWITCH_GR303_TMC;
09256                /* Make sure this isn't a d-channel */
09257                matchesdchan=0;
09258                for (x = 0; x < NUM_SPANS; x++) {
09259                   for (y = 0; y < NUM_DCHANS; y++) {
09260                      if (pris[x].dchannels[y] == tmp->channel) {
09261                         matchesdchan = 1;
09262                         break;
09263                      }
09264                   }
09265                }
09266                offset = p.chanpos;
09267                if (!matchesdchan) {
09268                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
09269                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
09270                      destroy_dahdi_pvt(&tmp);
09271                      return NULL;
09272                   }
09273                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
09274                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
09275                      destroy_dahdi_pvt(&tmp);
09276                      return NULL;
09277                   }
09278                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
09279                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
09280                      destroy_dahdi_pvt(&tmp);
09281                      return NULL;
09282                   }
09283                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
09284                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
09285                      destroy_dahdi_pvt(&tmp);
09286                      return NULL;
09287                   }
09288                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
09289                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
09290                      destroy_dahdi_pvt(&tmp);
09291                      return NULL;
09292                   }
09293                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
09294                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
09295                      destroy_dahdi_pvt(&tmp);
09296                      return NULL;
09297                   }
09298                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
09299                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
09300                      destroy_dahdi_pvt(&tmp);
09301                      return NULL;
09302                   }
09303                   if (pris[span].numchans >= MAX_CHANNELS) {
09304                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
09305                         pris[span].trunkgroup);
09306                      destroy_dahdi_pvt(&tmp);
09307                      return NULL;
09308                   }
09309                   pris[span].nodetype = conf->pri.nodetype;
09310                   pris[span].switchtype = myswitchtype;
09311                   pris[span].nsf = conf->pri.nsf;
09312                   pris[span].dialplan = conf->pri.dialplan;
09313                   pris[span].localdialplan = conf->pri.localdialplan;
09314                   pris[span].pvts[pris[span].numchans++] = tmp;
09315                   pris[span].minunused = conf->pri.minunused;
09316                   pris[span].minidle = conf->pri.minidle;
09317                   pris[span].overlapdial = conf->pri.overlapdial;
09318 #ifdef HAVE_PRI_INBANDDISCONNECT
09319                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
09320 #endif
09321                   pris[span].facilityenable = conf->pri.facilityenable;
09322                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
09323                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
09324                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
09325                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
09326                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
09327                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
09328                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
09329                   pris[span].resetinterval = conf->pri.resetinterval;
09330                   
09331                   tmp->pri = &pris[span];
09332                   tmp->prioffset = offset;
09333                   tmp->call = NULL;
09334 
09335                   tmp->priexclusive = conf->chan.priexclusive;
09336                } else {
09337                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
09338                   destroy_dahdi_pvt(&tmp);
09339                   return NULL;
09340                }
09341             }
09342          } else {
09343             tmp->prioffset = 0;
09344          }
09345 #endif
09346 
09347 #ifdef HAVE_OPENR2
09348          if (chan_sig == SIG_MFCR2 && reloading != 1) {
09349             char logdir[OR2_MAX_PATH];
09350             struct dahdi_mfcr2 *dahdi_r2;
09351             int threshold = 0;
09352             int snres = 0;
09353             dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
09354             if (!dahdi_r2) {
09355                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
09356             } else if (!dahdi_r2->protocol_context){
09357                char tmplogdir[] = "/tmp";
09358                dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 
09359                      &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
09360                if (!dahdi_r2->protocol_context) {
09361                   ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
09362                   destroy_dahdi_pvt(&tmp);
09363                   return NULL;
09364                } 
09365                openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
09366                openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
09367                openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
09368                openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
09369                openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
09370                openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
09371                openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
09372                openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
09373 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
09374                openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
09375                openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
09376 #endif
09377                if (ast_strlen_zero(mfcr2_cur_logdir)) {
09378                   if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
09379                      ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09380                   }
09381                } else {
09382                   snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
09383                   if (snres >= sizeof(logdir)) {
09384                      ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
09385                      if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
09386                         ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09387                      }
09388                   } else {
09389                      if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
09390                         ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
09391                      }
09392                   }  
09393                }
09394                if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
09395                   if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
09396                      ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
09397                   }
09398                }
09399             } 
09400             if (dahdi_r2) {
09401                /* TODO: should we check numchans overflow, or is it already done by DAHDI? */
09402                dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
09403                tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
09404                      tmp->subs[SUB_REAL].dfd, NULL, NULL);
09405                if (!tmp->r2chan) {
09406                   openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
09407                   ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
09408                   destroy_dahdi_pvt(&tmp);
09409                   return NULL;
09410                }
09411                openr2_chan_set_client_data(tmp->r2chan, tmp);
09412                /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
09413                openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
09414                openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
09415                if (mfcr2_cur_call_files) {
09416                   openr2_chan_enable_call_files(tmp->r2chan);
09417                }
09418                tmp->mfcr2_category = mfcr2_cur_category;
09419                tmp->mfcr2 = dahdi_r2;
09420                tmp->mfcr2call = 0;
09421                tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
09422                tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
09423                tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
09424                tmp->mfcr2_ani_index = 0;
09425                tmp->mfcr2_dnis_index = 0;
09426                tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
09427                tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
09428             }
09429          }
09430 #endif
09431 
09432       } else {
09433          chan_sig = tmp->sig;
09434          if (tmp->subs[SUB_REAL].dfd > -1) {
09435             memset(&p, 0, sizeof(p));
09436             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09437          }
09438       }
09439       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
09440       switch (chan_sig) {
09441       case SIG_FXSKS:
09442       case SIG_FXSLS:
09443       case SIG_EM:
09444       case SIG_EM_E1:
09445       case SIG_EMWINK:
09446       case SIG_FEATD:
09447       case SIG_FEATDMF:
09448       case SIG_FEATDMF_TA:
09449       case SIG_FEATB:
09450       case SIG_E911:
09451       case SIG_SF:
09452       case SIG_SFWINK:
09453       case SIG_FGC_CAMA:
09454       case SIG_FGC_CAMAMF:
09455       case SIG_SF_FEATD:
09456       case SIG_SF_FEATDMF:
09457       case SIG_SF_FEATB:
09458          p.starttime = 250;
09459          break;
09460       }
09461 
09462       if (tmp->radio) {
09463          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
09464          p.channo = channel;
09465          p.rxwinktime = 1;
09466          p.rxflashtime = 1;
09467          p.starttime = 1;
09468          p.debouncetime = 5;
09469       }
09470       if (!tmp->radio) {
09471          p.channo = channel;
09472          /* Override timing settings based on config file */
09473          if (conf->timing.prewinktime >= 0)
09474             p.prewinktime = conf->timing.prewinktime;
09475          if (conf->timing.preflashtime >= 0)
09476             p.preflashtime = conf->timing.preflashtime;
09477          if (conf->timing.winktime >= 0)
09478             p.winktime = conf->timing.winktime;
09479          if (conf->timing.flashtime >= 0)
09480             p.flashtime = conf->timing.flashtime;
09481          if (conf->timing.starttime >= 0)
09482             p.starttime = conf->timing.starttime;
09483          if (conf->timing.rxwinktime >= 0)
09484             p.rxwinktime = conf->timing.rxwinktime;
09485          if (conf->timing.rxflashtime >= 0)
09486             p.rxflashtime = conf->timing.rxflashtime;
09487          if (conf->timing.debouncetime >= 0)
09488             p.debouncetime = conf->timing.debouncetime;
09489       }
09490       
09491       /* dont set parms on a pseudo-channel (or CRV) */
09492       if (tmp->subs[SUB_REAL].dfd >= 0)
09493       {
09494          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09495          if (res < 0) {
09496             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09497             destroy_dahdi_pvt(&tmp);
09498             return NULL;
09499          }
09500       }
09501 #if 1
09502       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09503          memset(&bi, 0, sizeof(bi));
09504          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09505          if (!res) {
09506             bi.txbufpolicy = conf->chan.buf_policy;
09507             bi.rxbufpolicy = conf->chan.buf_policy;
09508             bi.numbufs = conf->chan.buf_no;
09509             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09510             if (res < 0) {
09511                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09512             }
09513          } else {
09514             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09515          }
09516          tmp->buf_policy = conf->chan.buf_policy;
09517          tmp->buf_no = conf->chan.buf_no;
09518          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
09519           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
09520           * The reason the ioctl call above failed should to be determined before worrying about the
09521           * faxbuffer-related ioctl calls */
09522          tmp->bufsize = bi.bufsize;
09523       }
09524 #endif
09525       tmp->immediate = conf->chan.immediate;
09526       tmp->transfertobusy = conf->chan.transfertobusy;
09527       tmp->sig = chan_sig;
09528       tmp->ringt_base = ringt_base;
09529       tmp->firstradio = 0;
09530       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09531          tmp->permcallwaiting = conf->chan.callwaiting;
09532       else
09533          tmp->permcallwaiting = 0;
09534       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
09535       tmp->destroy = 0;
09536       tmp->drings = drings;
09537       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
09538       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09539       tmp->threewaycalling = conf->chan.threewaycalling;
09540       tmp->adsi = conf->chan.adsi;
09541       tmp->use_smdi = conf->chan.use_smdi;
09542       tmp->permhidecallerid = conf->chan.hidecallerid;
09543       tmp->hidecalleridname = conf->chan.hidecalleridname;
09544       tmp->callreturn = conf->chan.callreturn;
09545       tmp->echocancel = conf->chan.echocancel;
09546       tmp->echotraining = conf->chan.echotraining;
09547       tmp->pulse = conf->chan.pulse;
09548       if (tmp->echocancel)
09549          tmp->echocanbridged = conf->chan.echocanbridged;
09550       else {
09551          if (conf->chan.echocanbridged)
09552             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09553          tmp->echocanbridged = 0;
09554       }
09555       tmp->busydetect = conf->chan.busydetect;
09556       tmp->busycount = conf->chan.busycount;
09557       tmp->busycompare = conf->chan.busycompare;
09558       tmp->busytonelength = conf->chan.busytonelength;
09559       tmp->busyquietlength = conf->chan.busyquietlength;
09560       tmp->busyfuzziness = conf->chan.busyfuzziness;
09561       tmp->silencethreshold = conf->chan.silencethreshold;
09562       tmp->callprogress = conf->chan.callprogress;
09563       tmp->cancallforward = conf->chan.cancallforward;
09564       tmp->dtmfrelax = conf->chan.dtmfrelax;
09565       tmp->callwaiting = tmp->permcallwaiting;
09566       tmp->hidecallerid = tmp->permhidecallerid;
09567       tmp->channel = channel;
09568       tmp->stripmsd = conf->chan.stripmsd;
09569       tmp->use_callerid = conf->chan.use_callerid;
09570       tmp->cid_signalling = conf->chan.cid_signalling;
09571       tmp->cid_start = conf->chan.cid_start;
09572       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09573       tmp->restrictcid = conf->chan.restrictcid;
09574       tmp->use_callingpres = conf->chan.use_callingpres;
09575       if (tmp->usedistinctiveringdetection) {
09576          if (!tmp->use_callerid) {
09577             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09578             tmp->use_callerid = 1;
09579          }
09580       }
09581 
09582       if (tmp->cid_signalling == CID_SIG_SMDI) {
09583          if (!tmp->use_smdi) {
09584             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09585             tmp->use_smdi = 1;
09586          }
09587       }
09588       if (tmp->use_smdi) {
09589          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09590          if (!(tmp->smdi_iface)) {
09591             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09592             tmp->use_smdi = 0;
09593          }
09594       }
09595 
09596       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09597       tmp->amaflags = conf->chan.amaflags;
09598       if (!here) {
09599          tmp->confno = -1;
09600          tmp->propconfno = -1;
09601       }
09602       tmp->canpark = conf->chan.canpark;
09603       tmp->transfer = conf->chan.transfer;
09604       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09605       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09606       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09607       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09608       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09609       tmp->cid_ton = 0;
09610       if (chan_sig != SIG_PRI) {
09611          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09612          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09613       } else {
09614          tmp->cid_num[0] = '\0';
09615          tmp->cid_name[0] = '\0';
09616       }
09617       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09618       tmp->msgstate = -1;
09619       memcpy(&tmp->group, conf->chan.group, sizeof(tmp->group));
09620       memcpy(&tmp->callgroup, conf->chan.callgroup, sizeof(tmp->callgroup));
09621       memcpy(&tmp->pickupgroup, conf->chan.pickupgroup, sizeof(tmp->pickupgroup));
09622       tmp->rxgain = conf->chan.rxgain;
09623       tmp->txgain = conf->chan.txgain;
09624       tmp->tonezone = conf->chan.tonezone;
09625       tmp->onhooktime = time(NULL);
09626       if (tmp->subs[SUB_REAL].dfd > -1) {
09627          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09628          if (tmp->dsp)
09629             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09630          update_conf(tmp);
09631          if (!here) {
09632             if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09633                /* Hang it up to be sure it's good */
09634                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09635          }
09636          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09637 #ifdef HAVE_PRI
09638          /* the dchannel is down so put the channel in alarm */
09639          if (tmp->pri && !pri_is_up(tmp->pri)) {
09640             tmp->inalarm = 1;
09641             tmp->resetting = 0;
09642          }
09643 #endif            
09644          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09645             tmp->inalarm = 1;
09646 #if defined(HAVE_PRI)
09647             tmp->resetting = 0;
09648 #endif   /* defined(HAVE_PRI) */
09649             handle_alarms(tmp, res);
09650          } else {
09651             /* yes, this looks strange... the unknown_alarm flag is only used to
09652                control whether an 'alarm cleared' message gets generated when we
09653                get an indication that the channel is no longer in alarm status.
09654                however, the channel *could* be in an alarm status that we aren't
09655                aware of (since get_alarms() only reports span alarms, not channel
09656                alarms). setting this flag will cause any potential 'alarm cleared'
09657                message to be suppressed, but if a real alarm occurs before that
09658                happens, this flag will get cleared by it and the situation will
09659                be normal.
09660             */
09661             tmp->unknown_alarm = 1;
09662          }
09663       }
09664 
09665       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09666       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09667       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09668       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09669 
09670    }
09671    if (tmp && !here) {
09672       /* nothing on the iflist */
09673       if (!*wlist) {
09674          *wlist = tmp;
09675          tmp->prev = NULL;
09676          tmp->next = NULL;
09677          *wend = tmp;
09678       } else {
09679          /* at least one member on the iflist */
09680          struct dahdi_pvt *working = *wlist;
09681 
09682          /* check if we maybe have to put it on the begining */
09683          if (working->channel > tmp->channel) {
09684             tmp->next = *wlist;
09685             tmp->prev = NULL;
09686             (*wlist)->prev = tmp;
09687             *wlist = tmp;
09688          } else {
09689          /* go through all the members and put the member in the right place */
09690             while (working) {
09691                /* in the middle */
09692                if (working->next) {
09693                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09694                      tmp->next = working->next;
09695                      tmp->prev = working;
09696                      working->next->prev = tmp;
09697                      working->next = tmp;
09698                      break;
09699                   }
09700                } else {
09701                /* the last */
09702                   if (working->channel < tmp->channel) {
09703                      working->next = tmp;
09704                      tmp->next = NULL;
09705                      tmp->prev = working;
09706                      *wend = tmp;
09707                      break;
09708                   }
09709                }
09710                working = working->next;
09711             }
09712          }
09713       }
09714    }
09715    return tmp;
09716 }

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

Definition at line 6669 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_DEBUG, option_debug, READ_SIZE, and dahdi_pvt::subs.

Referenced by dahdi_write().

06670 {
06671    int sent=0;
06672    int size;
06673    int res;
06674    int fd;
06675    fd = p->subs[index].dfd;
06676    while (len) {
06677       size = len;
06678       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06679          size = (linear ? READ_SIZE * 2 : READ_SIZE);
06680       res = write(fd, buf, size);
06681       if (res != size) {
06682          if (option_debug)
06683             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06684          return sent;
06685       }
06686       len -= size;
06687       buf += size;
06688    }
06689    return sent;
06690 }

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

Definition at line 7196 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

07197 {
07198    char c;
07199 
07200    *str = 0; /* start with empty output buffer */
07201    for (;;)
07202    {
07203       /* Wait for the first digit (up to specified ms). */
07204       c = ast_waitfordigit(chan, ms);
07205       /* if timeout, hangup or error, return as such */
07206       if (c < 1)
07207          return c;
07208       *str++ = c;
07209       *str = 0;
07210       if (strchr(term, c))
07211          return 1;
07212    }
07213 }

static int parse_buffers_policy ( const char *  parse,
int *  num_buffers,
int *  policy 
) [static]

Definition at line 4417 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write(), and process_dahdi().

04418 {
04419    int res;
04420    char policy_str[21] = "";
04421    
04422    if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
04423       ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
04424       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
04425       return 1;
04426    }
04427    if (*num_buffers < 0) {
04428       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
04429       return -1;
04430    }
04431    if (!strcasecmp(policy_str, "full")) {
04432       *policy = DAHDI_POLICY_WHEN_FULL;
04433    } else if (!strcasecmp(policy_str, "immediate")) {
04434       *policy = DAHDI_POLICY_IMMEDIATE;
04435 #ifdef DAHDI_POLICY_HALF_FULL
04436    } else if (!strcasecmp(policy_str, "half")) {
04437       *policy = DAHDI_POLICY_HALF_FULL;
04438 #endif
04439    } else {
04440       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
04441       return -1;
04442    }
04443 
04444    return 0;
04445 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

Definition at line 3496 of file chan_dahdi.c.

References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, and dahdi_pri::pri.

Referenced by pri_find_principle().

03497 {
03498    int x = -1;
03499 
03500    for (x = 0; x < NUM_DCHANS; x++) {
03501       if ((pri->dchans[x] == pri->pri))
03502          break;
03503    }
03504 
03505    return pri->fds[x];
03506 }

static int pri_assign_bearer ( struct dahdi_pvt crv,
struct dahdi_pri pri,
struct dahdi_pvt bearer 
) [static]

Definition at line 3466 of file chan_dahdi.c.

References dahdi_pvt::bearer, dahdi_pvt::call, dahdi_subchannel::dfd, ast_channel::fds, inuse, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::realcall, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_request(), pri_dchannel(), and pri_fixup_principle().

03467 {
03468    bearer->owner = &inuse;
03469    bearer->realcall = crv;
03470    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03471    if (crv->subs[SUB_REAL].owner)
03472       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03473    crv->bearer = bearer;
03474    crv->call = bearer->call;
03475    crv->pri = pri;
03476    return 0;
03477 }

static void pri_check_restart ( struct dahdi_pri pri  )  [static]

Definition at line 10931 of file chan_dahdi.c.

References dahdi_pri::lastreset, dahdi_pri::numchans, dahdi_pri::pri, PVT_TO_CHANNEL, dahdi_pri::pvts, dahdi_pri::resetpos, dahdi_pri::resetting, dahdi_pvt::resetting, and sig_pri_is_chan_in_use().

Referenced by pri_dchannel().

10932 {
10933    for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
10934       if (!pri->pvts[pri->resetpos]
10935          || sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
10936          continue;
10937       }
10938       break;
10939    }
10940    if (pri->resetpos < pri->numchans) {
10941       /* Mark the channel as resetting and restart it */
10942       pri->pvts[pri->resetpos]->resetting = 1;
10943       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10944    } else {
10945       pri->resetting = 0;
10946       time(&pri->lastreset);
10947    }
10948 }

static int pri_create_spanmap ( int  span,
int  trunkgroup,
int  logicalspan 
) [static]

Definition at line 9105 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.

Referenced by setup_dahdi().

09106 {
09107    if (pris[span].mastertrunkgroup) {
09108       ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
09109       return -1;
09110    }
09111    pris[span].mastertrunkgroup = trunkgroup;
09112    pris[span].prilogicalspan = logicalspan;
09113    return 0;
09114 }

static int pri_create_trunkgroup ( int  trunkgroup,
int *  channels 
) [static]

Definition at line 9042 of file chan_dahdi.c.

References ast_log(), DAHDI_FILE_CHANNEL, DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, errno, LOG_WARNING, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, dahdi_pri::span, and dahdi_pri::trunkgroup.

Referenced by setup_dahdi().

09043 {
09044    struct dahdi_spaninfo si;
09045    struct dahdi_params p;
09046    int fd;
09047    int span;
09048    int ospan=0;
09049    int x,y;
09050    for (x = 0; x < NUM_SPANS; x++) {
09051       if (pris[x].trunkgroup == trunkgroup) {
09052          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09053          return -1;
09054       }
09055    }
09056    for (y = 0; y < NUM_DCHANS; y++) {
09057       if (!channels[y]) 
09058          break;
09059       memset(&si, 0, sizeof(si));
09060       memset(&p, 0, sizeof(p));
09061       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
09062       if (fd < 0) {
09063          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09064          return -1;
09065       }
09066       x = channels[y];
09067       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09068          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09069          close(fd);
09070          return -1;
09071       }
09072       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09073          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09074          return -1;
09075       }
09076       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09077          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09078          close(fd);
09079          return -1;
09080       }
09081       span = p.spanno - 1;
09082       if (pris[span].trunkgroup) {
09083          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09084          close(fd);
09085          return -1;
09086       }
09087       if (pris[span].pvts[0]) {
09088          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09089          close(fd);
09090          return -1;
09091       }
09092       if (!y) {
09093          pris[span].trunkgroup = trunkgroup;
09094          pris[span].offset = channels[y] - p.chanpos;
09095          ospan = span;
09096       }
09097       pris[ospan].dchannels[y] = channels[y];
09098       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09099       pris[span].span = span + 1;
09100       close(fd);
09101    }
09102    return 0;   
09103 }

static void* pri_dchannel ( void *  vpri  )  [static]

Definition at line 11030 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alreadyhungup, apply_plan_to_number(), ast_canmatch_extension(), AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_copy_string(), ast_dsp_set_features(), ast_exists_extension(), AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_pthread_create, ast_pthread_create_background, ast_shrink_phone_number(), AST_SOFTHANGUP_DEV, AST_STATE_BUSY, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_verbose(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::callingpres, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confirmanswer, dahdi_pvt::context, DAHDI_CALL_LEVEL_ALERTING, DAHDI_CALL_LEVEL_CONNECT, DAHDI_CALL_LEVEL_OVERLAP, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_chan_name, dahdi_enable_ec(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_queue_frame(), dahdi_request(), dahdi_setlaw(), DCHAN_NOTINALARM, DCHAN_UP, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, dahdi_pri::debug, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::dnid, do_idle_thread(), dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::dsp_features, DSP_PROGRESS_RINGING, errno, event2str(), dahdi_pvt::exten, dahdi_pri::fds, ast_channel::hangupcause, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pvt::inalarm, inuse, dahdi_pvt::isidlecall, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pri::lastreset, len(), dahdi_pvt::lock, dahdi_pri::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needringing, dahdi_pri::no_d_channels, dahdi_pri::numchans, option_debug, option_verbose, dahdi_pvt::outgoing, dahdi_pri::overlapdial, dahdi_pvt::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), PRI_CHANNEL, pri_check_restart(), pri_find_crv(), pri_find_dchan(), pri_find_empty_chan(), pri_find_fixup_principle(), pri_find_principle(), pri_find_principle_by_call(), pri_hangup_all(), pri_is_up(), pri_order(), PRI_SPAN, dahdi_pvt::prioffset, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pri::pvts, dahdi_pvt::rdnis, dahdi_pvt::realcall, redirectingreason2str(), dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, ring(), dahdi_pvt::rxgain, S_OR, set_actual_gain(), dahdi_pvt::sig, SIG_FXSKS, sig_pri_is_chan_available(), dahdi_pri::span, ss_thread(), SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pri::switchtype, t, dahdi_pri::trunkgroup, dahdi_pvt::txgain, dahdi_pvt::use_callerid, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

Referenced by start_pri().

11031 {
11032    struct dahdi_pri *pri = vpri;
11033    pri_event *e;
11034    struct pollfd fds[NUM_DCHANS];
11035    int res;
11036    int chanpos = 0, origchanpos = 0;
11037    int x;
11038    int haveidles;
11039    int activeidles;
11040    int nextidle = -1;
11041    struct ast_channel *c;
11042    struct timeval tv, lowest, *next;
11043    struct timeval lastidle = { 0, 0 };
11044    int doidling=0;
11045    char *cc;
11046    char idlen[80];
11047    struct ast_channel *idle;
11048    pthread_t p;
11049    time_t t;
11050    int i, which=-1;
11051    int numdchans;
11052    int cause=0;
11053    struct dahdi_pvt *crv;
11054    pthread_t threadid;
11055    pthread_attr_t attr;
11056    char ani2str[6];
11057    char plancallingnum[256];
11058    char plancallingani[256];
11059    char calledtonstr[10];
11060    unsigned int len;
11061 
11062    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11063 
11064    gettimeofday(&lastidle, NULL);
11065    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
11066       /* Need to do idle dialing, check to be sure though */
11067       cc = strchr(pri->idleext, '@');
11068       if (cc) {
11069          *cc = '\0';
11070          cc++;
11071          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
11072 #if 0
11073          /* Extensions may not be loaded yet */
11074          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
11075             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
11076          else
11077 #endif
11078             doidling = 1;
11079       } else
11080          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
11081    }
11082    for (;;) {
11083       for (i = 0; i < NUM_DCHANS; i++) {
11084          if (!pri->dchannels[i])
11085             break;
11086          fds[i].fd = pri->fds[i];
11087          fds[i].events = POLLIN | POLLPRI;
11088          fds[i].revents = 0;
11089       }
11090       numdchans = i;
11091       time(&t);
11092       ast_mutex_lock(&pri->lock);
11093       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
11094          if (pri->resetting && pri_is_up(pri)) {
11095             if (pri->resetpos < 0) {
11096                pri_check_restart(pri);
11097             }
11098          } else {
11099             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
11100                pri->resetting = 1;
11101                pri->resetpos = -1;
11102             }
11103          }
11104       }
11105       /* Look for any idle channels if appropriate */
11106       if (doidling && pri_is_up(pri)) {
11107          nextidle = -1;
11108          haveidles = 0;
11109          activeidles = 0;
11110          for (x = pri->numchans; x >= 0; x--) {
11111             if (pri->pvts[x]) {
11112                if (sig_pri_is_chan_available(pri->pvts[x])) {
11113                   if (haveidles < pri->minunused) {
11114                      haveidles++;
11115                   } else {
11116                      nextidle = x;
11117                      break;
11118                   }
11119                } else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11120                   activeidles++;
11121                }
11122             }
11123          }
11124          if (nextidle > -1) {
11125             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
11126                /* Don't create a new idle call more than once per second */
11127                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
11128                /*
11129                 * Release the PRI lock while we create the channel so other
11130                 * threads can send D channel messages.
11131                 */
11132                ast_mutex_unlock(&pri->lock);
11133                idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
11134                ast_mutex_lock(&pri->lock);
11135                if (idle) {
11136                   pri->pvts[nextidle]->isidlecall = 1;
11137                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
11138                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
11139                      ast_mutex_unlock(&pri->lock);
11140                      ast_hangup(idle);
11141                      ast_mutex_lock(&pri->lock);
11142                   }
11143                } else {
11144                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
11145                }
11146                gettimeofday(&lastidle, NULL);
11147             }
11148          } else if ((haveidles < pri->minunused) &&
11149                (activeidles > pri->minidle)) {
11150             /* Mark something for hangup if there is something 
11151                that can be hungup */
11152             for (x = pri->numchans; x >= 0; x--) {
11153                /* find a candidate channel */
11154                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11155                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11156                   haveidles++;
11157                   /* Stop if we have enough idle channels or
11158                     can't spare any more active idle ones */
11159                   if ((haveidles >= pri->minunused) ||
11160                       (activeidles <= pri->minidle))
11161                      break;
11162                } 
11163             }
11164          }
11165       }
11166       /* Start with reasonable max */
11167       lowest = ast_tv(60, 0);
11168       for (i = 0; i < NUM_DCHANS; i++) {
11169          /* Find lowest available d-channel */
11170          if (!pri->dchannels[i])
11171             break;
11172          if ((next = pri_schedule_next(pri->dchans[i]))) {
11173             /* We need relative time here */
11174             tv = ast_tvsub(*next, ast_tvnow());
11175             if (tv.tv_sec < 0) {
11176                tv = ast_tv(0,0);
11177             }
11178             if (doidling || pri->resetting) {
11179                if (tv.tv_sec > 1) {
11180                   tv = ast_tv(1, 0);
11181                }
11182             } else {
11183                if (tv.tv_sec > 60) {
11184                   tv = ast_tv(60, 0);
11185                }
11186             }
11187          } else if (doidling || pri->resetting) {
11188             /* Make sure we stop at least once per second if we're
11189                monitoring idle channels */
11190             tv = ast_tv(1,0);
11191          } else {
11192             /* Don't poll for more than 60 seconds */
11193             tv = ast_tv(60, 0);
11194          }
11195          if (!i || ast_tvcmp(tv, lowest) < 0) {
11196             lowest = tv;
11197          }
11198       }
11199       ast_mutex_unlock(&pri->lock);
11200 
11201       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11202       pthread_testcancel();
11203       e = NULL;
11204       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11205       pthread_testcancel();
11206       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11207 
11208       ast_mutex_lock(&pri->lock);
11209       if (!res) {
11210          for (which = 0; which < NUM_DCHANS; which++) {
11211             if (!pri->dchans[which])
11212                break;
11213             /* Just a timeout, run the scheduler */
11214             e = pri_schedule_run(pri->dchans[which]);
11215             if (e)
11216                break;
11217          }
11218       } else if (res > -1) {
11219          for (which = 0; which < NUM_DCHANS; which++) {
11220             if (!pri->dchans[which])
11221                break;
11222             if (fds[which].revents & POLLPRI) {
11223                /* Check for an event */
11224                x = 0;
11225                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11226                if (x) 
11227                   ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
11228                /* Keep track of alarm state */  
11229                if (x == DAHDI_EVENT_ALARM) {
11230                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11231                   pri_find_dchan(pri);
11232                } else if (x == DAHDI_EVENT_NOALARM) {
11233                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
11234                   pri_restart(pri->dchans[which]);
11235                }
11236             
11237                if (option_debug)
11238                   ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11239             } else if (fds[which].revents & POLLIN) {
11240                e = pri_check_event(pri->dchans[which]);
11241             }
11242             if (e)
11243                break;
11244          }
11245       } else if (errno != EINTR)
11246          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11247 
11248       if (e) {
11249          if (pri->debug)
11250             pri_dump_event(pri->dchans[which], e);
11251 
11252          if (e->e != PRI_EVENT_DCHAN_DOWN) {
11253             if (!(pri->dchanavail[which] & DCHAN_UP)) {
11254                if (option_verbose > 1) 
11255                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11256             }
11257             pri->dchanavail[which] |= DCHAN_UP;
11258          } else {
11259             if (pri->dchanavail[which] & DCHAN_UP) {
11260                if (option_verbose > 1) 
11261                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11262             }
11263             pri->dchanavail[which] &= ~DCHAN_UP;
11264          }
11265 
11266          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11267             /* Must be an NFAS group that has the secondary dchan active */
11268             pri->pri = pri->dchans[which];
11269 
11270          switch (e->e) {
11271          case PRI_EVENT_DCHAN_UP:
11272             pri->no_d_channels = 0;
11273             if (!pri->pri) pri_find_dchan(pri);
11274 
11275             /* Note presense of D-channel */
11276             time(&pri->lastreset);
11277 
11278             /* Restart in 5 seconds */
11279             if (pri->resetinterval > -1) {
11280                pri->lastreset -= pri->resetinterval;
11281                pri->lastreset += 5;
11282             }
11283             /* Take the channels from inalarm condition */
11284             pri->resetting = 0;
11285             for (i = 0; i < pri->numchans; i++) {
11286                if (pri->pvts[i]) {
11287                   pri->pvts[i]->inalarm = 0;
11288                   pri->pvts[i]->resetting = 0;
11289                }
11290             }
11291             break;
11292          case PRI_EVENT_DCHAN_DOWN:
11293             pri_find_dchan(pri);
11294             if (!pri_is_up(pri)) {
11295                /* Hangup active channels and put them in alarm mode */
11296                pri->resetting = 0;
11297                for (i = 0; i < pri->numchans; i++) {
11298                   struct dahdi_pvt *p = pri->pvts[i];
11299                   if (p) {
11300                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11301                         /* T309 is not enabled : destroy calls when alarm occurs */
11302                         if (p->call) {
11303                            if (p->pri && p->pri->pri) {
11304                               pri_destroycall(p->pri->pri, p->call);
11305                               p->call = NULL;
11306                            } else
11307                               ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
11308                         }
11309                         if (p->realcall) {
11310                            pri_hangup_all(p->realcall, pri);
11311                         } else if (p->owner)
11312                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11313                      }
11314                      p->inalarm = 1;
11315                      p->resetting = 0;
11316                   }
11317                }
11318             }
11319             break;
11320          case PRI_EVENT_RESTART:
11321             if (e->restart.channel > -1 && PRI_CHANNEL(e->ring.channel) != 0xFF) {
11322                chanpos = pri_find_principle(pri, e->restart.channel);
11323                if (chanpos < 0)
11324                   ast_log(LOG_WARNING,
11325                      "Span %d: Restart requested on odd/unavailable channel number %d/%d\n",
11326                      pri->span, PRI_SPAN(e->restart.channel),
11327                      PRI_CHANNEL(e->restart.channel));
11328                else {
11329                   if (option_verbose > 2)
11330                      ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d restarted\n",
11331                         pri->span, PRI_SPAN(e->restart.channel),
11332                         PRI_CHANNEL(e->restart.channel));
11333                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11334                   if (pri->pvts[chanpos]->call) {
11335                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11336                      pri->pvts[chanpos]->call = NULL;
11337                   }
11338                   /* Force soft hangup if appropriate */
11339                   if (pri->pvts[chanpos]->realcall) 
11340                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11341                   else if (pri->pvts[chanpos]->owner)
11342                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11343                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11344                }
11345             } else {
11346                if (option_verbose > 2)
11347                   ast_verbose(VERBOSE_PREFIX_2 "Restart requested on entire span %d\n",
11348                      pri->span);
11349                for (x = 0; x < pri->numchans; x++)
11350                   if (pri->pvts[x]) {
11351                      ast_mutex_lock(&pri->pvts[x]->lock);
11352                      if (pri->pvts[x]->call) {
11353                         pri_destroycall(pri->pri, pri->pvts[x]->call);
11354                         pri->pvts[x]->call = NULL;
11355                      }
11356                      if (pri->pvts[x]->realcall) 
11357                         pri_hangup_all(pri->pvts[x]->realcall, pri);
11358                      else if (pri->pvts[x]->owner)
11359                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11360                      ast_mutex_unlock(&pri->pvts[x]->lock);
11361                   }
11362             }
11363             break;
11364          case PRI_EVENT_KEYPAD_DIGIT:
11365             chanpos = pri_find_principle_by_call(pri, e->digit.call);
11366             if (chanpos < 0) {
11367                ast_log(LOG_WARNING,
11368                   "Span %d: Received keypad digits for unknown call.\n", pri->span);
11369                break;
11370             }
11371             ast_mutex_lock(&pri->pvts[chanpos]->lock);
11372             /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
11373             if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11374                && pri->pvts[chanpos]->owner) {
11375                /* how to do that */
11376                int digitlen = strlen(e->digit.digits);
11377                char digit;
11378                int i;
11379                for (i = 0; i < digitlen; i++) {
11380                   digit = e->digit.digits[i];
11381                   {
11382                      struct ast_frame f = { AST_FRAME_DTMF, digit, };
11383                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11384                   }
11385                }
11386             }
11387             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11388             break;
11389             
11390          case PRI_EVENT_INFO_RECEIVED:
11391             chanpos = pri_find_principle_by_call(pri, e->ring.call);
11392             if (chanpos < 0) {
11393                ast_log(LOG_WARNING,
11394                   "Span %d: Received INFORMATION for unknown call.\n", pri->span);
11395                break;
11396             }
11397             ast_mutex_lock(&pri->pvts[chanpos]->lock);
11398             /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
11399             if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11400                && pri->pvts[chanpos]->owner) {
11401                /* how to do that */
11402                int digitlen = strlen(e->ring.callednum);
11403                char digit;
11404                int i;
11405                for (i = 0; i < digitlen; i++) {
11406                   digit = e->ring.callednum[i];
11407                   {
11408                      struct ast_frame f = { AST_FRAME_DTMF, digit, };
11409                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11410                   }
11411                }
11412             }
11413             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11414             break;
11415          case PRI_EVENT_RING:
11416             crv = NULL;
11417             chanpos = pri_find_principle_by_call(pri, e->ring.call);
11418             if (-1 < chanpos) {
11419                /* Libpri has already filtered out duplicate SETUPs. */
11420                ast_log(LOG_WARNING,
11421                   "Span %d: Got SETUP with duplicate call ptr.  Dropping call.\n",
11422                   pri->span);
11423                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
11424                break;
11425             }
11426             if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
11427                /* Any channel requested. */
11428                chanpos = pri_find_empty_chan(pri, 1, -1);
11429             } else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
11430                /* No channel specified. */
11431                {
11432                   /* We will not accept incoming call waiting calls. */
11433                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INCOMPATIBLE_DESTINATION);
11434                   break;
11435                }
11436             } else {
11437                /* A channel is specified. */
11438                chanpos = pri_find_principle(pri, e->ring.channel);
11439                ast_log(LOG_DEBUG, "chanpos %d channel %d\n", chanpos, PRI_CHANNEL(e->ring.channel));
11440                origchanpos = chanpos;
11441                if (chanpos < 0) {
11442                   ast_log(LOG_WARNING,
11443                      "Span %d: SETUP on unconfigured channel %d/%d\n",
11444                      pri->span, PRI_SPAN(e->ring.channel),
11445                      PRI_CHANNEL(e->ring.channel));
11446                } else if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
11447                   /* This is where we handle initial glare */
11448                   ast_log(LOG_NOTICE,
11449                      "Span %d: SETUP requested unavailable channel %d/%d.  Attempting to renegotiate.\n",
11450                      pri->span, PRI_SPAN(e->ring.channel),
11451                      PRI_CHANNEL(e->ring.channel));
11452                   chanpos = -1;
11453                } 
11454 #if defined(ALWAYS_PICK_CHANNEL)
11455                if (e->ring.flexible) {
11456                   chanpos = -1;
11457                }
11458 #endif   /* defined(ALWAYS_PICK_CHANNEL) */
11459                if (chanpos < 0 && e->ring.flexible) {
11460                   /* We can try to pick another channel. */
11461                   chanpos = pri_find_empty_chan(pri, 1, origchanpos);
11462                }
11463             }
11464             if (chanpos < 0) {
11465                if (e->ring.flexible) {
11466                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11467                } else {
11468                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11469                }
11470                break;
11471             }
11472 
11473             ast_mutex_lock(&pri->pvts[chanpos]->lock);
11474             if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11475                /* Should be safe to lock CRV AFAIK while bearer is still locked */
11476                crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11477                if (crv)
11478                   ast_mutex_lock(&crv->lock);
11479                if (!crv || crv->owner) {
11480                   pri->pvts[chanpos]->call = NULL;
11481                   if (crv) {
11482                      if (crv->owner)
11483                         crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11484                      ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
11485                   } else
11486                      ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
11487                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11488                   if (crv)
11489                      ast_mutex_unlock(&crv->lock);
11490                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11491                   break;
11492                }
11493             }
11494 
11495             /* Mark channel as in use so noone else will steal it. */
11496             pri->pvts[chanpos]->call = e->ring.call;
11497 
11498             apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11499             if (pri->pvts[chanpos]->use_callerid) {
11500                ast_shrink_phone_number(plancallingnum);
11501                ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11502 #ifdef PRI_ANI
11503                if (!ast_strlen_zero(e->ring.callingani)) {
11504                   apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11505                   ast_shrink_phone_number(plancallingani);
11506                   ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11507                } else {
11508                   pri->pvts[chanpos]->cid_ani[0] = '\0';
11509                }
11510 #endif
11511                ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11512                pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
11513             } else {
11514                pri->pvts[chanpos]->cid_num[0] = '\0';
11515                pri->pvts[chanpos]->cid_ani[0] = '\0';
11516                pri->pvts[chanpos]->cid_name[0] = '\0';
11517                pri->pvts[chanpos]->cid_ton = 0;
11518             }
11519             apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11520                       e->ring.redirectingnum, e->ring.callingplanrdnis);
11521 
11522             /* Set DNID on all incoming calls -- even immediate */
11523             ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11524 
11525             /* If immediate=yes go to s|1 */
11526             if (pri->pvts[chanpos]->immediate) {
11527                if (option_verbose > 2)
11528                   ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
11529                pri->pvts[chanpos]->exten[0] = 's';
11530                pri->pvts[chanpos]->exten[1] = '\0';
11531             }
11532             /* Get called number */
11533             else if (!ast_strlen_zero(e->ring.callednum)) {
11534                ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11535             } else if (pri->overlapdial)
11536                pri->pvts[chanpos]->exten[0] = '\0';
11537             else {
11538                /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
11539                pri->pvts[chanpos]->exten[0] = 's';
11540                pri->pvts[chanpos]->exten[1] = '\0';
11541             }
11542             /* No number yet, but received "sending complete"? */
11543             if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11544                if (option_verbose > 2)
11545                   ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
11546                pri->pvts[chanpos]->exten[0] = 's';
11547                pri->pvts[chanpos]->exten[1] = '\0';
11548             }
11549 
11550             /* Make sure extension exists (or in overlap dial mode, can exist) */
11551             if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11552                ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11553                /* Setup law */
11554                int law;
11555                if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11556                   /* Set to audio mode at this point */
11557                   law = 1;
11558                   if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11559                      ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11560                }
11561                if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11562                   law = DAHDI_LAW_ALAW;
11563                else
11564                   law = DAHDI_LAW_MULAW;
11565                res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11566                if (res < 0) 
11567                   ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11568                res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11569                if (res < 0)
11570                   ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11571                if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11572                   /* Just announce proceeding */
11573                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11574                   pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11575                } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11576                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
11577                   pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11578                } else {
11579                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
11580                   pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11581                }
11582                /* Get the use_callingpres state */
11583                pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11584             
11585                /* Start PBX */
11586                if (!e->ring.complete
11587                   && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11588                   && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11589                   /*
11590                    * Release the PRI lock while we create the channel so other
11591                    * threads can send D channel messages.  We must also release
11592                    * the private lock to prevent deadlock while creating the
11593                    * channel.
11594                    */
11595                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11596                   ast_mutex_unlock(&pri->lock);
11597                   if (crv) {
11598                      /* Set bearer and such */
11599                      pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11600                      c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11601                      pri->pvts[chanpos]->owner = &inuse;
11602                      ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11603                   } else {
11604                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11605                   }
11606                   ast_mutex_lock(&pri->lock);
11607                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11608                   if (c) {
11609                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11610                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11611                      }
11612                      if (e->ring.ani2 >= 0) {
11613                         snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11614                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11615                      }
11616 
11617 #ifdef SUPPORT_USERUSER
11618                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
11619                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11620                      }
11621 #endif
11622 
11623                      snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11624                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11625                      if (e->ring.redirectingreason >= 0)
11626                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11627 
11628                      if (!pri->pvts[chanpos]->digital) {
11629                         /*
11630                          * Call has a channel.
11631                          * Indicate that we are providing dialtone.
11632                          */
11633                         pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */
11634                         pri_progress(pri->pri, e->ring.call,
11635                            PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11636                      }
11637                   }
11638 
11639                   pthread_attr_init(&attr);
11640                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11641                   if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
11642                      if (option_verbose > 2)
11643                         ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11644                            plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11645                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11646                   } else {
11647                      ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11648                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11649                      if (c) {
11650                         /* Avoid deadlock while destroying channel */
11651                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11652                         ast_mutex_unlock(&pri->lock);
11653                         ast_hangup(c);
11654                         ast_mutex_lock(&pri->lock);
11655                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
11656                      } else {
11657                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11658                         pri->pvts[chanpos]->call = NULL;
11659                      }
11660                   }
11661                   pthread_attr_destroy(&attr);
11662                } else {
11663                   /*
11664                    * Release the PRI lock while we create the channel so other
11665                    * threads can send D channel messages.  We must also release
11666                    * the private lock to prevent deadlock while creating the
11667                    * channel.
11668                    */
11669                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11670                   ast_mutex_unlock(&pri->lock);
11671                   c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11672                   ast_mutex_lock(&pri->lock);
11673                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11674                   if (c) {
11675                      /*
11676                       * It is reasonably safe to set the following
11677                       * channel variables while the PRI and DAHDI private
11678                       * structures are locked.  The PBX has not been
11679                       * started yet and it is unlikely that any other task
11680                       * will do anything with the channel we have just
11681                       * created.
11682                       */
11683                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11684                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11685                      }
11686                      if (e->ring.ani2 >= 0) {
11687                         snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11688                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11689                      }
11690 
11691 #ifdef SUPPORT_USERUSER
11692                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
11693                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11694                      }
11695 #endif
11696 
11697                      if (e->ring.redirectingreason >= 0)
11698                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11699 
11700                      snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11701                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11702                   }
11703                   if (c && !ast_pbx_start(c)) {
11704                      if (option_verbose > 2)
11705                         ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11706                            plancallingnum, pri->pvts[chanpos]->exten,
11707                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11708 
11709                      dahdi_enable_ec(pri->pvts[chanpos]);
11710                   } else {
11711                      ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11712                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11713                      if (c) {
11714                         /* Avoid deadlock while destroying channel */
11715                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11716                         ast_mutex_unlock(&pri->lock);
11717                         ast_hangup(c);
11718                         ast_mutex_lock(&pri->lock);
11719                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
11720                      } else {
11721                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11722                         pri->pvts[chanpos]->call = NULL;
11723                      }
11724                   }
11725                }
11726             } else {
11727                if (option_verbose > 2)
11728                   ast_verbose(VERBOSE_PREFIX_3 "Span %d: Extension %s@%s does not exist.  Rejecting call from '%s'.\n",
11729                      pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context,
11730                      pri->pvts[chanpos]->cid_num);
11731                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11732                pri->pvts[chanpos]->call = NULL;
11733                pri->pvts[chanpos]->exten[0] = '\0';
11734             }
11735             if (crv)
11736                ast_mutex_unlock(&crv->lock);
11737             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11738             break;
11739          case PRI_EVENT_RINGING:
11740             chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
11741                e->ringing.call);
11742             if (chanpos < 0) {
11743                break;
11744             }
11745             ast_mutex_lock(&pri->pvts[chanpos]->lock);
11746             if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11747                dahdi_enable_ec(pri->pvts[chanpos]);
11748                pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11749                if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
11750                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
11751                }
11752             } else
11753                ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
11754             if (
11755 #ifdef PRI_PROGRESS_MASK
11756                e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
11757 #else
11758                e->ringing.progress == 8
11759 #endif
11760                ) {
11761                /* Now we can do call progress detection */
11762                if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11763                   /* RINGING detection isn't required because we got ALERTING signal */
11764                   ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11765                   pri->pvts[chanpos]->dsp_features = 0;
11766                }
11767             }
11768 
11769 #ifdef SUPPORT_USERUSER
11770             if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11771                struct ast_channel *owner = pri->pvts[chanpos]->owner;
11772                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11773                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11774                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11775             }
11776 #endif
11777 
11778             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11779             break;
11780          case PRI_EVENT_PROGRESS:
11781             chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
11782                e->proceeding.call);
11783             if (chanpos < 0) {
11784                break;
11785             }
11786             if ((!pri->pvts[chanpos]->progress)
11787 #ifdef PRI_PROGRESS_MASK
11788                || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
11789 #else
11790                || (e->proceeding.progress == 8)
11791 #endif
11792                ) {
11793                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11794 
11795                if (e->proceeding.cause > -1) {
11796                   if (option_verbose > 2)
11797                      ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
11798 
11799                   /* Work around broken, out of spec USER_BUSY cause in a progress message */
11800                   if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11801                      if (pri->pvts[chanpos]->owner) {
11802                         if (option_verbose > 2)
11803                            ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11804 
11805                         pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11806                         f.subclass = AST_CONTROL_BUSY;
11807                      }
11808                   }
11809                }
11810 
11811                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11812                ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11813                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11814                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11815                if (
11816 #ifdef PRI_PROGRESS_MASK
11817                   e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
11818 #else
11819                   e->proceeding.progress == 8
11820 #endif
11821                   ) {
11822                   /* Now we can do call progress detection */
11823                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11824                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11825                      pri->pvts[chanpos]->dsp_features = 0;
11826                   }
11827                   /* Bring voice path up */
11828                   f.subclass = AST_CONTROL_PROGRESS;
11829                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11830                }
11831                pri->pvts[chanpos]->progress = 1;
11832                pri->pvts[chanpos]->dialing = 0;
11833                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11834             }
11835             break;
11836          case PRI_EVENT_PROCEEDING:
11837             chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
11838                e->proceeding.call);
11839             if (chanpos < 0) {
11840                break;
11841             }
11842             ast_mutex_lock(&pri->pvts[chanpos]->lock);
11843             if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
11844                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11845 
11846                pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11847                ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11848                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11849                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11850                if (
11851 #ifdef PRI_PROGRESS_MASK
11852                   e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
11853 #else
11854                   e->proceeding.progress == 8
11855 #endif
11856                   ) {
11857                   /* Now we can do call progress detection */
11858                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11859                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11860                      pri->pvts[chanpos]->dsp_features = 0;
11861                   }
11862                   /* Bring voice path up */
11863                   f.subclass = AST_CONTROL_PROGRESS;
11864                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11865                }
11866                pri->pvts[chanpos]->dialing = 0;
11867             }
11868             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11869             break;
11870          case PRI_EVENT_FACNAME:
11871             chanpos = pri_find_principle_by_call(pri, e->facname.call);
11872             if (chanpos < 0) {
11873                ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
11874                   pri->span);
11875                break;
11876             }
11877             if (pri->pvts[chanpos]->use_callerid) {
11878                /* Re-use *69 field for PRI */
11879                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11880                ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11881                ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11882                pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
11883                dahdi_enable_ec(pri->pvts[chanpos]);
11884                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11885             }
11886             break;            
11887          case PRI_EVENT_ANSWER:
11888             chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
11889             if (chanpos < 0) {
11890                break;
11891             }
11892             ast_mutex_lock(&pri->pvts[chanpos]->lock);
11893             /* Now we can do call progress detection */
11894 
11895             /* We changed this so it turns on the DSP no matter what... progress or no progress.
11896              * By this time, we need DTMF detection and other features that were previously disabled
11897              * -- Matt F */
11898             if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11899                ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11900                pri->pvts[chanpos]->dsp_features = 0;
11901             }
11902             if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11903                ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
11904                x = DAHDI_START;
11905                res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11906                if (res < 0) {
11907                   if (errno != EINPROGRESS) {
11908                      ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11909                   }
11910                }
11911             } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11912                pri->pvts[chanpos]->dialing = 1;
11913                /* Send any "w" waited stuff */
11914                res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11915                if (res < 0) {
11916                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11917                   pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11918                } else
11919                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11920                pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11921             } else if (pri->pvts[chanpos]->confirmanswer) {
11922                ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11923             } else {
11924                pri->pvts[chanpos]->dialing = 0;
11925                if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
11926                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
11927                }
11928                pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11929                /* Enable echo cancellation if it's not on already */
11930                dahdi_enable_ec(pri->pvts[chanpos]);
11931             }
11932 
11933 #ifdef SUPPORT_USERUSER
11934             if (!ast_strlen_zero(e->answer.useruserinfo)) {
11935                struct ast_channel *owner = pri->pvts[chanpos]->owner;
11936                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11937                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11938                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11939             }
11940 #endif
11941 
11942             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11943             break;            
11944          case PRI_EVENT_HANGUP:
11945             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
11946             if (chanpos < 0) {
11947                /*
11948                 * Continue hanging up the call even though
11949                 * we do not remember it (if we ever did).
11950                 */
11951                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
11952                break;
11953             }
11954             ast_mutex_lock(&pri->pvts[chanpos]->lock);
11955             switch (e->hangup.cause) {
11956             case PRI_CAUSE_INVALID_CALL_REFERENCE:
11957                /*
11958                 * The peer denies the existence of this call so we must
11959                 * continue hanging it up and forget about it.
11960                 */
11961                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
11962                pri->pvts[chanpos]->call = NULL;
11963                break;
11964             default:
11965                break;
11966             }
11967             if (!pri->pvts[chanpos]->alreadyhungup) {
11968                /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11969                pri->pvts[chanpos]->alreadyhungup = 1;
11970                if (pri->pvts[chanpos]->realcall)
11971                   pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11972                else if (pri->pvts[chanpos]->owner) {
11973                   /* Queue a BUSY instead of a hangup if our cause is appropriate */
11974                   pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11975                   switch (pri->pvts[chanpos]->owner->_state) {
11976                   case AST_STATE_BUSY:
11977                   case AST_STATE_UP:
11978                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11979                      break;
11980                   default:
11981                      if (!pri->pvts[chanpos]->outgoing) {
11982                         /*
11983                          * The incoming call leg hung up before getting
11984                          * connected so just hangup the call.
11985                          */
11986                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11987                         break;
11988                      }
11989                      switch (e->hangup.cause) {
11990                      case PRI_CAUSE_USER_BUSY:
11991                         pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11992                         break;
11993                      case PRI_CAUSE_CALL_REJECTED:
11994                      case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11995                      case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11996                      case PRI_CAUSE_SWITCH_CONGESTION:
11997                      case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11998                      case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11999                         pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
12000                         break;
12001                      default:
12002                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12003                         break;
12004                      }
12005                      break;
12006                   }
12007                } else {
12008                   /*
12009                    * Continue hanging up the call even though
12010                    * we do not have an owner.
12011                    */
12012                   pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
12013                   pri->pvts[chanpos]->call = NULL;
12014                }
12015                if (option_verbose > 2) 
12016                   ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup, cause %d\n",
12017                      pri->span, pri->pvts[chanpos]->logicalspan,
12018                      pri->pvts[chanpos]->prioffset, e->hangup.cause);
12019             } else {
12020                /* Continue hanging up the call. */
12021                pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
12022                pri->pvts[chanpos]->call = NULL;
12023             }
12024 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
12025             if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
12026                && !pri->resetting && !pri->pvts[chanpos]->resetting) {
12027                if (option_verbose > 2)
12028                   ast_verbose(VERBOSE_PREFIX_3
12029                      "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
12030                      pri->span, pri->pvts[chanpos]->logicalspan,
12031                      pri->pvts[chanpos]->prioffset);
12032                pri->pvts[chanpos]->resetting = 1;
12033                pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
12034             }
12035 #endif   /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
12036             if (e->hangup.aoc_units > -1)
12037                if (option_verbose > 2)
12038                   ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
12039                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
12040 
12041 #ifdef SUPPORT_USERUSER
12042             if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
12043                struct ast_channel *owner = pri->pvts[chanpos]->owner;
12044                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12045                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12046                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12047             }
12048 #endif
12049 
12050             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12051             break;
12052 #ifndef PRI_EVENT_HANGUP_REQ
12053 #error please update libpri
12054 #endif
12055          case PRI_EVENT_HANGUP_REQ:
12056             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
12057             if (chanpos < 0) {
12058                /*
12059                 * Continue hanging up the call even though
12060                 * we do not remember it (if we ever did).
12061                 */
12062                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
12063                break;
12064             }
12065             ast_mutex_lock(&pri->pvts[chanpos]->lock);
12066             switch (e->hangup.cause) {
12067             case PRI_CAUSE_INVALID_CALL_REFERENCE:
12068                /*
12069                 * The peer denies the existence of this call so we must
12070                 * continue hanging it up and forget about it.  We should not
12071                 * get this cause here, but for completeness we will handle it
12072                 * anyway.
12073                 */
12074                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
12075                pri->pvts[chanpos]->call = NULL;
12076                break;
12077             default:
12078                break;
12079             }
12080             if (pri->pvts[chanpos]->realcall)
12081                pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12082             else if (pri->pvts[chanpos]->owner) {
12083                pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
12084                switch (pri->pvts[chanpos]->owner->_state) {
12085                case AST_STATE_BUSY:
12086                case AST_STATE_UP:
12087                   pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12088                   break;
12089                default:
12090                   if (!pri->pvts[chanpos]->outgoing) {
12091                      /*
12092                       * The incoming call leg hung up before getting
12093                       * connected so just hangup the call.
12094                       */
12095                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12096                      break;
12097                   }
12098                   switch (e->hangup.cause) {
12099                   case PRI_CAUSE_USER_BUSY:
12100                      pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
12101                      break;
12102                   case PRI_CAUSE_CALL_REJECTED:
12103                   case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
12104                   case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
12105                   case PRI_CAUSE_SWITCH_CONGESTION:
12106                   case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
12107                   case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
12108                      pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
12109                      break;
12110                   default:
12111                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12112                      break;
12113                   }
12114                   break;
12115                }
12116                if (option_verbose > 2) 
12117                   ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup request, cause %d\n",
12118                      pri->span, pri->pvts[chanpos]->logicalspan,
12119                      pri->pvts[chanpos]->prioffset, e->hangup.cause);
12120                if (e->hangup.aoc_units > -1)
12121                   if (option_verbose > 2)
12122                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
12123                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
12124             } else {
12125                /*
12126                 * Continue hanging up the call even though
12127                 * we do not have an owner.
12128                 */
12129                pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
12130                pri->pvts[chanpos]->call = NULL;
12131             }
12132 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
12133             if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
12134                && !pri->resetting && !pri->pvts[chanpos]->resetting) {
12135                if (option_verbose > 2)
12136                   ast_verbose(VERBOSE_PREFIX_3
12137                      "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
12138                      pri->span, pri->pvts[chanpos]->logicalspan,
12139                      pri->pvts[chanpos]->prioffset);
12140                pri->pvts[chanpos]->resetting = 1;
12141                pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
12142             }
12143 #endif   /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
12144 
12145 #ifdef SUPPORT_USERUSER
12146             if (!ast_strlen_zero(e->hangup.useruserinfo)) {
12147                struct ast_channel *owner = pri->pvts[chanpos]->owner;
12148                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12149                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12150                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12151             }
12152 #endif
12153 
12154             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12155             break;
12156          case PRI_EVENT_HANGUP_ACK:
12157             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
12158             if (chanpos < 0) {
12159                break;
12160             }
12161             ast_mutex_lock(&pri->pvts[chanpos]->lock);
12162             pri->pvts[chanpos]->call = NULL;
12163             if (pri->pvts[chanpos]->owner) {
12164                if (option_verbose > 2) 
12165                   ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup ACK\n",
12166                      pri->span, pri->pvts[chanpos]->logicalspan,
12167                      pri->pvts[chanpos]->prioffset);
12168             }
12169 #ifdef SUPPORT_USERUSER
12170             if (!ast_strlen_zero(e->hangup.useruserinfo)) {
12171                struct ast_channel *owner = pri->pvts[chanpos]->owner;
12172                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12173                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
12174                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12175             }
12176 #endif
12177 
12178             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12179             break;
12180          case PRI_EVENT_CONFIG_ERR:
12181             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
12182             break;
12183          case PRI_EVENT_RESTART_ACK:
12184             chanpos = pri_find_principle(pri, e->restartack.channel);
12185             if (chanpos < 0) {
12186                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
12187                   channel number, so we have to figure it out...  This must be why
12188                   everybody resets exactly a channel at a time. */
12189                for (x = 0; x < pri->numchans; x++) {
12190                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
12191                      chanpos = x;
12192                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
12193                      ast_log(LOG_DEBUG,
12194                         "Span %d: Assuming restart ack is for channel %d/%d\n",
12195                         pri->span, pri->pvts[chanpos]->logicalspan,
12196                         pri->pvts[chanpos]->prioffset);
12197                      if (pri->pvts[chanpos]->realcall)
12198                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12199                      else if (pri->pvts[chanpos]->owner) {
12200                         ast_log(LOG_WARNING,
12201                            "Span %d: Got restart ack on channel %d/%d with owner\n",
12202                            pri->span, pri->pvts[chanpos]->logicalspan,
12203                            pri->pvts[chanpos]->prioffset);
12204                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12205                      }
12206                      pri->pvts[chanpos]->resetting = 0;
12207                      if (option_verbose > 2)
12208                         ast_verbose(VERBOSE_PREFIX_3
12209                            "Span %d: Channel %d/%d successfully restarted\n",
12210                            pri->span, pri->pvts[chanpos]->logicalspan,
12211                            pri->pvts[chanpos]->prioffset);
12212                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12213                      if (pri->resetting)
12214                         pri_check_restart(pri);
12215                      break;
12216                   }
12217                }
12218                if (chanpos < 0) {
12219                   ast_log(LOG_WARNING,
12220                      "Span %d: Restart ACK on strange channel %d/%d\n",
12221                      pri->span, PRI_SPAN(e->restartack.channel),
12222                      PRI_CHANNEL(e->restartack.channel));
12223                }
12224             } else {
12225                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12226                if (pri->pvts[chanpos]->realcall) 
12227                   pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12228                else if (pri->pvts[chanpos]->owner) {
12229                   ast_log(LOG_WARNING,
12230                      "Span %d: Got restart ack on channel %d/%d with owner\n",
12231                      pri->span, pri->pvts[chanpos]->logicalspan,
12232                      pri->pvts[chanpos]->prioffset);
12233                   pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12234                }
12235                pri->pvts[chanpos]->resetting = 0;
12236                if (option_verbose > 2)
12237                   ast_verbose(VERBOSE_PREFIX_3
12238                      "Span %d: Channel %d/%d successfully restarted\n",
12239                      pri->span, pri->pvts[chanpos]->logicalspan,
12240                      pri->pvts[chanpos]->prioffset);
12241                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12242                if (pri->resetting)
12243                   pri_check_restart(pri);
12244             }
12245             break;
12246          case PRI_EVENT_SETUP_ACK:
12247             chanpos = pri_find_fixup_principle(pri, e->setup_ack.channel,
12248                e->setup_ack.call);
12249             if (chanpos < 0) {
12250                break;
12251             }
12252             ast_mutex_lock(&pri->pvts[chanpos]->lock);
12253             if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
12254                pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
12255             }
12256 
12257             /* Send any queued digits */
12258             len = strlen(pri->pvts[chanpos]->dialdest);
12259             for (x = 0; x < len; ++x) {
12260                ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
12261                pri_information(pri->pri, pri->pvts[chanpos]->call,
12262                   pri->pvts[chanpos]->dialdest[x]);
12263             }
12264 
12265             if (!pri->pvts[chanpos]->progress
12266                && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
12267                && !pri->pvts[chanpos]->digital) {
12268                /*
12269                 * Call has a channel.
12270                 * Indicate for overlap dialing that dialtone may be present.
12271                 */
12272                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
12273                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12274                pri->pvts[chanpos]->progress = 1;/* Claim to have seen inband-information */
12275                pri->pvts[chanpos]->dialing = 0;
12276                if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
12277                   ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
12278                   pri->pvts[chanpos]->dsp_features = 0;
12279                }
12280             }
12281             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12282             break;
12283          case PRI_EVENT_NOTIFY:
12284 #if defined(HAVE_PRI_CALL_HOLD)
12285             chanpos = pri_find_principle_by_call(pri, e->notify.call);
12286             if (chanpos < 0) {
12287                ast_log(LOG_WARNING, "Span %d: Received NOTIFY for unknown call.\n",
12288                   pri->span);
12289                break;
12290             }
12291 #else
12292             /*
12293              * This version of libpri does not supply a call pointer for
12294              * this message.  We are just going to have to trust that the
12295              * correct principle is found.
12296              */
12297             chanpos = pri_find_principle(pri, e->notify.channel);
12298             if (chanpos < 0) {
12299                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
12300                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
12301                break;
12302             }
12303 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
12304             {
12305                struct ast_frame f = { AST_FRAME_CONTROL, };
12306                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12307                switch (e->notify.info) {
12308                case PRI_NOTIFY_REMOTE_HOLD:
12309                   f.subclass = AST_CONTROL_HOLD;
12310                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12311                   break;
12312                case PRI_NOTIFY_REMOTE_RETRIEVAL:
12313                   f.subclass = AST_CONTROL_UNHOLD;
12314                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12315                   break;
12316                }
12317                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12318             }
12319             break;
12320          default:
12321             ast_log(LOG_DEBUG, "Event: %d\n", e->e);
12322          }
12323       }  
12324       ast_mutex_unlock(&pri->lock);
12325    }
12326    /* Never reached */
12327    return NULL;
12328 }

static struct dahdi_pvt* pri_find_crv ( struct dahdi_pri pri,
int  crv 
) [static, read]

Definition at line 10391 of file chan_dahdi.c.

References dahdi_pvt::channel, dahdi_pri::crvs, and dahdi_pvt::next.

Referenced by pri_dchannel().

10392 {
10393    struct dahdi_pvt *p;
10394    p = pri->crvs;
10395    while (p) {
10396       if (p->channel == crv)
10397          return p;
10398       p = p->next;
10399    }
10400    return NULL;
10401 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 3508 of file chan_dahdi.c.

References ast_log(), DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, LOG_NOTICE, LOG_WARNING, dahdi_pri::no_d_channels, NUM_DCHANS, and dahdi_pri::pri.

Referenced by pri_dchannel().

03509 {
03510    int oldslot = -1;
03511    struct pri *old;
03512    int newslot = -1;
03513    int x;
03514    old = pri->pri;
03515    for (x = 0; x < NUM_DCHANS; x++) {
03516       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03517          newslot = x;
03518       if (pri->dchans[x] == old) {
03519          oldslot = x;
03520       }
03521    }
03522    if (newslot < 0) {
03523       newslot = 0;
03524       if (!pri->no_d_channels) {
03525          pri->no_d_channels = 1;
03526          ast_log(LOG_WARNING,
03527             "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
03528             pri->dchannels[newslot]);
03529       }
03530    } else {
03531       pri->no_d_channels = 0;
03532    }
03533    if (old && (oldslot != newslot))
03534       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03535          pri->dchannels[oldslot], pri->dchannels[newslot]);
03536    pri->pri = pri->dchans[newslot];
03537    return 0;
03538 }

static int pri_find_empty_chan ( struct dahdi_pri pri,
int  backwards,
int  orig 
) [static]

Definition at line 9976 of file chan_dahdi.c.

References ast_have_common_group(), ast_log(), dahdi_pvt::group, LOG_DEBUG, LOG_NOTICE, dahdi_pvt::logicalspan, dahdi_pri::numchans, dahdi_pvt::prioffset, dahdi_pri::pvts, and sig_pri_is_chan_available().

Referenced by dahdi_request(), and pri_dchannel().

09977 {
09978    int x;
09979    if (backwards)
09980       x = pri->numchans;
09981    else
09982       x = 0;
09983    for (;;) {
09984       if (backwards && (x < 0))
09985          break;
09986       if (!backwards && (x >= pri->numchans))
09987          break;
09988       if (pri->pvts[x]
09989          && sig_pri_is_chan_available(pri->pvts[x])) {
09990          if (orig < 0) {
09991             ast_log(LOG_NOTICE, "Found empty available channel %d/%d\n", 
09992                         pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09993             return x;
09994          } else {
09995             if (ast_have_common_group(&pri->pvts[x]->group, &pri->pvts[orig]->group)) {
09996                ast_log(LOG_NOTICE, "Found empty channel %d/%d available belonging to same group that %d/%d (x: %d)\n", pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset,
09997                            pri->pvts[x]->logicalspan, pri->pvts[orig]->prioffset, x);
09998                return x;
09999             } else {
10000                ast_log(LOG_DEBUG, "Empty channel %d/%d available but not belongs to same group that %d/%d (x: %d)\n", pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset, 
10001                            pri->pvts[x]->logicalspan, pri->pvts[orig]->prioffset, x);
10002             }
10003          }
10004       }
10005       if (backwards)
10006          x--;
10007       else
10008          x++;
10009    }
10010    return -1;
10011 }

static int pri_find_fixup_principle ( struct dahdi_pri pri,
int  channel,
q931_call *  call 
) [static]

Definition at line 10752 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, PRI_CHANNEL, pri_find_principle(), pri_fixup_principle(), PRI_SPAN, sig_pri_kill_call(), and dahdi_pri::span.

Referenced by pri_dchannel().

10753 {
10754    int chanpos;
10755 
10756    chanpos = pri_find_principle(pri, channel);
10757    if (chanpos < 0) {
10758       ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
10759          pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
10760       sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
10761       return -1;
10762    }
10763    chanpos = pri_fixup_principle(pri, chanpos, call);
10764    if (chanpos < 0) {
10765       ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
10766          pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
10767       /*
10768        * Using Q.931 section 5.2.3.1 b) as the reason for picking
10769        * PRI_CAUSE_CHANNEL_UNACCEPTABLE.  Receiving a
10770        * PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart
10771        * that channel (which is not specified by Q.931) and kill some
10772        * other call which would be bad.
10773        */
10774       sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
10775       return -1;
10776    }
10777    return chanpos;
10778 }

static int pri_find_principle ( struct dahdi_pri pri,
int  channel 
) [static]

Definition at line 10567 of file chan_dahdi.c.

References dahdi_pvt::logicalspan, dahdi_pri::numchans, pri_active_dchan_fd(), PRI_CHANNEL, PRI_EXPLICIT, PRI_SPAN, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, and dahdi_pri::pvts.

Referenced by pri_dchannel(), and pri_find_fixup_principle().

10568 {
10569    int x;
10570    int span = PRI_SPAN(channel);
10571    int spanfd;
10572    struct dahdi_params param;
10573    int principle = -1;
10574    int explicit = PRI_EXPLICIT(channel);
10575    channel = PRI_CHANNEL(channel);
10576 
10577    if (!explicit) {
10578       spanfd = pri_active_dchan_fd(pri);
10579       memset(&param, 0, sizeof(param));
10580       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10581          return -1;
10582       span = pris[param.spanno - 1].prilogicalspan;
10583    }
10584 
10585    for (x = 0; x < pri->numchans; x++) {
10586       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10587          principle = x;
10588          break;
10589       }
10590    }
10591    
10592    return principle;
10593 }

static int pri_find_principle_by_call ( struct dahdi_pri pri,
q931_call *  call 
) [static]

Definition at line 10500 of file chan_dahdi.c.

References dahdi_pvt::call, dahdi_pri::numchans, and dahdi_pri::pvts.

Referenced by pri_dchannel(), and sig_pri_kill_call().

10501 {
10502    int idx;
10503 
10504    if (!call) {
10505       /* Cannot find a call without a call. */
10506       return -1;
10507    }
10508    for (idx = 0; idx < pri->numchans; ++idx) {
10509       if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
10510          /* Found the principle */
10511          return idx;
10512       }
10513    }
10514    return -1;
10515 }

static int pri_fixup_principle ( struct dahdi_pri pri,
int  principle,
q931_call *  c 
) [static]

Definition at line 10610 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_build, ast_verbose(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::channel, dahdi_pri::crvs, DAHDI_CALL_LEVEL_IDLE, dahdi_chan_name, dahdi_close_sub(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::logicalspan, name, dahdi_pvt::next, dahdi_pri::numchans, option_verbose, dahdi_pvt::owner, pri_assign_bearer(), dahdi_pvt::prioffset, dahdi_pri::pvts, sig_pri_is_chan_available(), sig_pri_lock_owner(), SUB_REAL, dahdi_pri::trunkgroup, VERBOSE_PREFIX_3, and wakeup_sub().

Referenced by pri_find_fixup_principle().

10611 {
10612    int x;
10613    struct dahdi_pvt *crv;
10614    if (!c) {
10615       if (principle < 0)
10616          return -1;
10617       return principle;
10618    }
10619    if ((principle > -1) && 
10620       (principle < pri->numchans) && 
10621       (pri->pvts[principle]) && 
10622       (pri->pvts[principle]->call == c))
10623       return principle;
10624    /* First, check for other bearers */
10625    for (x = 0; x < pri->numchans; x++) {
10626       if (!pri->pvts[x])
10627          continue;
10628       if (pri->pvts[x]->call == c) {
10629          /* Found our call */
10630          if (principle != x) {
10631             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10632 
10633             /* Get locks to safely move to the new private structure. */
10634             ast_mutex_lock(&old->lock);
10635             sig_pri_lock_owner(pri, x);
10636             ast_mutex_lock(&new->lock);
10637 
10638             if (option_verbose > 2) {
10639                ast_verbose(VERBOSE_PREFIX_3
10640                   "Moving call (%s) from channel %d to %d.\n",
10641                   old->owner ? old->owner->name : "",
10642                   old->channel, new->channel);
10643             }
10644             if (!sig_pri_is_chan_available(new)) {
10645                ast_log(LOG_WARNING,
10646                   "Can't move call (%s) from channel %d to %d.  It is already in use.\n",
10647                   old->owner ? old->owner->name : "",
10648                   old->channel, new->channel);
10649                ast_mutex_unlock(&new->lock);
10650                if (old->owner) {
10651                   ast_mutex_unlock(&old->owner->lock);
10652                }
10653                ast_mutex_unlock(&old->lock);
10654                return -1;
10655             }
10656 
10657             /* Fix it all up now */
10658             new->owner = old->owner;
10659             old->owner = NULL;
10660             if (new->owner) {
10661                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
10662                new->owner->tech_pvt = new;
10663                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
10664                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10665                old->subs[SUB_REAL].owner = NULL;
10666             } else
10667                ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
10668             new->call = old->call;
10669             old->call = NULL;
10670 
10671             /* Copy any DSP that may be present */
10672             new->dsp = old->dsp;
10673             new->dsp_features = old->dsp_features;
10674             old->dsp = NULL;
10675             old->dsp_features = 0;
10676 
10677             /* Transfer flags from the old channel. */
10678             new->alreadyhungup = old->alreadyhungup;
10679             new->isidlecall = old->isidlecall;
10680             new->progress = old->progress;
10681             new->allocated = old->allocated;
10682             new->outgoing = old->outgoing;
10683             new->digital = old->digital;
10684             old->alreadyhungup = 0;
10685             old->isidlecall = 0;
10686             old->progress = 0;
10687             old->allocated = 0;
10688             old->outgoing = 0;
10689             old->digital = 0;
10690 
10691             /* More stuff to transfer to the new channel. */
10692             new->call_level = old->call_level;
10693             old->call_level = DAHDI_CALL_LEVEL_IDLE;
10694  
10695             ast_mutex_unlock(&old->lock);
10696             if (new->owner) {
10697                ast_mutex_unlock(&new->owner->lock);
10698             }
10699             ast_mutex_unlock(&new->lock);
10700          }
10701          return principle;
10702       }
10703    }
10704    /* Now check for a CRV with no bearer */
10705    crv = pri->crvs;
10706    while (crv) {
10707       if (crv->call == c) {
10708          /* This is our match...  Perform some basic checks */
10709          if (crv->bearer)
10710             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10711          else if (pri->pvts[principle]->owner) 
10712             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10713          else {
10714             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
10715                wakeup the potential sleeper */
10716             dahdi_close_sub(crv, SUB_REAL);
10717             pri->pvts[principle]->call = crv->call;
10718             pri_assign_bearer(crv, pri, pri->pvts[principle]);
10719             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
10720                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10721                            pri->trunkgroup, crv->channel);
10722             wakeup_sub(crv, SUB_REAL, pri);
10723          }
10724          return principle;
10725       }
10726       crv = crv->next;
10727    }
10728    ast_log(LOG_WARNING, "Call specified, but not found?\n");
10729    return -1;
10730 }

static int pri_grab ( struct dahdi_pvt pvt,
struct dahdi_pri pri 
) [inline, static]

Definition at line 1199 of file chan_dahdi.c.

References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, and dahdi_pri::master.

Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), send_keypad_facility_exec(), and ss_thread().

01200 {
01201    int res;
01202    /* Grab the lock first */
01203    do {
01204       res = ast_mutex_trylock(&pri->lock);
01205       if (res) {
01206          DEADLOCK_AVOIDANCE(&pvt->lock);
01207       }
01208    } while (res);
01209    /* Then break the poll */
01210    if (pri->master != AST_PTHREADT_NULL)
01211       pthread_kill(pri->master, SIGURG);
01212    return 0;
01213 }

static int pri_hangup_all ( struct dahdi_pvt p,
struct dahdi_pri pri 
) [static]

Definition at line 10950 of file chan_dahdi.c.

References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, ast_channel::lock, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by pri_dchannel().

10951 {
10952    int x;
10953    int redo;
10954    ast_mutex_unlock(&pri->lock);
10955    ast_mutex_lock(&p->lock);
10956    do {
10957       redo = 0;
10958       for (x = 0; x < 3; x++) {
10959          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
10960             redo++;
10961             DEADLOCK_AVOIDANCE(&p->lock);
10962          }
10963          if (p->subs[x].owner) {
10964             ast_queue_hangup(p->subs[x].owner);
10965             ast_mutex_unlock(&p->subs[x].owner->lock);
10966          }
10967       }
10968    } while (redo);
10969    ast_mutex_unlock(&p->lock);
10970    ast_mutex_lock(&pri->lock);
10971    return 0;
10972 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 3456 of file chan_dahdi.c.

References DCHAN_AVAILABLE, dahdi_pri::dchanavail, and NUM_DCHANS.

Referenced by mkintf(), and pri_dchannel().

03457 {
03458    int x;
03459    for (x = 0; x < NUM_DCHANS; x++) {
03460       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03461          return 1;
03462    }
03463    return 0;
03464 }

static char* pri_order ( int  level  )  [static]

Definition at line 3479 of file chan_dahdi.c.

Referenced by handle_pri_show_span(), and pri_dchannel().

03480 {
03481    switch (level) {
03482    case 0:
03483       return "Primary";
03484    case 1:
03485       return "Secondary";
03486    case 2:
03487       return "Tertiary";
03488    case 3:
03489       return "Quaternary";
03490    default:
03491       return "<Unknown>";
03492    }     
03493 }

static void pri_queue_control ( struct dahdi_pri pri,
int  chanpos,
int  subclass 
) [static]

Definition at line 10477 of file chan_dahdi.c.

References AST_FRAME_CONTROL, pri_queue_frame(), and ast_frame::subclass.

Referenced by sig_pri_kill_call().

10478 {
10479    struct ast_frame f = {AST_FRAME_CONTROL, };
10480 
10481    f.subclass = subclass;
10482    pri_queue_frame(pri, chanpos, &f);
10483 }

static void pri_queue_frame ( struct dahdi_pri pri,
int  chanpos,
struct ast_frame frame 
) [static]

Definition at line 10452 of file chan_dahdi.c.

References ast_channel_unlock, ast_queue_frame(), dahdi_pvt::owner, dahdi_pri::pvts, and sig_pri_lock_owner().

Referenced by pri_queue_control().

10453 {
10454    sig_pri_lock_owner(pri, chanpos);
10455    if (pri->pvts[chanpos]->owner) {
10456       ast_queue_frame(pri->pvts[chanpos]->owner, frame);
10457       ast_channel_unlock(pri->pvts[chanpos]->owner);
10458    }
10459 }

static void pri_rel ( struct dahdi_pri pri  )  [inline, static]
static int pri_resolve_span ( int *  span,
int  channel,
int  offset,
struct dahdi_spaninfo *  si 
) [static]

Definition at line 8996 of file chan_dahdi.c.

References ast_log(), DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, LOG_WARNING, dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pri::offset, pris, and dahdi_pri::span.

Referenced by mkintf().

08997 {
08998    int x;
08999    int trunkgroup;
09000    /* Get appropriate trunk group if there is one */
09001    trunkgroup = pris[*span].mastertrunkgroup;
09002    if (trunkgroup) {
09003       /* Select a specific trunk group */
09004       for (x = 0; x < NUM_SPANS; x++) {
09005          if (pris[x].trunkgroup == trunkgroup) {
09006             *span = x;
09007             return 0;
09008          }
09009       }
09010       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09011       *span = -1;
09012    } else {
09013       if (pris[*span].trunkgroup) {
09014          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09015          *span = -1;
09016       } else if (pris[*span].mastertrunkgroup) {
09017          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09018          *span = -1;
09019       } else {
09020          if (si->totalchans == 31) {
09021             /* E1 */
09022             pris[*span].dchannels[0] = 16 + offset;
09023          } else if (si->totalchans == 24) {
09024             /* T1 or J1 */
09025             pris[*span].dchannels[0] = 24 + offset;
09026          } else if (si->totalchans == 3) {
09027             /* BRI */
09028             pris[*span].dchannels[0] = 3 + offset;
09029          } else {
09030             ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
09031             *span = -1;
09032             return 0;
09033          }
09034          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09035          pris[*span].offset = offset;
09036          pris[*span].span = *span + 1;
09037       }
09038    }
09039    return 0;
09040 }

static int process_dahdi ( struct dahdi_chan_conf confp,
const char *  cat,
struct ast_variable v,
int  reload,
int  skipchannels 
) [static]

Definition at line 14121 of file chan_dahdi.c.

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero(), ast_true(), ast_verbose(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, dahdi_chan_conf_default(), DAHDI_FILE_CTL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::language, ast_variable::lineno, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, LOG_WARNING, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pri::minidle, dahdi_pri::minunused, mkintf(), dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, ast_variable::name, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_CADENCE_MAX, option_verbose, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, parse_buffers_policy(), dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, dahdi_pvt::pulse, dahdi_pvt::radio, READ_SIZE, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, strsep(), dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, ast_variable::value, and VERBOSE_PREFIX_3.

Referenced by setup_dahdi().

14122 {
14123    struct dahdi_pvt *tmp;
14124    int y;
14125    int found_pseudo = 0;
14126         char dahdichan[MAX_CHANLIST_LEN] = {};
14127 
14128    for (; v; v = v->next) {
14129       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14130          continue;
14131 
14132       /* Create the interface list */
14133       if (!strcasecmp(v->name, "channel")
14134 #ifdef HAVE_PRI
14135           || !strcasecmp(v->name, "crv")
14136 #endif         
14137          ) {
14138          int iscrv;
14139          if (skipchannels)
14140             continue;
14141          iscrv = !strcasecmp(v->name, "crv");
14142          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14143                return -1;
14144       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
14145          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14146          if (v->name[0] == 'z' || v->name[0] == 'Z') {
14147             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
14148          }
14149       } else if (!strcasecmp(v->name, "buffers")) {
14150          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
14151             ast_log(LOG_WARNING, "Using default buffer policy.\n");
14152             confp->chan.buf_no = numbufs;
14153             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14154          }
14155       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14156          if (ast_true(v->value))
14157             confp->chan.usedistinctiveringdetection = 1;
14158       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14159          if (ast_true(v->value))
14160             distinctiveringaftercid = 1;
14161       } else if (!strcasecmp(v->name, "dring1context")) {
14162          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
14163       } else if (!strcasecmp(v->name, "dring2context")) {
14164          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
14165       } else if (!strcasecmp(v->name, "dring3context")) {
14166          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
14167       } else if (!strcasecmp(v->name, "dring1")) {
14168          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
14169       } else if (!strcasecmp(v->name, "dring2")) {
14170          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
14171       } else if (!strcasecmp(v->name, "dring3")) {
14172          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
14173       } else if (!strcasecmp(v->name, "usecallerid")) {
14174          confp->chan.use_callerid = ast_true(v->value);
14175       } else if (!strcasecmp(v->name, "cidsignalling")) {
14176          if (!strcasecmp(v->value, "bell"))
14177             confp->chan.cid_signalling = CID_SIG_BELL;
14178          else if (!strcasecmp(v->value, "v23"))
14179             confp->chan.cid_signalling = CID_SIG_V23;
14180          else if (!strcasecmp(v->value, "dtmf"))
14181             confp->chan.cid_signalling = CID_SIG_DTMF;
14182          else if (!strcasecmp(v->value, "smdi"))
14183             confp->chan.cid_signalling = CID_SIG_SMDI;
14184          else if (!strcasecmp(v->value, "v23_jp"))
14185             confp->chan.cid_signalling = CID_SIG_V23_JP;
14186          else if (ast_true(v->value))
14187             confp->chan.cid_signalling = CID_SIG_BELL;
14188       } else if (!strcasecmp(v->name, "cidstart")) {
14189          if (!strcasecmp(v->value, "ring"))
14190             confp->chan.cid_start = CID_START_RING;
14191          else if (!strcasecmp(v->value, "polarity"))
14192             confp->chan.cid_start = CID_START_POLARITY;
14193          else if (!strcasecmp(v->value, "dtmf"))
14194             confp->chan.cid_start = CID_START_DTMF_NOALERT;
14195          else if (ast_true(v->value))
14196             confp->chan.cid_start = CID_START_RING;
14197       } else if (!strcasecmp(v->name, "threewaycalling")) {
14198          confp->chan.threewaycalling = ast_true(v->value);
14199       } else if (!strcasecmp(v->name, "cancallforward")) {
14200          confp->chan.cancallforward = ast_true(v->value);
14201       } else if (!strcasecmp(v->name, "relaxdtmf")) {
14202          if (ast_true(v->value)) 
14203             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14204          else
14205             confp->chan.dtmfrelax = 0;
14206       } else if (!strcasecmp(v->name, "mailbox")) {
14207          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14208       } else if (!strcasecmp(v->name, "hasvoicemail")) {
14209          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14210             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14211          }
14212       } else if (!strcasecmp(v->name, "adsi")) {
14213          confp->chan.adsi = ast_true(v->value);
14214       } else if (!strcasecmp(v->name, "usesmdi")) {
14215          confp->chan.use_smdi = ast_true(v->value);
14216       } else if (!strcasecmp(v->name, "smdiport")) {
14217          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14218       } else if (!strcasecmp(v->name, "transfer")) {
14219          confp->chan.transfer = ast_true(v->value);
14220       } else if (!strcasecmp(v->name, "canpark")) {
14221          confp->chan.canpark = ast_true(v->value);
14222       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14223          confp->chan.echocanbridged = ast_true(v->value);
14224       } else if (!strcasecmp(v->name, "busydetect")) {
14225          confp->chan.busydetect = ast_true(v->value);
14226       } else if (!strcasecmp(v->name, "busycount")) {
14227          confp->chan.busycount = atoi(v->value);
14228       } else if (!strcasecmp(v->name, "silencethreshold")) {
14229             confp->chan.silencethreshold = atoi(v->value);
14230       } else if (!strcasecmp(v->name, "busycompare")) {
14231             confp->chan.busycompare = ast_true(v->value);
14232       } else if (!strcasecmp(v->name, "busypattern")) {
14233          int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14234          if (count == 1)
14235             confp->chan.busyquietlength = 0;
14236          else if (count < 1)
14237                ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
14238       } else if (!strcasecmp(v->name, "busyfuzziness")) {
14239             confp->chan.busyfuzziness = atoi(v->value);
14240       } else if (!strcasecmp(v->name, "callprogress")) {
14241          if (ast_true(v->value))
14242             confp->chan.callprogress |= 1;
14243          else
14244             confp->chan.callprogress &= ~1;
14245       } else if (!strcasecmp(v->name, "faxdetect")) {
14246          if (!strcasecmp(v->value, "incoming")) {
14247             confp->chan.callprogress |= 4;
14248             confp->chan.callprogress &= ~2;
14249          } else if (!strcasecmp(v->value, "outgoing")) {
14250             confp->chan.callprogress &= ~4;
14251             confp->chan.callprogress |= 2;
14252          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14253             confp->chan.callprogress |= 6;
14254          else
14255             confp->chan.callprogress &= ~6;
14256       } else if (!strcasecmp(v->name, "echocancel")) {
14257          if (!ast_strlen_zero(v->value)) {
14258             y = atoi(v->value);
14259          } else
14260             y = 0;
14261          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
14262             confp->chan.echocancel = y;
14263          else {
14264             confp->chan.echocancel = ast_true(v->value);
14265             if (confp->chan.echocancel)
14266                confp->chan.echocancel=128;
14267          }
14268       } else if (!strcasecmp(v->name, "echotraining")) {
14269          if (sscanf(v->value, "%30d", &y) == 1) {
14270             if ((y < 10) || (y > 4000)) {
14271                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
14272             } else {
14273                confp->chan.echotraining = y;
14274             }
14275          } else if (ast_true(v->value)) {
14276             confp->chan.echotraining = 400;
14277          } else
14278             confp->chan.echotraining = 0;
14279       } else if (!strcasecmp(v->name, "hidecallerid")) {
14280          confp->chan.hidecallerid = ast_true(v->value);
14281       } else if (!strcasecmp(v->name, "hidecalleridname")) {
14282          confp->chan.hidecalleridname = ast_true(v->value);
14283       } else if (!strcasecmp(v->name, "pulsedial")) {
14284          confp->chan.pulse = ast_true(v->value);
14285       } else if (!strcasecmp(v->name, "callreturn")) {
14286          confp->chan.callreturn = ast_true(v->value);
14287       } else if (!strcasecmp(v->name, "callwaiting")) {
14288          confp->chan.callwaiting = ast_true(v->value);
14289       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14290          confp->chan.callwaitingcallerid = ast_true(v->value);
14291       } else if (!strcasecmp(v->name, "context")) {
14292          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14293       } else if (!strcasecmp(v->name, "language")) {
14294          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14295       } else if (!strcasecmp(v->name, "progzone")) {
14296          ast_copy_string(progzone, v->value, sizeof(progzone));
14297       } else if (!strcasecmp(v->name, "mohinterpret") 
14298          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14299          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14300       } else if (!strcasecmp(v->name, "mohsuggest")) {
14301          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14302       } else if (!strcasecmp(v->name, "stripmsd")) {
14303          confp->chan.stripmsd = atoi(v->value);
14304       } else if (!strcasecmp(v->name, "jitterbuffers")) {
14305          numbufs = atoi(v->value);
14306       } else if (!strcasecmp(v->name, "group")) {
14307          memset(confp->chan.group, 0, sizeof(confp->chan.group));
14308          ast_get_group(&confp->chan.group, v->value);
14309       } else if (!strcasecmp(v->name, "callgroup")) {
14310          memset(confp->chan.callgroup, 0, sizeof(confp->chan.callgroup));
14311          if (strcasecmp(v->value, "none")) {
14312             ast_get_group(&confp->chan.callgroup, v->value);
14313          }
14314       } else if (!strcasecmp(v->name, "pickupgroup")) {
14315          memset(confp->chan.pickupgroup, 0, sizeof(confp->chan.pickupgroup));
14316          if (strcasecmp(v->value, "none")) {
14317             ast_get_group(&confp->chan.pickupgroup, v->value);
14318          }
14319       } else if (!strcasecmp(v->name, "immediate")) {
14320          confp->chan.immediate = ast_true(v->value);
14321       } else if (!strcasecmp(v->name, "transfertobusy")) {
14322          confp->chan.transfertobusy = ast_true(v->value);
14323       } else if (!strcasecmp(v->name, "rxgain")) {
14324          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14325             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
14326          }
14327       } else if (!strcasecmp(v->name, "txgain")) {
14328          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14329             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
14330          }
14331       } else if (!strcasecmp(v->name, "tonezone")) {
14332          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14333             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
14334          }
14335       } else if (!strcasecmp(v->name, "callerid")) {
14336          if (!strcasecmp(v->value, "asreceived")) {
14337             confp->chan.cid_num[0] = '\0';
14338             confp->chan.cid_name[0] = '\0';
14339          } else {
14340             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14341          } 
14342       } else if (!strcasecmp(v->name, "fullname")) {
14343          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14344       } else if (!strcasecmp(v->name, "cid_number")) {
14345          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14346       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
14347          confp->chan.dahditrcallerid = ast_true(v->value);
14348          if (strstr(v->name, "zap")) {
14349             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
14350          }
14351       } else if (!strcasecmp(v->name, "restrictcid")) {
14352          confp->chan.restrictcid = ast_true(v->value);
14353       } else if (!strcasecmp(v->name, "usecallingpres")) {
14354          confp->chan.use_callingpres = ast_true(v->value);
14355       } else if (!strcasecmp(v->name, "accountcode")) {
14356          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14357       } else if (!strcasecmp(v->name, "amaflags")) {
14358          y = ast_cdr_amaflags2int(v->value);
14359          if (y < 0) 
14360             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
14361          else
14362             confp->chan.amaflags = y;
14363       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14364          confp->chan.polarityonanswerdelay = atoi(v->value);
14365       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14366          confp->chan.answeronpolarityswitch = ast_true(v->value);
14367       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14368          confp->chan.hanguponpolarityswitch = ast_true(v->value);
14369       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14370          confp->chan.sendcalleridafter = atoi(v->value);
14371       } else if (reload != 1) {
14372           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14373             confp->chan.outsigmod = -1;
14374             if (!strcasecmp(v->value, "em")) {
14375                confp->chan.sig = SIG_EM;
14376             } else if (!strcasecmp(v->value, "em_e1")) {
14377                confp->chan.sig = SIG_EM_E1;
14378             } else if (!strcasecmp(v->value, "em_w")) {
14379                confp->chan.sig = SIG_EMWINK;
14380                confp->chan.radio = 0;
14381             } else if (!strcasecmp(v->value, "fxs_ls")) {
14382                confp->chan.sig = SIG_FXSLS;
14383                confp->chan.radio = 0;
14384             } else if (!strcasecmp(v->value, "fxs_gs")) {
14385                confp->chan.sig = SIG_FXSGS;
14386                confp->chan.radio = 0;
14387             } else if (!strcasecmp(v->value, "fxs_ks")) {
14388                confp->chan.sig = SIG_FXSKS;
14389                confp->chan.radio = 0;
14390             } else if (!strcasecmp(v->value, "fxo_ls")) {
14391                confp->chan.sig = SIG_FXOLS;
14392                confp->chan.radio = 0;
14393             } else if (!strcasecmp(v->value, "fxo_gs")) {
14394                confp->chan.sig = SIG_FXOGS;
14395                confp->chan.radio = 0;
14396             } else if (!strcasecmp(v->value, "fxo_ks")) {
14397                confp->chan.sig = SIG_FXOKS;
14398                confp->chan.radio = 0;
14399             } else if (!strcasecmp(v->value, "fxs_rx")) {
14400                confp->chan.sig = SIG_FXSKS;
14401                confp->chan.radio = 1;
14402             } else if (!strcasecmp(v->value, "fxo_rx")) {
14403                confp->chan.sig = SIG_FXOLS;
14404                confp->chan.radio = 1;
14405             } else if (!strcasecmp(v->value, "fxs_tx")) {
14406                confp->chan.sig = SIG_FXSLS;
14407                confp->chan.radio = 1;
14408             } else if (!strcasecmp(v->value, "fxo_tx")) {
14409                confp->chan.sig = SIG_FXOGS;
14410                confp->chan.radio = 1;
14411             } else if (!strcasecmp(v->value, "em_rx")) {
14412                confp->chan.sig = SIG_EM;
14413                confp->chan.radio = 1;
14414             } else if (!strcasecmp(v->value, "em_tx")) {
14415                confp->chan.sig = SIG_EM;
14416                confp->chan.radio = 1;
14417             } else if (!strcasecmp(v->value, "em_rxtx")) {
14418                confp->chan.sig = SIG_EM;
14419                confp->chan.radio = 2;
14420             } else if (!strcasecmp(v->value, "em_txrx")) {
14421                confp->chan.sig = SIG_EM;
14422                confp->chan.radio = 2;
14423             } else if (!strcasecmp(v->value, "sf")) {
14424                confp->chan.sig = SIG_SF;
14425                confp->chan.radio = 0;
14426             } else if (!strcasecmp(v->value, "sf_w")) {
14427                confp->chan.sig = SIG_SFWINK;
14428                confp->chan.radio = 0;
14429             } else if (!strcasecmp(v->value, "sf_featd")) {
14430                confp->chan.sig = SIG_FEATD;
14431                confp->chan.radio = 0;
14432             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14433                confp->chan.sig = SIG_FEATDMF;
14434                confp->chan.radio = 0;
14435             } else if (!strcasecmp(v->value, "sf_featb")) {
14436                confp->chan.sig = SIG_SF_FEATB;
14437                confp->chan.radio = 0;
14438             } else if (!strcasecmp(v->value, "sf")) {
14439                confp->chan.sig = SIG_SF;
14440                confp->chan.radio = 0;
14441             } else if (!strcasecmp(v->value, "sf_rx")) {
14442                confp->chan.sig = SIG_SF;
14443                confp->chan.radio = 1;
14444             } else if (!strcasecmp(v->value, "sf_tx")) {
14445                confp->chan.sig = SIG_SF;
14446                confp->chan.radio = 1;
14447             } else if (!strcasecmp(v->value, "sf_rxtx")) {
14448                confp->chan.sig = SIG_SF;
14449                confp->chan.radio = 2;
14450             } else if (!strcasecmp(v->value, "sf_txrx")) {
14451                confp->chan.sig = SIG_SF;
14452                confp->chan.radio = 2;
14453             } else if (!strcasecmp(v->value, "featd")) {
14454                confp->chan.sig = SIG_FEATD;
14455                confp->chan.radio = 0;
14456             } else if (!strcasecmp(v->value, "featdmf")) {
14457                confp->chan.sig = SIG_FEATDMF;
14458                confp->chan.radio = 0;
14459             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14460                confp->chan.sig = SIG_FEATDMF_TA;
14461                confp->chan.radio = 0;
14462             } else if (!strcasecmp(v->value, "e911")) {
14463                confp->chan.sig = SIG_E911;
14464                confp->chan.radio = 0;
14465             } else if (!strcasecmp(v->value, "fgccama")) {
14466                confp->chan.sig = SIG_FGC_CAMA;
14467                confp->chan.radio = 0;
14468             } else if (!strcasecmp(v->value, "fgccamamf")) {
14469                confp->chan.sig = SIG_FGC_CAMAMF;
14470                confp->chan.radio = 0;
14471             } else if (!strcasecmp(v->value, "featb")) {
14472                confp->chan.sig = SIG_FEATB;
14473                confp->chan.radio = 0;
14474 #ifdef HAVE_OPENR2
14475             } else if (!strcasecmp(v->value, "mfcr2")) {
14476                confp->chan.sig = SIG_MFCR2;
14477 #endif
14478 
14479 #ifdef HAVE_PRI
14480             } else if (!strcasecmp(v->value, "pri_net")) {
14481                confp->chan.radio = 0;
14482                confp->chan.sig = SIG_PRI;
14483                confp->pri.nodetype = PRI_NETWORK;
14484             } else if (!strcasecmp(v->value, "pri_cpe")) {
14485                confp->chan.sig = SIG_PRI;
14486                confp->chan.radio = 0;
14487                confp->pri.nodetype = PRI_CPE;
14488             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14489                confp->chan.sig = SIG_GR303FXOKS;
14490                confp->chan.radio = 0;
14491                confp->pri.nodetype = PRI_NETWORK;
14492             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14493                confp->chan.sig = SIG_GR303FXSKS;
14494                confp->chan.radio = 0;
14495                confp->pri.nodetype = PRI_CPE;
14496 #endif
14497             } else {
14498                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
14499             }
14500           } else if (!strcasecmp(v->name, "outsignalling")) {
14501             if (!strcasecmp(v->value, "em")) {
14502                confp->chan.outsigmod = SIG_EM;
14503             } else if (!strcasecmp(v->value, "em_e1")) {
14504                confp->chan.outsigmod = SIG_EM_E1;
14505             } else if (!strcasecmp(v->value, "em_w")) {
14506                confp->chan.outsigmod = SIG_EMWINK;
14507             } else if (!strcasecmp(v->value, "sf")) {
14508                confp->chan.outsigmod = SIG_SF;
14509             } else if (!strcasecmp(v->value, "sf_w")) {
14510                confp->chan.outsigmod = SIG_SFWINK;
14511             } else if (!strcasecmp(v->value, "sf_featd")) {
14512                confp->chan.outsigmod = SIG_FEATD;
14513             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14514                confp->chan.outsigmod = SIG_FEATDMF;
14515             } else if (!strcasecmp(v->value, "sf_featb")) {
14516                confp->chan.outsigmod = SIG_SF_FEATB;
14517             } else if (!strcasecmp(v->value, "sf")) {
14518                confp->chan.outsigmod = SIG_SF;
14519             } else if (!strcasecmp(v->value, "featd")) {
14520                confp->chan.outsigmod = SIG_FEATD;
14521             } else if (!strcasecmp(v->value, "featdmf")) {
14522                confp->chan.outsigmod = SIG_FEATDMF;
14523             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14524                confp->chan.outsigmod = SIG_FEATDMF_TA;
14525             } else if (!strcasecmp(v->value, "e911")) {
14526                confp->chan.outsigmod = SIG_E911;
14527             } else if (!strcasecmp(v->value, "fgccama")) {
14528                confp->chan.outsigmod = SIG_FGC_CAMA;
14529             } else if (!strcasecmp(v->value, "fgccamamf")) {
14530                confp->chan.outsigmod = SIG_FGC_CAMAMF;
14531             } else if (!strcasecmp(v->value, "featb")) {
14532                confp->chan.outsigmod = SIG_FEATB;
14533             } else {
14534                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
14535             }
14536 #ifdef HAVE_PRI
14537          } else if (!strcasecmp(v->name, "pridialplan")) {
14538             if (!strcasecmp(v->value, "national")) {
14539                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14540             } else if (!strcasecmp(v->value, "unknown")) {
14541                confp->pri.dialplan = PRI_UNKNOWN + 1;
14542             } else if (!strcasecmp(v->value, "private")) {
14543                confp->pri.dialplan = PRI_PRIVATE + 1;
14544             } else if (!strcasecmp(v->value, "international")) {
14545                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14546             } else if (!strcasecmp(v->value, "local")) {
14547                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14548             } else if (!strcasecmp(v->value, "dynamic")) {
14549                confp->pri.dialplan = -1;
14550             } else {
14551                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14552             }
14553          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14554             if (!strcasecmp(v->value, "national")) {
14555                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14556             } else if (!strcasecmp(v->value, "unknown")) {
14557                confp->pri.localdialplan = PRI_UNKNOWN + 1;
14558             } else if (!strcasecmp(v->value, "private")) {
14559                confp->pri.localdialplan = PRI_PRIVATE + 1;
14560             } else if (!strcasecmp(v->value, "international")) {
14561                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14562             } else if (!strcasecmp(v->value, "local")) {
14563                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14564             } else if (!strcasecmp(v->value, "dynamic")) {
14565                confp->pri.localdialplan = -1;
14566             } else {
14567                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14568             }
14569          } else if (!strcasecmp(v->name, "switchtype")) {
14570             if (!strcasecmp(v->value, "national")) 
14571                confp->pri.switchtype = PRI_SWITCH_NI2;
14572             else if (!strcasecmp(v->value, "ni1"))
14573                confp->pri.switchtype = PRI_SWITCH_NI1;
14574             else if (!strcasecmp(v->value, "dms100"))
14575                confp->pri.switchtype = PRI_SWITCH_DMS100;
14576             else if (!strcasecmp(v->value, "4ess"))
14577                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14578             else if (!strcasecmp(v->value, "5ess"))
14579                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14580             else if (!strcasecmp(v->value, "euroisdn"))
14581                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14582             else if (!strcasecmp(v->value, "qsig"))
14583                confp->pri.switchtype = PRI_SWITCH_QSIG;
14584             else {
14585                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
14586                return -1;
14587             }
14588          } else if (!strcasecmp(v->name, "nsf")) {
14589             if (!strcasecmp(v->value, "sdn"))
14590                confp->pri.nsf = PRI_NSF_SDN;
14591             else if (!strcasecmp(v->value, "megacom"))
14592                confp->pri.nsf = PRI_NSF_MEGACOM;
14593             else if (!strcasecmp(v->value, "tollfreemegacom"))
14594                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
14595             else if (!strcasecmp(v->value, "accunet"))
14596                confp->pri.nsf = PRI_NSF_ACCUNET;
14597             else if (!strcasecmp(v->value, "none"))
14598                confp->pri.nsf = PRI_NSF_NONE;
14599             else {
14600                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
14601                confp->pri.nsf = PRI_NSF_NONE;
14602             }
14603          } else if (!strcasecmp(v->name, "priindication")) {
14604             if (!strcasecmp(v->value, "outofband"))
14605                confp->chan.priindication_oob = 1;
14606             else if (!strcasecmp(v->value, "inband"))
14607                confp->chan.priindication_oob = 0;
14608             else
14609                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
14610                   v->value, v->lineno);
14611          } else if (!strcasecmp(v->name, "priexclusive")) {
14612             confp->chan.priexclusive = ast_true(v->value);
14613          } else if (!strcasecmp(v->name, "internationalprefix")) {
14614             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14615          } else if (!strcasecmp(v->name, "nationalprefix")) {
14616             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14617          } else if (!strcasecmp(v->name, "localprefix")) {
14618             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14619          } else if (!strcasecmp(v->name, "privateprefix")) {
14620             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14621          } else if (!strcasecmp(v->name, "unknownprefix")) {
14622             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14623          } else if (!strcasecmp(v->name, "resetinterval")) {
14624             if (!strcasecmp(v->value, "never"))
14625                confp->pri.resetinterval = -1;
14626             else if (atoi(v->value) >= 60)
14627                confp->pri.resetinterval = atoi(v->value);
14628             else
14629                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
14630                   v->value, v->lineno);
14631          } else if (!strcasecmp(v->name, "minunused")) {
14632             confp->pri.minunused = atoi(v->value);
14633          } else if (!strcasecmp(v->name, "minidle")) {
14634             confp->pri.minidle = atoi(v->value); 
14635          } else if (!strcasecmp(v->name, "idleext")) {
14636             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14637          } else if (!strcasecmp(v->name, "idledial")) {
14638             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14639          } else if (!strcasecmp(v->name, "overlapdial")) {
14640             if (ast_true(v->value)) {
14641                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14642             } else if (!strcasecmp(v->value, "incoming")) {
14643                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14644             } else if (!strcasecmp(v->value, "outgoing")) {
14645                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14646             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14647                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14648             } else {
14649                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14650             }
14651 #ifdef HAVE_PRI_INBANDDISCONNECT
14652          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14653             confp->pri.inbanddisconnect = ast_true(v->value);
14654 #endif
14655          } else if (!strcasecmp(v->name, "pritimer")) {
14656 #ifdef PRI_GETSET_TIMERS
14657             char tmp[20];
14658             char *timerc;
14659             char *c;
14660             int timer;
14661             int timeridx;
14662 
14663             ast_copy_string(tmp, v->value, sizeof(tmp));
14664             c = tmp;
14665             timerc = strsep(&c, ",");
14666             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14667                timeridx = pri_timer2idx(timerc);
14668                timer = atoi(c);
14669                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14670                   ast_log(LOG_WARNING,
14671                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14672                      v->lineno);
14673                } else if (!timer) {
14674                   ast_log(LOG_WARNING,
14675                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14676                      c, timerc, v->lineno);
14677                } else {
14678                   pritimers[timeridx] = timer;
14679                }
14680             } else {
14681                ast_log(LOG_WARNING,
14682                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14683                   v->value, v->lineno);
14684             }
14685 #endif /* PRI_GETSET_TIMERS */
14686          } else if (!strcasecmp(v->name, "facilityenable")) {
14687             confp->pri.facilityenable = ast_true(v->value);
14688 #endif /* HAVE_PRI */
14689 
14690 #ifdef HAVE_OPENR2
14691          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
14692             ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
14693             ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY  KNOW WHAT YOU ARE DOING*.\n", mfcr2_cur_r2proto_file);
14694          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
14695             ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
14696          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
14697             mfcr2_cur_variant = openr2_proto_get_variant(v->value);
14698             if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
14699                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
14700             }
14701          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
14702             mfcr2_cur_mfback_timeout = atoi(v->value);
14703             if (!mfcr2_cur_mfback_timeout) {
14704                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
14705                mfcr2_cur_mfback_timeout = -1;
14706             } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
14707                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
14708             }
14709          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
14710             mfcr2_cur_metering_pulse_timeout = atoi(v->value);
14711             if (mfcr2_cur_metering_pulse_timeout > 500) {
14712                ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
14713             }
14714 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
14715          } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
14716             mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
14717          } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
14718             mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
14719          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
14720             mfcr2_cur_dtmf_time_on = atoi(v->value);
14721          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
14722             mfcr2_cur_dtmf_time_off = atoi(v->value);
14723 #endif
14724          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
14725             mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
14726          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
14727             mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
14728          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
14729             mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
14730          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
14731             mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
14732          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
14733             mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
14734          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
14735             mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
14736          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
14737             mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
14738          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
14739             mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
14740          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
14741             mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
14742          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
14743             mfcr2_cur_max_ani = atoi(v->value);
14744             if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
14745                mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
14746             }
14747          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
14748             mfcr2_cur_max_dnis = atoi(v->value);
14749             if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
14750                mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
14751             }
14752          } else if (!strcasecmp(v->name, "mfcr2_category")) {
14753             mfcr2_cur_category = openr2_proto_get_category(v->value);
14754             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
14755                mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
14756                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 
14757                      v->value, v->lineno);
14758             }
14759          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
14760             openr2_log_level_t tmplevel;
14761             char *toklevel = NULL;
14762             char *saveptr = NULL;
14763             char *logval = ast_strdupa(v->value);
14764             toklevel = strtok_r(logval, ",", &saveptr);
14765             if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14766                ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
14767             } else if (OR2_LOG_NOTHING == tmplevel) {
14768                mfcr2_cur_loglevel = tmplevel;
14769             } else {
14770                mfcr2_cur_loglevel |= tmplevel;
14771                while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14772                   if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14773                      ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
14774                      continue;
14775                   }
14776                   mfcr2_cur_loglevel |= tmplevel;
14777                }
14778             }
14779 #endif /* HAVE_OPENR2 */
14780 
14781          } else if (!strcasecmp(v->name, "cadence")) {
14782             /* setup to scan our argument */
14783             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14784             int i;
14785             struct dahdi_ring_cadence new_cadence;
14786             int cid_location = -1;
14787             int firstcadencepos = 0;
14788             char original_args[80];
14789             int cadence_is_ok = 1;
14790 
14791             ast_copy_string(original_args, v->value, sizeof(original_args));
14792             /* 16 cadences allowed (8 pairs) */
14793             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &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]);
14794    
14795             /* Cadence must be even (on/off) */
14796             if (element_count % 2 == 1) {
14797                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
14798                cadence_is_ok = 0;
14799             }
14800    
14801             /* Ring cadences cannot be negative */
14802             for (i = 0; i < element_count; i++) {
14803                if (c[i] == 0) {
14804                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
14805                   cadence_is_ok = 0;
14806                   break;
14807                } else if (c[i] < 0) {
14808                   if (i % 2 == 1) {
14809                      /* Silence duration, negative possibly okay */
14810                      if (cid_location == -1) {
14811                         cid_location = i;
14812                         c[i] *= -1;
14813                      } else {
14814                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
14815                         cadence_is_ok = 0;
14816                         break;
14817                      }
14818                   } else {
14819                      if (firstcadencepos == 0) {
14820                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
14821                                  /* duration will be passed negative to the DAHDI driver */
14822                      } else {
14823                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
14824                         cadence_is_ok = 0;
14825                         break;
14826                      }
14827                   }
14828                }
14829             }
14830    
14831             /* Substitute our scanned cadence */
14832             for (i = 0; i < 16; i++) {
14833                new_cadence.ringcadence[i] = c[i];
14834             }
14835    
14836             if (cadence_is_ok) {
14837                /* ---we scanned it without getting annoyed; now some sanity checks--- */
14838                if (element_count < 2) {
14839                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
14840                } else {
14841                   if (cid_location == -1) {
14842                      /* user didn't say; default to first pause */
14843                      cid_location = 1;
14844                   } else {
14845                      /* convert element_index to cidrings value */
14846                      cid_location = (cid_location + 1) / 2;
14847                   }
14848                   /* ---we like their cadence; try to install it--- */
14849                   if (!user_has_defined_cadences++)
14850                      /* this is the first user-defined cadence; clear the default user cadences */
14851                      num_cadence = 0;
14852                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
14853                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
14854                   else {
14855                      cadences[num_cadence] = new_cadence;
14856                      cidrings[num_cadence++] = cid_location;
14857                      if (option_verbose > 2)
14858                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
14859                   }
14860                }
14861             }
14862          } else if (!strcasecmp(v->name, "ringtimeout")) {
14863             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
14864          } else if (!strcasecmp(v->name, "prewink")) {
14865             confp->timing.prewinktime = atoi(v->value);
14866          } else if (!strcasecmp(v->name, "preflash")) {
14867             confp->timing.preflashtime = atoi(v->value);
14868          } else if (!strcasecmp(v->name, "wink")) {
14869             confp->timing.winktime = atoi(v->value);
14870          } else if (!strcasecmp(v->name, "flash")) {
14871             confp->timing.flashtime = atoi(v->value);
14872          } else if (!strcasecmp(v->name, "start")) {
14873             confp->timing.starttime = atoi(v->value);
14874          } else if (!strcasecmp(v->name, "rxwink")) {
14875             confp->timing.rxwinktime = atoi(v->value);
14876          } else if (!strcasecmp(v->name, "rxflash")) {
14877             confp->timing.rxflashtime = atoi(v->value);
14878          } else if (!strcasecmp(v->name, "debounce")) {
14879             confp->timing.debouncetime = atoi(v->value);
14880          } else if (!strcasecmp(v->name, "toneduration")) {
14881             int toneduration;
14882             int ctlfd;
14883             int res;
14884             struct dahdi_dialparams dps;
14885 
14886             ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
14887 
14888             if (ctlfd == -1) {
14889                ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
14890                return -1;
14891             }
14892 
14893             toneduration = atoi(v->value);
14894             if (toneduration > -1) {
14895                memset(&dps, 0, sizeof(dps));
14896 
14897                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
14898                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
14899                if (res < 0) {
14900                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
14901                   close(ctlfd);
14902                   return -1;
14903                }
14904             }
14905             close(ctlfd);
14906          } else if (!strcasecmp(v->name, "defaultcic")) {
14907             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
14908          } else if (!strcasecmp(v->name, "defaultozz")) {
14909             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
14910          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
14911             dtmfcid_level = atoi(v->value);
14912          } 
14913       } else if (!skipchannels)
14914          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
14915    }
14916    if (dahdichan[0]) { 
14917       /* The user has set 'dahdichan' */
14918       /*< \todo pass proper line number instead of 0 */
14919       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
14920          return -1;
14921       }
14922    }
14923    /*< \todo why check for the pseudo in the per-channel section.
14924     * Any actual use for manual setup of the pseudo channel? */
14925    if (!found_pseudo && reload != 1) {
14926       /* use the default configuration for a channel, so
14927          that any settings from real configured channels
14928          don't "leak" into the pseudo channel config
14929       */
14930       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
14931 
14932       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
14933 
14934       if (tmp) {
14935          if (option_verbose > 2)
14936             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
14937       } else {
14938          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
14939       }
14940    }
14941    return 0;
14942 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 10974 of file chan_dahdi.c.

Referenced by pri_dchannel().

10975 {
10976    switch (redirectingreason) {
10977    case 0:
10978       return "UNKNOWN";
10979    case 1:
10980       return "BUSY";
10981    case 2:
10982       return "NO_REPLY";
10983    case 0xF:
10984       return "UNCONDITIONAL";
10985    default:
10986       return "NOREDIRECT";
10987    }
10988 }

static int reload ( void   )  [static]

Definition at line 15285 of file chan_dahdi.c.

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

15286 {
15287    int res = 0;
15288 
15289    res = setup_dahdi(1);
15290    if (res) {
15291       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15292       return -1;
15293    }
15294    return 0;
15295 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 2374 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_hangup().

02375 {
02376    p->confno = -1;
02377    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02378    if (p->subs[SUB_REAL].dfd > -1) {
02379       struct dahdi_confinfo zi;
02380 
02381       memset(&zi, 0, sizeof(zi));
02382       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02383          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02384    }
02385    return 0;
02386 }

static int restart_monitor ( void   )  [static]

Definition at line 8953 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, and monlock.

Referenced by dahdi_hangup(), dahdi_request(), and setup_dahdi().

08954 {
08955    pthread_attr_t attr;
08956    pthread_attr_init(&attr);
08957    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08958    /* If we're supposed to be stopped -- stay stopped */
08959    if (monitor_thread == AST_PTHREADT_STOP)
08960       return 0;
08961    ast_mutex_lock(&monlock);
08962    if (monitor_thread == pthread_self()) {
08963       ast_mutex_unlock(&monlock);
08964       ast_log(LOG_WARNING, "Cannot kill myself\n");
08965       return -1;
08966    }
08967    if (monitor_thread != AST_PTHREADT_NULL) {
08968       /* Wake up the thread */
08969       pthread_kill(monitor_thread, SIGURG);
08970    } else {
08971       /* Start a new monitor */
08972       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08973          ast_mutex_unlock(&monlock);
08974          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08975          pthread_attr_destroy(&attr);
08976          return -1;
08977       }
08978    }
08979    ast_mutex_unlock(&monlock);
08980    pthread_attr_destroy(&attr);
08981    return 0;
08982 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2707 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::dfd, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), dahdi_read(), handle_init_event(), and send_callerid().

02708 {
02709    int res;
02710    if (p->saveconf.confmode) {
02711       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02712       p->saveconf.confmode = 0;
02713       if (res) {
02714          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02715          return -1;
02716       }
02717       if (option_debug)
02718          ast_log(LOG_DEBUG, "Restored conferencing\n");
02719    }
02720    return 0;
02721 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 2634 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::dfd, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.

Referenced by dahdi_hangup(), and ss_thread().

02635 {
02636    int res;
02637 
02638    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02639    if (res) {
02640       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02641       return -1;
02642    }
02643 
02644    return 0;
02645 }

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2680 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::dfd, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_callwait(), and dahdi_handle_event().

02681 {
02682    struct dahdi_confinfo c;
02683    int res;
02684    if (p->saveconf.confmode) {
02685       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02686       return -1;
02687    }
02688    p->saveconf.chan = 0;
02689    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02690    if (res) {
02691       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02692       p->saveconf.confmode = 0;
02693       return -1;
02694    }
02695    memset(&c, 0, sizeof(c));
02696    c.confmode = DAHDI_CONF_NORMAL;
02697    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02698    if (res) {
02699       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02700       return -1;
02701    }
02702    if (option_debug)
02703       ast_log(LOG_DEBUG, "Disabled conferencing\n");
02704    return 0;
02705 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 2748 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::callwaitcas, CALLWAITING_SUPPRESS_SAMPLES, dahdi_pvt::cid_suppress_expire, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), dahdi_subchannel::dfd, errno, free, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_call(), dahdi_callwait(), dahdi_read(), and send_cwcidspill().

02749 {
02750    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02751    int res;
02752    /* Take out of linear mode if necessary */
02753    if (p->subs[SUB_REAL].linear) {
02754       p->subs[SUB_REAL].linear = 0;
02755       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02756    }
02757    while (p->cidpos < p->cidlen) {
02758       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02759       if (res < 0) {
02760          if (errno == EAGAIN)
02761             return 0;
02762          else {
02763             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02764             return -1;
02765          }
02766       }
02767       if (!res)
02768          return 0;
02769       p->cidpos += res;
02770    }
02771    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
02772    free(p->cidspill);
02773    p->cidspill = NULL;
02774    if (p->callwaitcas) {
02775       /* Wait for CID/CW to expire */
02776       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02777       p->cid_suppress_expire = p->cidcwexpire;
02778    } else
02779       restore_conference(p);
02780    return 0;
02781 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

Definition at line 2725 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verbose(), dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, MAX_CALLERID_SIZE, option_verbose, READ_SIZE, send_callerid(), and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_dtmf().

02726 {
02727    p->callwaitcas = 0;
02728    p->cidcwexpire = 0;
02729    p->cid_suppress_expire = 0;
02730    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02731       return -1;
02732    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02733    /* Make sure we account for the end */
02734    p->cidlen += READ_SIZE * 4;
02735    p->cidpos = 0;
02736    send_callerid(p);
02737    if (option_verbose > 2)
02738       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02739    return 0;
02740 }

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

Definition at line 3405 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::call, dahdi_pvt::lock, LOG_DEBUG, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), and ast_channel::tech_pvt.

Referenced by dahdi_send_keypad_facility_exec(), and zap_send_keypad_facility_exec().

03406 {
03407    /* Data will be our digit string */
03408    struct dahdi_pvt *p;
03409    char *digits = (char *) data;
03410 
03411    if (ast_strlen_zero(digits)) {
03412       ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03413       return -1;
03414    }
03415 
03416    p = (struct dahdi_pvt *)chan->tech_pvt;
03417 
03418    if (!p) {
03419       ast_log(LOG_DEBUG, "Unable to find technology private\n");
03420       return -1;
03421    }
03422 
03423    ast_mutex_lock(&p->lock);
03424 
03425    if (!p->pri || !p->call) {
03426       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03427       ast_mutex_unlock(&p->lock);
03428       return -1;
03429    }
03430 
03431    if (!pri_grab(p, p->pri)) {
03432       pri_keypad_facility(p->pri->pri, p->call, digits);
03433       pri_rel(p->pri);
03434    } else {
03435       ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03436       ast_mutex_unlock(&p->lock);
03437       return -1;
03438    }
03439 
03440    ast_mutex_unlock(&p->lock);
03441 
03442    return 0;
03443 }

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

Definition at line 2615 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

Referenced by bump_gains(), dahdi_call(), mkintf(), pri_dchannel(), and restore_gains().

02616 {
02617    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02618 }

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

Definition at line 2597 of file chan_dahdi.c.

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

Referenced by dahdi_setoption(), and set_actual_gain().

02598 {
02599    struct dahdi_gains g;
02600    int res;
02601 
02602    memset(&g, 0, sizeof(g));
02603    g.chan = chan;
02604    res = ioctl(fd, DAHDI_GETGAINS, &g);
02605    if (res) {
02606       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02607       return res;
02608    }
02609 
02610    fill_rxgain(&g, gain, law);
02611 
02612    return ioctl(fd, DAHDI_SETGAINS, &g);
02613 }

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

Definition at line 2578 of file chan_dahdi.c.

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

Referenced by dahdi_setoption(), and set_actual_gain().

02579 {
02580    struct dahdi_gains g;
02581    int res;
02582 
02583    memset(&g, 0, sizeof(g));
02584    g.chan = chan;
02585    res = ioctl(fd, DAHDI_GETGAINS, &g);
02586    if (res) {
02587       if (option_debug)
02588          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02589       return res;
02590    }
02591 
02592    fill_txgain(&g, gain, law);
02593 
02594    return ioctl(fd, DAHDI_SETGAINS, &g);
02595 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 14944 of file chan_dahdi.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), CHAN_ZAP_MODE, dahdi_chan_conf_default(), dahdi_chan_mode, global_jbconf, iflock, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, master, mfcr2_monitor(), ast_variable::name, ast_variable::next, NUM_DCHANS, NUM_SPANS, option_verbose, pri_create_spanmap(), pri_create_trunkgroup(), pris, process_dahdi(), r2links, restart_monitor(), start_pri(), ast_variable::value, and VERBOSE_PREFIX_2.

Referenced by dahdi_restart(), load_module(), and reload().

14945 {
14946    struct ast_config *cfg;
14947    struct ast_variable *v;
14948    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
14949    int res;
14950 
14951 #ifdef HAVE_PRI
14952    char *c;
14953    int spanno;
14954    int i, x;
14955    int logicalspan;
14956    int trunkgroup;
14957    int dchannels[NUM_DCHANS];
14958 #endif
14959 
14960 #ifdef HAVE_ZAPTEL
14961    int load_from_zapata_conf = 1;
14962 #else
14963    int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
14964 #endif
14965 
14966    if (load_from_zapata_conf) {
14967       if (!(cfg = ast_config_load("zapata.conf"))) {
14968          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
14969          return 0;
14970       }
14971    } else {
14972       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
14973          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
14974          return 0;
14975       }
14976    }
14977 
14978    /* It's a little silly to lock it, but we mind as well just to be sure */
14979    ast_mutex_lock(&iflock);
14980 #ifdef HAVE_PRI
14981    if (reload != 1) {
14982       /* Process trunkgroups first */
14983       v = ast_variable_browse(cfg, "trunkgroups");
14984       while (v) {
14985          if (!strcasecmp(v->name, "trunkgroup")) {
14986             trunkgroup = atoi(v->value);
14987             if (trunkgroup > 0) {
14988                if ((c = strchr(v->value, ','))) {
14989                   i = 0;
14990                   memset(dchannels, 0, sizeof(dchannels));
14991                   while (c && (i < NUM_DCHANS)) {
14992                      dchannels[i] = atoi(c + 1);
14993                      if (dchannels[i] < 0) {
14994                         ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14995                      } else
14996                         i++;
14997                      c = strchr(c + 1, ',');
14998                   }
14999                   if (i) {
15000                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15001                         ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
15002                      } else if (option_verbose > 1)
15003                         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");
15004                   } else
15005                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15006                } else
15007                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15008             } else
15009                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15010          } else if (!strcasecmp(v->name, "spanmap")) {
15011             spanno = atoi(v->value);
15012             if (spanno > 0) {
15013                if ((c = strchr(v->value, ','))) {
15014                   trunkgroup = atoi(c + 1);
15015                   if (trunkgroup > 0) {
15016                      if ((c = strchr(c + 1, ','))) 
15017                         logicalspan = atoi(c + 1);
15018                      else
15019                         logicalspan = 0;
15020                      if (logicalspan >= 0) {
15021                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15022                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15023                         } else if (option_verbose > 1) 
15024                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15025                      } else
15026                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
15027                   } else
15028                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15029                } else
15030                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15031             } else
15032                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15033          } else {
15034             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15035          }
15036          v = v->next;
15037       }
15038    }
15039 #endif
15040    
15041    /* Copy the default jb config over global_jbconf */
15042    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
15043 
15044    v = ast_variable_browse(cfg, "channels");
15045    res = process_dahdi(&conf, "", v, reload, 0);
15046    ast_mutex_unlock(&iflock);
15047    ast_config_destroy(cfg);
15048    if (res)
15049       return res;
15050    cfg = ast_config_load("users.conf");
15051    if (cfg) {
15052       char *cat;
15053 
15054       /* Reset conf back to defaults, so values from chan_dahdi.conf don't leak in. */
15055       conf = dahdi_chan_conf_default();
15056       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
15057       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15058          if (!strcasecmp(cat, "general"))
15059             continue;
15060          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
15061             struct dahdi_chan_conf sect_conf;
15062             memcpy(&sect_conf, &conf, sizeof(sect_conf));
15063 
15064             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
15065          }
15066       }
15067       ast_config_destroy(cfg);
15068    }
15069 #ifdef HAVE_PRI
15070    if (reload != 1) {
15071       for (x = 0; x < NUM_SPANS; x++) {
15072          if (pris[x].pvts[0]) {
15073             if (start_pri(pris + x)) {
15074                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15075                return -1;
15076             } else if (option_verbose > 1)
15077                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
15078          }
15079       }
15080    }
15081 #endif
15082 
15083 #ifdef HAVE_OPENR2
15084    if (reload != 1) {
15085       int x;
15086       for (x = 0; x < NUM_SPANS; x++) {
15087          if (r2links[x].protocol_context) {
15088             if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
15089                ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
15090                return -1;
15091             } else {
15092                ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
15093             }
15094          }
15095       }
15096    }
15097 #endif
15098 
15099    /* And start the monitor for the first time */
15100    restart_monitor();
15101    return 0;
15102 }

static int sig_pri_available ( struct dahdi_pvt pvt  )  [static]

Definition at line 9775 of file chan_dahdi.c.

References dahdi_pvt::allocated, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pri::lock, dahdi_pvt::pri, and sig_pri_available_check().

Referenced by available().

09776 {
09777    struct dahdi_pvt *p = pvt;
09778    struct dahdi_pri *pri;
09779 
09780    if (!p->pri) {
09781       /* Something is wrong here.  A PRI channel without the pri pointer? */
09782       return 0;
09783    }
09784    pri = p->pri;
09785 
09786    ast_mutex_lock(&pri->lock);
09787    if (sig_pri_available_check(p)) {
09788       p->allocated = 1;
09789       ast_mutex_unlock(&pri->lock);
09790       return 1;
09791    }
09792 
09793    ast_mutex_unlock(&pri->lock);
09794    return 0;
09795 }

static int sig_pri_available_check ( struct dahdi_pvt pvt  )  [static]

Definition at line 9761 of file chan_dahdi.c.

References sig_pri_is_chan_available().

Referenced by sig_pri_available().

09762 {
09763    /*
09764     * If interface is available for use
09765     * then the channel is available.
09766     */
09767    if (sig_pri_is_chan_available(pvt)) {
09768       return 1;
09769    }
09770    return 0;
09771 }

static int sig_pri_is_chan_available ( struct dahdi_pvt pvt  )  [static]

Definition at line 9744 of file chan_dahdi.c.

References sig_pri_is_chan_in_use().

Referenced by pri_dchannel(), pri_find_empty_chan(), pri_fixup_principle(), and sig_pri_available_check().

09745 {
09746    return !sig_pri_is_chan_in_use(pvt);
09747 }

static int sig_pri_is_chan_in_use ( struct dahdi_pvt pvt  )  [static]

Definition at line 9728 of file chan_dahdi.c.

References dahdi_pvt::allocated, dahdi_pvt::call, dahdi_pvt::inalarm, dahdi_pvt::owner, and dahdi_pvt::resetting.

Referenced by pri_check_restart(), and sig_pri_is_chan_available().

09729 {
09730    return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm;
09731 }

static void sig_pri_kill_call ( struct dahdi_pri pri,
q931_call *  call,
int  cause 
) [static]

Definition at line 10532 of file chan_dahdi.c.

References AST_CONTROL_HANGUP, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::call, ast_channel::hangupcause, dahdi_pvt::lock, dahdi_pvt::owner, dahdi_pri::pri, pri_find_principle_by_call(), pri_queue_control(), and dahdi_pri::pvts.

Referenced by pri_find_fixup_principle().

10533 {
10534    int chanpos;
10535 
10536    chanpos = pri_find_principle_by_call(pri, call);
10537    if (chanpos < 0) {
10538       pri_hangup(pri->pri, call, cause);
10539       return;
10540    }
10541    ast_mutex_lock(&pri->pvts[chanpos]->lock);
10542    if (!pri->pvts[chanpos]->owner) {
10543       pri_hangup(pri->pri, call, cause);
10544       pri->pvts[chanpos]->call = NULL;
10545       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10546       return;
10547    }
10548    pri->pvts[chanpos]->owner->hangupcause = cause;
10549    pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
10550    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10551 }

static void sig_pri_lock_owner ( struct dahdi_pri pri,
int  chanpos 
) [static]

Definition at line 10418 of file chan_dahdi.c.

References ast_channel_trylock, ast_mutex_lock(), ast_mutex_unlock(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_pvt::owner, and dahdi_pri::pvts.

Referenced by pri_fixup_principle(), and pri_queue_frame().

10419 {
10420    for (;;) {
10421       if (!pri->pvts[chanpos]->owner) {
10422          /* There is no owner lock to get. */
10423          break;
10424       }
10425       if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
10426          /* We got the lock */
10427          break;
10428       }
10429       /* We must unlock the PRI to avoid the possibility of a deadlock */
10430       ast_mutex_unlock(&pri->lock);
10431       DEADLOCK_AVOIDANCE(&pri->pvts[chanpos]->lock);
10432       ast_mutex_lock(&pri->lock);
10433    }
10434 }

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

Definition at line 7233 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, ast_clear_flag, ast_cond_signal(), AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_put(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, 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_mutex_lock(), ast_mutex_unlock(), 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_set_flag, 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(), dahdi_pvt::call, dahdi_pvt::call_forward, dahdi_pvt::call_level, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, dahdi_pvt::cid_name, ast_callerid::cid_num, dahdi_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_RING, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_chan_name, dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, DAHDI_OVERLAPDIAL_INCOMING, dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dnd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, dahdi_pvt::exten, exten, ast_frame::frametype, free, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, dahdi_pvt::inalarm, ISTRUNK, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event(), my_getsigstr(), name, NEED_MFDETECT, option_debug, option_verbose, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PVT_TO_CHANNEL, quit, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_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, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, dahdi_pvt::span, ss_thread_lock, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event(), do_monitor(), handle_init_event(), and pri_dchannel().

07234 {
07235    struct ast_channel *chan = data;
07236    struct dahdi_pvt *p = chan->tech_pvt;
07237    char exten[AST_MAX_EXTENSION] = "";
07238    char exten2[AST_MAX_EXTENSION] = "";
07239    unsigned char buf[256];
07240    char dtmfcid[300];
07241    char dtmfbuf[300];
07242    struct callerid_state *cs = NULL;
07243    char *name = NULL, *number = NULL;
07244    int distMatches;
07245    int curRingData[3];
07246    int receivedRingT;
07247    int counter1;
07248    int counter;
07249    int samples = 0;
07250    struct ast_smdi_md_message *smdi_msg = NULL;
07251    int flags = 0;
07252    int i;
07253    int timeout;
07254    int getforward = 0;
07255    char *s1, *s2;
07256    int len = 0;
07257    int res;
07258    int index;
07259 
07260    ast_mutex_lock(&ss_thread_lock);
07261    ss_thread_count++;
07262    ast_mutex_unlock(&ss_thread_lock);
07263    /* in the bizarre case where the channel has become a zombie before we
07264       even get started here, abort safely
07265    */
07266    if (!p) {
07267       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07268       ast_hangup(chan);
07269       goto quit;
07270    }
07271    if (option_verbose > 2) 
07272       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
07273    index = dahdi_get_index(chan, p, 0);
07274    if (index < 0) {
07275       ast_hangup(chan);
07276       goto quit;
07277    }
07278    if (p->dsp)
07279       ast_dsp_digitreset(p->dsp);
07280    switch (p->sig) {
07281 #ifdef HAVE_PRI
07282    case SIG_PRI:
07283       /* Now loop looking for an extension */
07284       ast_copy_string(exten, p->exten, sizeof(exten));
07285       len = strlen(exten);
07286       res = 0;
07287       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07288          if (len && !ast_ignore_pattern(chan->context, exten))
07289             tone_zone_play_tone(p->subs[index].dfd, -1);
07290          else
07291             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07292          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07293             timeout = matchdigittimeout;
07294          else
07295             timeout = gendigittimeout;
07296          res = ast_waitfordigit(chan, timeout);
07297          if (res < 0) {
07298             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07299             ast_hangup(chan);
07300             goto quit;
07301          } else if (res) {
07302             exten[len++] = res;
07303             exten[len] = '\0';
07304          } else
07305             break;
07306       }
07307       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
07308       if (ast_strlen_zero(exten)) {
07309          if (option_verbose > 2)
07310             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
07311          exten[0] = 's';
07312          exten[1] = '\0';
07313       }
07314       tone_zone_play_tone(p->subs[index].dfd, -1);
07315       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07316          /* Start the real PBX */
07317          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07318          if (p->dsp) {
07319             ast_dsp_digitreset(p->dsp);
07320          }
07321 #if defined(ISSUE_16789)
07322          /*
07323           * Conditionaled out this code to effectively revert the Mantis
07324           * issue 16789 change.  It breaks overlap dialing through
07325           * Asterisk.  There is not enough information available at this
07326           * point to know if dialing is complete.  The
07327           * ast_exists_extension(), ast_matchmore_extension(), and
07328           * ast_canmatch_extension() calls are not adequate to detect a
07329           * dial through extension pattern of "_9!".
07330           *
07331           * Workaround is to use the dialplan Proceeding() application
07332           * early on non-dial through extensions.
07333           */
07334          if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
07335             && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07336             ast_mutex_lock(&p->lock);
07337             if (p->pri->pri) {
07338                if (!pri_grab(p, p->pri)) {
07339                   if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
07340                      p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07341                   }
07342                   pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07343                   pri_rel(p->pri);
07344                } else {
07345                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07346                }
07347             }
07348             ast_mutex_unlock(&p->lock);
07349          }
07350 #endif   /* defined(ISSUE_16789) */
07351 
07352          dahdi_enable_ec(p);
07353          ast_setstate(chan, AST_STATE_RING);
07354          res = ast_pbx_run(chan);
07355          if (res) {
07356             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07357          }
07358       } else {
07359          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07360          chan->hangupcause = AST_CAUSE_UNALLOCATED;
07361          ast_hangup(chan);
07362          p->exten[0] = '\0';
07363          /* Since we send release complete here, we won't get one */
07364          p->call = NULL;
07365       }
07366       goto quit;
07367       break;
07368 #endif
07369    case SIG_FEATD:
07370    case SIG_FEATDMF:
07371    case SIG_FEATDMF_TA:
07372    case SIG_E911:
07373    case SIG_FGC_CAMAMF:
07374    case SIG_FEATB:
07375    case SIG_EMWINK:
07376    case SIG_SF_FEATD:
07377    case SIG_SF_FEATDMF:
07378    case SIG_SF_FEATB:
07379    case SIG_SFWINK:
07380       if (dahdi_wink(p, index))  
07381          goto quit;
07382       /* Fall through */
07383    case SIG_EM:
07384    case SIG_EM_E1:
07385    case SIG_SF:
07386    case SIG_FGC_CAMA:
07387       res = tone_zone_play_tone(p->subs[index].dfd, -1);
07388       if (p->dsp)
07389          ast_dsp_digitreset(p->dsp);
07390       /* set digit mode appropriately */
07391       if (p->dsp) {
07392          if (NEED_MFDETECT(p))
07393             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
07394          else 
07395             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07396       }
07397       memset(dtmfbuf, 0, sizeof(dtmfbuf));
07398       /* Wait for the first digit only if immediate=no */
07399       if (!p->immediate)
07400          /* Wait for the first digit (up to 5 seconds). */
07401          res = ast_waitfordigit(chan, 5000);
07402       else
07403          res = 0;
07404       if (res > 0) {
07405          /* save first char */
07406          dtmfbuf[0] = res;
07407          switch (p->sig) {
07408          case SIG_FEATD:
07409          case SIG_SF_FEATD:
07410             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07411             if (res > 0)
07412                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07413             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07414             break;
07415          case SIG_FEATDMF_TA:
07416             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07417             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07418             if (dahdi_wink(p, index)) goto quit;
07419             dtmfbuf[0] = 0;
07420             /* Wait for the first digit (up to 5 seconds). */
07421             res = ast_waitfordigit(chan, 5000);
07422             if (res <= 0) break;
07423             dtmfbuf[0] = res;
07424             /* fall through intentionally */
07425          case SIG_FEATDMF:
07426          case SIG_E911:
07427          case SIG_FGC_CAMAMF:
07428          case SIG_SF_FEATDMF:
07429             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07430             /* if international caca, do it again to get real ANO */
07431             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07432             {
07433                if (dahdi_wink(p, index)) goto quit;
07434                dtmfbuf[0] = 0;
07435                /* Wait for the first digit (up to 5 seconds). */
07436                res = ast_waitfordigit(chan, 5000);
07437                if (res <= 0) break;
07438                dtmfbuf[0] = res;
07439                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07440             }
07441             if (res > 0) {
07442                /* if E911, take off hook */
07443                if (p->sig == SIG_E911)
07444                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07445                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07446             }
07447             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07448             break;
07449          case SIG_FEATB:
07450          case SIG_SF_FEATB:
07451             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07452             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07453             break;
07454          case SIG_EMWINK:
07455             /* if we received a '*', we are actually receiving Feature Group D
07456                dial syntax, so use that mode; otherwise, fall through to normal
07457                mode
07458             */
07459             if (res == '*') {
07460                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07461                if (res > 0)
07462                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07463                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07464                break;
07465             }
07466          default:
07467             /* If we got the first digit, get the rest */
07468             len = 1;
07469             dtmfbuf[len] = '\0';
07470             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07471                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07472                   timeout = matchdigittimeout;
07473                } else {
07474                   timeout = gendigittimeout;
07475                }
07476                res = ast_waitfordigit(chan, timeout);
07477                if (res < 0) {
07478                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07479                   ast_hangup(chan);
07480                   goto quit;
07481                } else if (res) {
07482                   dtmfbuf[len++] = res;
07483                   dtmfbuf[len] = '\0';
07484                } else {
07485                   break;
07486                }
07487             }
07488             break;
07489          }
07490       }
07491       if (res == -1) {
07492          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
07493          ast_hangup(chan);
07494          goto quit;
07495       } else if (res < 0) {
07496          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
07497          ast_hangup(chan);
07498          goto quit;
07499       }
07500 
07501       if (p->sig == SIG_FGC_CAMA) {
07502          char anibuf[100];
07503 
07504          if (ast_safe_sleep(chan,1000) == -1) {
07505                            ast_hangup(chan);
07506                            goto quit;
07507          }
07508                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07509                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07510                         res = my_getsigstr(chan, anibuf, "#", 10000);
07511                         if ((res > 0) && (strlen(anibuf) > 2)) {
07512             if (anibuf[strlen(anibuf) - 1] == '#')
07513                anibuf[strlen(anibuf) - 1] = 0;
07514             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07515          }
07516                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07517       }
07518 
07519       ast_copy_string(exten, dtmfbuf, sizeof(exten));
07520       if (ast_strlen_zero(exten))
07521          ast_copy_string(exten, "s", sizeof(exten));
07522       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07523          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
07524          if (exten[0] == '*') {
07525             char *stringp=NULL;
07526             ast_copy_string(exten2, exten, sizeof(exten2));
07527             /* Parse out extension and callerid */
07528             stringp=exten2 +1;
07529             s1 = strsep(&stringp, "*");
07530             s2 = strsep(&stringp, "*");
07531             if (s2) {
07532                if (!ast_strlen_zero(p->cid_num))
07533                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07534                else
07535                   ast_set_callerid(chan, s1, NULL, s1);
07536                ast_copy_string(exten, s2, sizeof(exten));
07537             } else
07538                ast_copy_string(exten, s1, sizeof(exten));
07539          } else if (p->sig == SIG_FEATD)
07540             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07541       }
07542       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07543          if (exten[0] == '*') {
07544             char *stringp=NULL;
07545             ast_copy_string(exten2, exten, sizeof(exten2));
07546             /* Parse out extension and callerid */
07547             stringp=exten2 +1;
07548             s1 = strsep(&stringp, "#");
07549             s2 = strsep(&stringp, "#");
07550             if (s2) {
07551                if (!ast_strlen_zero(p->cid_num))
07552                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07553                else
07554                   if (*(s1 + 2))
07555                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07556                ast_copy_string(exten, s2 + 1, sizeof(exten));
07557             } else
07558                ast_copy_string(exten, s1 + 2, sizeof(exten));
07559          } else
07560             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07561       }
07562       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07563          if (exten[0] == '*') {
07564             char *stringp=NULL;
07565             ast_copy_string(exten2, exten, sizeof(exten2));
07566             /* Parse out extension and callerid */
07567             stringp=exten2 +1;
07568             s1 = strsep(&stringp, "#");
07569             s2 = strsep(&stringp, "#");
07570             if (s2 && (*(s2 + 1) == '0')) {
07571                if (*(s2 + 2))
07572                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07573             }
07574             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
07575             else ast_copy_string(exten, "911", sizeof(exten));
07576          } else
07577             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07578       }
07579       if (p->sig == SIG_FEATB) {
07580          if (exten[0] == '*') {
07581             char *stringp=NULL;
07582             ast_copy_string(exten2, exten, sizeof(exten2));
07583             /* Parse out extension and callerid */
07584             stringp=exten2 +1;
07585             s1 = strsep(&stringp, "#");
07586             ast_copy_string(exten, exten2 + 1, sizeof(exten));
07587          } else
07588             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07589       }
07590       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07591          dahdi_wink(p, index);
07592                         /* some switches require a minimum guard time between
07593                            the last FGD wink and something that answers
07594                            immediately. This ensures it */
07595          if (ast_safe_sleep(chan, 100)) {
07596             ast_hangup(chan);
07597             goto quit;
07598          }
07599       }
07600       dahdi_enable_ec(p);
07601       if (NEED_MFDETECT(p)) {
07602          if (p->dsp) {
07603             if (!p->hardwaredtmf)
07604                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
07605             else {
07606                ast_dsp_free(p->dsp);
07607                p->dsp = NULL;
07608             }
07609          }
07610       }
07611 
07612       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07613          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07614          if (p->dsp) ast_dsp_digitreset(p->dsp);
07615          res = ast_pbx_run(chan);
07616          if (res) {
07617             ast_log(LOG_WARNING, "PBX exited non-zero\n");
07618             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07619          }
07620          goto quit;
07621       } else {
07622          if (option_verbose > 2)
07623             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07624          sleep(2);
07625          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07626          if (res < 0)
07627             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07628          else
07629             sleep(1);
07630          res = ast_streamfile(chan, "ss-noservice", chan->language);
07631          if (res >= 0)
07632             ast_waitstream(chan, "");
07633          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07634          ast_hangup(chan);
07635          goto quit;
07636       }
07637       break;
07638    case SIG_FXOLS:
07639    case SIG_FXOGS:
07640    case SIG_FXOKS:
07641       /* Read the first digit */
07642       timeout = firstdigittimeout;
07643       /* If starting a threeway call, never timeout on the first digit so someone
07644          can use flash-hook as a "hold" feature */
07645       if (p->subs[SUB_THREEWAY].owner) 
07646          timeout = 999999;
07647       while (len < AST_MAX_EXTENSION-1) {
07648          /* Read digit unless it's supposed to be immediate, in which case the
07649             only answer is 's' */
07650          if (p->immediate) 
07651             res = 's';
07652          else
07653             res = ast_waitfordigit(chan, timeout);
07654          timeout = 0;
07655          if (res < 0) {
07656             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07657             res = tone_zone_play_tone(p->subs[index].dfd, -1);
07658             ast_hangup(chan);
07659             goto quit;
07660          } else if (res)  {
07661             exten[len++]=res;
07662             exten[len] = '\0';
07663          }
07664          if (!ast_ignore_pattern(chan->context, exten))
07665             tone_zone_play_tone(p->subs[index].dfd, -1);
07666          else
07667             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07668          if (!strcmp(exten,ast_pickup_ext())) {
07669             /* Scan all channels and see if there are any
07670              * ringing channels that have call groups
07671              * that equal this channels pickup group
07672              */
07673             if (index == SUB_REAL) {
07674                /* Switch us from Third call to Call Wait */
07675                if (p->subs[SUB_THREEWAY].owner) {
07676                   /* If you make a threeway call and the *8# a call, it should actually
07677                      look like a callwait */
07678                   alloc_sub(p, SUB_CALLWAIT);
07679                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07680                   unalloc_sub(p, SUB_THREEWAY);
07681                }
07682                dahdi_enable_ec(p);
07683                if (ast_pickup_call(chan)) {
07684                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
07685                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07686                   dahdi_wait_event(p->subs[index].dfd);
07687                }
07688                ast_hangup(chan);
07689                goto quit;
07690             } else {
07691                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
07692                ast_hangup(chan);
07693                goto quit;
07694             }
07695 
07696          } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07697             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07698                if (getforward) {
07699                   /* Record this as the forwarding extension */
07700                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
07701                   if (option_verbose > 2)
07702                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07703                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07704                   if (res)
07705                      break;
07706                   usleep(500000);
07707                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
07708                   sleep(1);
07709                   memset(exten, 0, sizeof(exten));
07710                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07711                   len = 0;
07712                   getforward = 0;
07713                } else  {
07714                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
07715                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07716                   if (!ast_strlen_zero(p->cid_num)) {
07717                      if (!p->hidecallerid)
07718                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
07719                      else
07720                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
07721                   }
07722                   if (!ast_strlen_zero(p->cid_name)) {
07723                      if (!p->hidecallerid)
07724                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
07725                   }
07726                   ast_setstate(chan, AST_STATE_RING);
07727                   dahdi_enable_ec(p);
07728                   res = ast_pbx_run(chan);
07729                   if (res) {
07730                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
07731                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07732                   }
07733                   goto quit;
07734                }
07735             } else {
07736                /* It's a match, but they just typed a digit, and there is an ambiguous match,
07737                   so just set the timeout to matchdigittimeout and wait some more */
07738                timeout = matchdigittimeout;
07739             }
07740          } else if (res == 0) {
07741             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07742             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07743             dahdi_wait_event(p->subs[index].dfd);
07744             ast_hangup(chan);
07745             goto quit;
07746          } else if (p->callwaiting && !strcmp(exten, "*70")) {
07747             if (option_verbose > 2) 
07748                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07749             /* Disable call waiting if enabled */
07750             p->callwaiting = 0;
07751             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07752             if (res) {
07753                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07754                   chan->name, strerror(errno));
07755             }
07756             len = 0;
07757             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07758             memset(exten, 0, sizeof(exten));
07759             timeout = firstdigittimeout;
07760                
07761          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07762             if (option_verbose > 2) 
07763                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07764             /* Disable Caller*ID if enabled */
07765             p->hidecallerid = 1;
07766             if (chan->cid.cid_num)
07767                free(chan->cid.cid_num);
07768             chan->cid.cid_num = NULL;
07769             if (chan->cid.cid_name)
07770                free(chan->cid.cid_name);
07771             chan->cid.cid_name = NULL;
07772             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07773             if (res) {
07774                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07775                   chan->name, strerror(errno));
07776             }
07777             len = 0;
07778             memset(exten, 0, sizeof(exten));
07779             timeout = firstdigittimeout;
07780          } else if (p->callreturn && !strcmp(exten, "*69")) {
07781             res = 0;
07782             if (!ast_strlen_zero(p->lastcid_num)) {
07783                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07784             }
07785             if (!res)
07786                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07787             break;
07788          } else if (!strcmp(exten, "*78")) {
07789             /* Do not disturb */
07790             if (option_verbose > 2)
07791                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07792             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07793                      "Channel: %s/%d\r\n"
07794                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
07795             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07796             p->dnd = 1;
07797             getforward = 0;
07798             memset(exten, 0, sizeof(exten));
07799             len = 0;
07800          } else if (!strcmp(exten, "*79")) {
07801             /* Do not disturb */
07802             if (option_verbose > 2)
07803                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07804             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07805                      "Channel: %s/%d\r\n"
07806                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
07807             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07808             p->dnd = 0;
07809             getforward = 0;
07810             memset(exten, 0, sizeof(exten));
07811             len = 0;
07812          } else if (p->cancallforward && !strcmp(exten, "*72")) {
07813             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07814             getforward = 1;
07815             memset(exten, 0, sizeof(exten));
07816             len = 0;
07817          } else if (p->cancallforward && !strcmp(exten, "*73")) {
07818             if (option_verbose > 2)
07819                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07820             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07821             memset(p->call_forward, 0, sizeof(p->call_forward));
07822             getforward = 0;
07823             memset(exten, 0, sizeof(exten));
07824             len = 0;
07825          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
07826                   p->subs[SUB_THREEWAY].owner &&
07827                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07828             /* This is a three way call, the main call being a real channel, 
07829                and we're parking the first call. */
07830             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07831             if (option_verbose > 2)
07832                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07833             break;
07834          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07835             if (option_verbose > 2)
07836                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07837             res = ast_db_put("blacklist", p->lastcid_num, "1");
07838             if (!res) {
07839                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07840                memset(exten, 0, sizeof(exten));
07841                len = 0;
07842             }
07843          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07844             if (option_verbose > 2) 
07845                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07846             /* Enable Caller*ID if enabled */
07847             p->hidecallerid = 0;
07848             if (chan->cid.cid_num)
07849                free(chan->cid.cid_num);
07850             chan->cid.cid_num = NULL;
07851             if (chan->cid.cid_name)
07852                free(chan->cid.cid_name);
07853             chan->cid.cid_name = NULL;
07854             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07855             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07856             if (res) {
07857                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07858                   chan->name, strerror(errno));
07859             }
07860             len = 0;
07861             memset(exten, 0, sizeof(exten));
07862             timeout = firstdigittimeout;
07863          } else if (!strcmp(exten, "*0")) {
07864             struct ast_channel *nbridge = 
07865                p->subs[SUB_THREEWAY].owner;
07866             struct dahdi_pvt *pbridge = NULL;
07867               /* set up the private struct of the bridged one, if any */
07868             if (nbridge && ast_bridged_channel(nbridge)) 
07869                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07870             if (nbridge && pbridge && 
07871                 (nbridge->tech == chan_tech) && 
07872                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07873                 ISTRUNK(pbridge)) {
07874                int func = DAHDI_FLASH;
07875                /* Clear out the dial buffer */
07876                p->dop.dialstr[0] = '\0';
07877                /* flash hookswitch */
07878                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07879                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
07880                      nbridge->name, strerror(errno));
07881                }
07882                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07883                unalloc_sub(p, SUB_THREEWAY);
07884                p->owner = p->subs[SUB_REAL].owner;
07885                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07886                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07887                ast_hangup(chan);
07888                goto quit;
07889             } else {
07890                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07891                dahdi_wait_event(p->subs[index].dfd);
07892                tone_zone_play_tone(p->subs[index].dfd, -1);
07893                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07894                unalloc_sub(p, SUB_THREEWAY);
07895                p->owner = p->subs[SUB_REAL].owner;
07896                ast_hangup(chan);
07897                goto quit;
07898             }              
07899          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07900                      ((exten[0] != '*') || (strlen(exten) > 2))) {
07901             if (option_debug)
07902                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);
07903             break;
07904          }
07905          if (!timeout)
07906             timeout = gendigittimeout;
07907          if (len && !ast_ignore_pattern(chan->context, exten))
07908             tone_zone_play_tone(p->subs[index].dfd, -1);
07909       }
07910       break;
07911    case SIG_FXSLS:
07912    case SIG_FXSGS:
07913    case SIG_FXSKS:
07914 #ifdef HAVE_PRI
07915       if (p->pri) {
07916          /* This is a GR-303 trunk actually.  Wait for the first ring... */
07917          struct ast_frame *f;
07918          int res;
07919          time_t start;
07920 
07921          time(&start);
07922          ast_setstate(chan, AST_STATE_RING);
07923          while (time(NULL) < start + 3) {
07924             res = ast_waitfor(chan, 1000);
07925             if (res) {
07926                f = ast_read(chan);
07927                if (!f) {
07928                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07929                   ast_hangup(chan);
07930                   goto quit;
07931                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07932                   res = 1;
07933                } else
07934                   res = 0;
07935                ast_frfree(f);
07936                if (res) {
07937                   ast_log(LOG_DEBUG, "Got ring!\n");
07938                   res = 0;
07939                   break;
07940                }
07941             }
07942          }
07943       }
07944 #endif
07945       /* check for SMDI messages */
07946       if (p->use_smdi && p->smdi_iface) {
07947          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07948 
07949          if (smdi_msg != NULL) {
07950             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07951 
07952             if (smdi_msg->type == 'B')
07953                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07954             else if (smdi_msg->type == 'N')
07955                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07956 
07957             ast_log(LOG_DEBUG, "Received SMDI message on %s\n", chan->name);
07958          } else {
07959             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07960          }
07961       }
07962 
07963       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07964             number = smdi_msg->calling_st;
07965 
07966       /* If we want caller id, we're in a prering state due to a polarity reversal
07967        * and we're set to use a polarity reversal to trigger the start of caller id,
07968        * grab the caller id and wait for ringing to start... */
07969       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
07970                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
07971          /* If set to use DTMF CID signalling, listen for DTMF */
07972          if (p->cid_signalling == CID_SIG_DTMF) {
07973             int i = 0;
07974             cs = NULL;
07975             ast_log(LOG_DEBUG, "Receiving DTMF cid on channel %s\n", chan->name);
07976             dahdi_setlinear(p->subs[index].dfd, 0);
07977             /*
07978              * We are the only party interested in the Rx stream since
07979              * we have not answered yet.  We don't need or even want DTMF
07980              * emulation.  The DTMF digits can come so fast that emulation
07981              * can drop some of them.
07982              */
07983             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
07984             res = 4000;/* This is a typical OFF time between rings. */
07985             for (;;) {
07986                struct ast_frame *f;
07987                res = ast_waitfor(chan, res);
07988                if (res <= 0) {
07989                   /*
07990                    * We do not need to restore the dahdi_setlinear()
07991                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
07992                    * are hanging up the channel.
07993                    */
07994                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07995                      "Exiting simple switch\n");
07996                   ast_hangup(chan);
07997                   goto quit;
07998                } 
07999                f = ast_read(chan);
08000                if (!f)
08001                   break;
08002                if (f->frametype == AST_FRAME_DTMF) {
08003                   if (i < ARRAY_LEN(dtmfbuf) - 1) {
08004                      dtmfbuf[i++] = f->subclass;
08005                   }
08006                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08007                   res = 4000;/* This is a typical OFF time between rings. */
08008                }
08009                ast_frfree(f);
08010                if (chan->_state == AST_STATE_RING ||
08011                    chan->_state == AST_STATE_RINGING) 
08012                   break; /* Got ring */
08013             }
08014             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08015             dtmfbuf[i] = '\0';
08016             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08017             /* Got cid and ring. */
08018             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
08019             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08020             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", dtmfcid, flags);
08021             /* If first byte is NULL, we have no cid */
08022             if (!ast_strlen_zero(dtmfcid)) 
08023                number = dtmfcid;
08024             else
08025                number = NULL;
08026          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08027          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08028             cs = callerid_new(p->cid_signalling);
08029             if (cs) {
08030                samples = 0;
08031 #if 1
08032                bump_gains(p);
08033 #endif            
08034                /* Take out of linear mode for Caller*ID processing */
08035                dahdi_setlinear(p->subs[index].dfd, 0);
08036                
08037                /* First we wait and listen for the Caller*ID */
08038                for (;;) {  
08039                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08040                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
08041                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08042                      callerid_free(cs);
08043                      ast_hangup(chan);
08044                      goto quit;
08045                   }
08046                   if (i & DAHDI_IOMUX_SIGEVENT) {
08047                      res = dahdi_get_event(p->subs[index].dfd);
08048                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08049                      if (res == DAHDI_EVENT_NOALARM) {
08050                         p->inalarm = 0;
08051                      }
08052 
08053                      if (p->cid_signalling == CID_SIG_V23_JP) {
08054 #ifdef DAHDI_EVENT_RINGBEGIN
08055                         if (res == DAHDI_EVENT_RINGBEGIN) {
08056                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08057                            usleep(1);
08058                         }
08059 #endif
08060                      } else {
08061                         res = 0;
08062                         break;
08063                      }
08064                   } else if (i & DAHDI_IOMUX_READ) {
08065                      res = read(p->subs[index].dfd, buf, sizeof(buf));
08066                      if (res < 0) {
08067                         if (errno != ELAST) {
08068                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08069                            callerid_free(cs);
08070                            ast_hangup(chan);
08071                            goto quit;
08072                         }
08073                         break;
08074                      }
08075                      samples += res;
08076 
08077                      if  (p->cid_signalling == CID_SIG_V23_JP) {
08078                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08079                      } else {
08080                         res = callerid_feed(cs, buf, res, AST_LAW(p));
08081                      }
08082                      if (res < 0) {
08083                         /*
08084                          * The previous diagnostic message output likely
08085                          * explains why it failed.
08086                          */
08087                         ast_log(LOG_WARNING,
08088                            "Failed to decode CallerID on channel '%s'\n",
08089                            chan->name);
08090                         break;
08091                      } else if (res)
08092                         break;
08093                      else if (samples > (8000 * 10))
08094                         break;
08095                   }
08096                }
08097                if (res == 1) {
08098                   callerid_get(cs, &name, &number, &flags);
08099                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08100                }
08101 
08102                if (p->cid_signalling == CID_SIG_V23_JP) {
08103                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08104                   usleep(1);
08105                }
08106 
08107                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
08108                res = 4000;/* This is a typical OFF time between rings. */
08109                for (;;) {
08110                   struct ast_frame *f;
08111                   res = ast_waitfor(chan, res);
08112                   if (res <= 0) {
08113                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08114                         "Exiting simple switch\n");
08115                      ast_hangup(chan);
08116                      goto quit;
08117                   } 
08118                   if (!(f = ast_read(chan))) {
08119                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08120                      ast_hangup(chan);
08121                      goto quit;
08122                   }
08123                   ast_frfree(f);
08124                   if (chan->_state == AST_STATE_RING ||
08125                       chan->_state == AST_STATE_RINGING) 
08126                      break; /* Got ring */
08127                }
08128    
08129                /* We must have a ring by now, so, if configured, lets try to listen for
08130                 * distinctive ringing */ 
08131                if (p->usedistinctiveringdetection) {
08132                   len = 0;
08133                   distMatches = 0;
08134                   /* Clear the current ring data array so we dont have old data in it. */
08135                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
08136                      curRingData[receivedRingT] = 0;
08137                   receivedRingT = 0;
08138                   counter = 0;
08139                   counter1 = 0;
08140                   /* Check to see if context is what it should be, if not set to be. */
08141                   if (strcmp(p->context,p->defcontext) != 0) {
08142                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08143                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08144                   }
08145       
08146                   for (;;) {  
08147                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08148                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
08149                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08150                         callerid_free(cs);
08151                         ast_hangup(chan);
08152                         goto quit;
08153                      }
08154                      if (i & DAHDI_IOMUX_SIGEVENT) {
08155                         res = dahdi_get_event(p->subs[index].dfd);
08156                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08157                         if (res == DAHDI_EVENT_NOALARM) {
08158                            p->inalarm = 0;
08159                         }
08160                         res = 0;
08161                         /* Let us detect distinctive ring */
08162       
08163                         curRingData[receivedRingT] = p->ringt;
08164       
08165                         if (p->ringt < p->ringt_base/2)
08166                            break;
08167                         /* Increment the ringT counter so we can match it against
08168                            values in chan_dahdi.conf for distinctive ring */
08169                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08170                            break;
08171                      } else if (i & DAHDI_IOMUX_READ) {
08172                         res = read(p->subs[index].dfd, buf, sizeof(buf));
08173                         if (res < 0) {
08174                            if (errno != ELAST) {
08175                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08176                               callerid_free(cs);
08177                               ast_hangup(chan);
08178                               goto quit;
08179                            }
08180                            break;
08181                         }
08182                         if (p->ringt) 
08183                            p->ringt--;
08184                         if (p->ringt == 1) {
08185                            res = -1;
08186                            break;
08187                         }
08188                      }
08189                   }
08190                   if (option_verbose > 2)
08191                      /* this only shows up if you have n of the dring patterns filled in */
08192                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08193    
08194                   for (counter = 0; counter < 3; counter++) {
08195                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
08196                      channel */
08197                      distMatches = 0;
08198                      for (counter1 = 0; counter1 < 3; counter1++) {
08199                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
08200                         (p->drings.ringnum[counter].ring[counter1]-10)) {
08201                            distMatches++;
08202                         }
08203                      }
08204                      if (distMatches == 3) {
08205                         /* The ring matches, set the context to whatever is for distinctive ring.. */
08206                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08207                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08208                         if (option_verbose > 2)
08209                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
08210                         break;
08211                      }
08212                   }
08213                }
08214                /* Restore linear mode (if appropriate) for Caller*ID processing */
08215                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08216 #if 1
08217                restore_gains(p);
08218 #endif            
08219             } else
08220                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
08221          } else {
08222             ast_log(LOG_WARNING, "Channel %s in prering "
08223                "state, but I have nothing to do. "
08224                "Terminating simple switch, should be "
08225                "restarted by the actual ring.\n", 
08226                chan->name);
08227             ast_hangup(chan);
08228             goto quit;
08229          }
08230       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08231          /* FSK Bell202 callerID */
08232          cs = callerid_new(p->cid_signalling);
08233          if (cs) {
08234 #if 1
08235             bump_gains(p);
08236 #endif            
08237             samples = 0;
08238             len = 0;
08239             distMatches = 0;
08240             /* Clear the current ring data array so we dont have old data in it. */
08241             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
08242                curRingData[receivedRingT] = 0;
08243             receivedRingT = 0;
08244             counter = 0;
08245             counter1 = 0;
08246             /* Check to see if context is what it should be, if not set to be. */
08247             if (strcmp(p->context,p->defcontext) != 0) {
08248                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08249                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08250             }
08251 
08252             /* Take out of linear mode for Caller*ID processing */
08253             dahdi_setlinear(p->subs[index].dfd, 0);
08254             for (;;) {  
08255                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08256                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
08257                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08258                   callerid_free(cs);
08259                   ast_hangup(chan);
08260                   goto quit;
08261                }
08262                if (i & DAHDI_IOMUX_SIGEVENT) {
08263                   res = dahdi_get_event(p->subs[index].dfd);
08264                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08265                   if (res == DAHDI_EVENT_NOALARM) {
08266                      p->inalarm = 0;
08267                   }
08268                   /* If we get a PR event, they hung up while processing calerid */
08269                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08270                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08271                      p->polarity = POLARITY_IDLE;
08272                      callerid_free(cs);
08273                      ast_hangup(chan);
08274                      goto quit;
08275                   }
08276                   res = 0;
08277                   /* Let us detect callerid when the telco uses distinctive ring */
08278 
08279                   curRingData[receivedRingT] = p->ringt;
08280 
08281                   if (p->ringt < p->ringt_base/2)
08282                      break;
08283                   /* Increment the ringT counter so we can match it against
08284                      values in chan_dahdi.conf for distinctive ring */
08285                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08286                      break;
08287                } else if (i & DAHDI_IOMUX_READ) {
08288                   res = read(p->subs[index].dfd, buf, sizeof(buf));
08289                   if (res < 0) {
08290                      if (errno != ELAST) {
08291                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08292                         callerid_free(cs);
08293                         ast_hangup(chan);
08294                         goto quit;
08295                      }
08296                      break;
08297                   }
08298                   if (p->ringt) 
08299                      p->ringt--;
08300                   if (p->ringt == 1) {
08301                      res = -1;
08302                      break;
08303                   }
08304                   samples += res;
08305                   res = callerid_feed(cs, buf, res, AST_LAW(p));
08306                   if (res < 0) {
08307                      /*
08308                       * The previous diagnostic message output likely
08309                       * explains why it failed.
08310                       */
08311                      ast_log(LOG_WARNING,
08312                         "Failed to decode CallerID on channel '%s'\n",
08313                         chan->name);
08314                      break;
08315                   } else if (res)
08316                      break;
08317                   else if (samples > (8000 * 10))
08318                      break;
08319                }
08320             }
08321             if (res == 1) {
08322                callerid_get(cs, &name, &number, &flags);
08323                if (option_debug)
08324                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08325             }
08326             if (distinctiveringaftercid == 1) {
08327                /* Clear the current ring data array so we dont have old data in it. */
08328                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08329                   curRingData[receivedRingT] = 0;
08330                }
08331                receivedRingT = 0;
08332                if (option_verbose > 2)
08333                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
08334                for (;;) {
08335                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08336                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
08337                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08338                      callerid_free(cs);
08339                      ast_hangup(chan);
08340                      goto quit;
08341                   }
08342                   if (i & DAHDI_IOMUX_SIGEVENT) {
08343                      res = dahdi_get_event(p->subs[index].dfd);
08344                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08345                      if (res == DAHDI_EVENT_NOALARM) {
08346                         p->inalarm = 0;
08347                      }
08348                      res = 0;
08349                      /* Let us detect callerid when the telco uses distinctive ring */
08350 
08351                      curRingData[receivedRingT] = p->ringt;
08352 
08353                      if (p->ringt < p->ringt_base/2)
08354                         break;
08355                      /* Increment the ringT counter so we can match it against
08356                         values in chan_dahdi.conf for distinctive ring */
08357                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
08358                         break;
08359                   } else if (i & DAHDI_IOMUX_READ) {
08360                      res = read(p->subs[index].dfd, buf, sizeof(buf));
08361                      if (res < 0) {
08362                         if (errno != ELAST) {
08363                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08364                            callerid_free(cs);
08365                            ast_hangup(chan);
08366                            goto quit;
08367                         }
08368                         break;
08369                      }
08370                   if (p->ringt)
08371                      p->ringt--;
08372                      if (p->ringt == 1) {
08373                         res = -1;
08374                         break;
08375                      }
08376                   }
08377                }
08378             }
08379             if (p->usedistinctiveringdetection) {
08380                if (option_verbose > 2)
08381                   /* this only shows up if you have n of the dring patterns filled in */
08382                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08383 
08384                for (counter = 0; counter < 3; counter++) {
08385                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
08386                   channel */
08387                   if (option_verbose > 2)
08388                      /* this only shows up if you have n of the dring patterns filled in */
08389                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
08390                         p->drings.ringnum[counter].ring[0],
08391                         p->drings.ringnum[counter].ring[1],
08392                         p->drings.ringnum[counter].ring[2]);
08393                   distMatches = 0;
08394                   for (counter1 = 0; counter1 < 3; counter1++) {
08395                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
08396                      (p->drings.ringnum[counter].ring[counter1]-10)) {
08397                         distMatches++;
08398                      }
08399                   }
08400                   if (distMatches == 3) {
08401                      /* The ring matches, set the context to whatever is for distinctive ring.. */
08402                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08403                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08404                      if (option_verbose > 2)
08405                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
08406                      break;
08407                   }
08408                }
08409             }
08410             /* Restore linear mode (if appropriate) for Caller*ID processing */
08411             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
08412 #if 1
08413             restore_gains(p);
08414 #endif            
08415             if (res < 0) {
08416                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08417             }
08418          } else
08419             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08420       }
08421       else
08422          cs = NULL;
08423 
08424       if (number)
08425          ast_shrink_phone_number(number);
08426       ast_set_callerid(chan, number, name, number);
08427 
08428       if (smdi_msg)
08429          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08430 
08431       if (cs)
08432          callerid_free(cs);
08433 
08434       ast_setstate(chan, AST_STATE_RING);
08435       chan->rings = 1;
08436       p->ringt = p->ringt_base;
08437       res = ast_pbx_run(chan);
08438       if (res) {
08439          ast_hangup(chan);
08440          ast_log(LOG_WARNING, "PBX exited non-zero\n");
08441       }
08442       goto quit;
08443    default:
08444       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08445       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
08446       if (res < 0)
08447             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08448    }
08449    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
08450    if (res < 0)
08451          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08452    ast_hangup(chan);
08453 quit:
08454    ast_mutex_lock(&ss_thread_lock);
08455    ss_thread_count--;
08456    ast_cond_signal(&ss_thread_complete);
08457    ast_mutex_unlock(&ss_thread_lock);
08458    return NULL;
08459 }

static int start_pri ( struct dahdi_pri pri  )  [static]

Definition at line 12330 of file chan_dahdi.c.

References ast_log(), ast_pthread_create_background, dahdi_close_pri_fd(), DAHDI_FILE_CHANNEL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_OUTGOING, DCHAN_NOTINALARM, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, DEFAULT_PRI_DEBUG, errno, dahdi_pri::fds, dahdi_pri::inbanddisconnect, LOG_ERROR, dahdi_pri::master, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, dahdi_pri::overlapdial, dahdi_pri::pri, pri_dchannel(), dahdi_pri::resetpos, and dahdi_pri::switchtype.

Referenced by setup_dahdi().

12331 {
12332    int res, x;
12333    struct dahdi_params p;
12334    struct dahdi_bufferinfo bi;
12335    struct dahdi_spaninfo si;
12336    int i;
12337    
12338    for (i = 0; i < NUM_DCHANS; i++) {
12339       if (!pri->dchannels[i])
12340          break;
12341       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
12342       x = pri->dchannels[i];
12343       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12344          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12345          return -1;
12346       }
12347       memset(&p, 0, sizeof(p));
12348       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12349       if (res) {
12350          dahdi_close_pri_fd(pri, i);
12351          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12352          return -1;
12353       }
12354       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12355          dahdi_close_pri_fd(pri, i);
12356          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
12357          return -1;
12358       }
12359       memset(&si, 0, sizeof(si));
12360       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12361       if (res) {
12362          dahdi_close_pri_fd(pri, i);
12363          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12364       }
12365       if (!si.alarms)
12366          pri->dchanavail[i] |= DCHAN_NOTINALARM;
12367       else
12368          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12369       memset(&bi, 0, sizeof(bi));
12370       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12371       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12372       bi.numbufs = 32;
12373       bi.bufsize = 1024;
12374       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12375          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12376          dahdi_close_pri_fd(pri, i);
12377          return -1;
12378       }
12379       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12380       /* Force overlap dial if we're doing GR-303! */
12381       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12382          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12383       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12384 #ifdef HAVE_PRI_INBANDDISCONNECT
12385       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12386 #endif
12387       /* Enslave to master if appropriate */
12388       if (i)
12389          pri_enslave(pri->dchans[0], pri->dchans[i]);
12390       if (!pri->dchans[i]) {
12391          dahdi_close_pri_fd(pri, i);
12392          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12393          return -1;
12394       }
12395       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12396       pri_set_nsf(pri->dchans[i], pri->nsf);
12397 #ifdef PRI_GETSET_TIMERS
12398       for (x = 0; x < PRI_MAX_TIMERS; x++) {
12399          if (pritimers[x] != 0)
12400             pri_set_timer(pri->dchans[i], x, pritimers[x]);
12401       }
12402 #endif
12403    }
12404    /* Assume primary is the one we use */
12405    pri->pri = pri->dchans[0];
12406    pri->resetpos = -1;
12407    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12408       for (i = 0; i < NUM_DCHANS; i++) {
12409          if (!pri->dchannels[i])
12410             break;
12411          dahdi_close_pri_fd(pri, i);
12412       }
12413       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12414       return -1;
12415    }
12416    return 0;
12417 }

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

Definition at line 1849 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::chan, dahdi_subchannel::dfd, ast_channel::fds, dahdi_subchannel::inthreeway, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().

Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().

01850 {
01851    int tchan;
01852    int tinthreeway;
01853    struct ast_channel *towner;
01854 
01855    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01856 
01857    tchan = p->subs[a].chan;
01858    towner = p->subs[a].owner;
01859    tinthreeway = p->subs[a].inthreeway;
01860 
01861    p->subs[a].chan = p->subs[b].chan;
01862    p->subs[a].owner = p->subs[b].owner;
01863    p->subs[a].inthreeway = p->subs[b].inthreeway;
01864 
01865    p->subs[b].chan = tchan;
01866    p->subs[b].owner = towner;
01867    p->subs[b].inthreeway = tinthreeway;
01868 
01869    if (p->subs[a].owner) 
01870       p->subs[a].owner->fds[0] = p->subs[a].dfd;
01871    if (p->subs[b].owner) 
01872       p->subs[b].owner->fds[0] = p->subs[b].dfd;
01873    wakeup_sub(p, a, NULL);
01874    wakeup_sub(p, b, NULL);
01875 }

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

Definition at line 1988 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_DEBUG, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.

Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().

01989 {
01990    if (!x) {
01991       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01992       return -1;
01993    }
01994    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01995    dahdi_close_sub(p, x);
01996    p->subs[x].linear = 0;
01997    p->subs[x].chan = 0;
01998    p->subs[x].owner = NULL;
01999    p->subs[x].inthreeway = 0;
02000    p->polarity = POLARITY_IDLE;
02001    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02002    return 0;
02003 }

static int unload_module ( void   )  [static]

Definition at line 14011 of file chan_dahdi.c.

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

14012 {
14013 #ifdef HAVE_PRI      
14014    int y;
14015    for (y = 0; y < NUM_SPANS; y++)
14016       ast_mutex_destroy(&pris[y].lock);
14017 #endif
14018    return __unload_module();
14019 }

static int update_conf ( struct dahdi_pvt p  )  [static]

Definition at line 2388 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, conf_add(), conf_del(), dahdi_pvt::confno, dahdi_subchannel::dfd, GET_CHANNEL, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, isslavenative(), LOG_DEBUG, dahdi_pvt::master, MAX_SLAVES, option_debug, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_unlink(), and mkintf().

02389 {
02390    int needconf = 0;
02391    int x;
02392    int useslavenative;
02393    struct dahdi_pvt *slave = NULL;
02394 
02395    useslavenative = isslavenative(p, &slave);
02396    /* Start with the obvious, general stuff */
02397    for (x = 0; x < 3; x++) {
02398       /* Look for three way calls */
02399       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02400          conf_add(p, &p->subs[x], x, 0);
02401          needconf++;
02402       } else {
02403          conf_del(p, &p->subs[x], x);
02404       }
02405    }
02406    /* If we have a slave, add him to our conference now. or DAX
02407       if this is slave native */
02408    for (x = 0; x < MAX_SLAVES; x++) {
02409       if (p->slaves[x]) {
02410          if (useslavenative)
02411             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02412          else {
02413             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02414             needconf++;
02415          }
02416       }
02417    }
02418    /* If we're supposed to be in there, do so now */
02419    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02420       if (useslavenative)
02421          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02422       else {
02423          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02424          needconf++;
02425       }
02426    }
02427    /* If we have a master, add ourselves to his conference */
02428    if (p->master) {
02429       if (isslavenative(p->master, NULL)) {
02430          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02431       } else {
02432          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02433       }
02434    }
02435    if (!needconf) {
02436       /* Nobody is left (or should be left) in our conference.
02437          Kill it. */
02438       p->confno = -1;
02439    }
02440    if (option_debug)
02441       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02442    return 0;
02443 }

static void wakeup_sub ( struct dahdi_pvt p,
int  a,
struct dahdi_pri pri 
) [static]

Definition at line 1295 of file chan_dahdi.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), dahdi_lock_sub_owner(), ast_channel::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by pri_fixup_principle(), and swap_subs().

01296 {
01297 #ifdef HAVE_PRI
01298    if (pri)
01299       ast_mutex_unlock(&pri->lock);
01300 #endif         
01301    dahdi_lock_sub_owner(p, a);
01302    if (p->subs[a].owner) {
01303       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01304       ast_mutex_unlock(&p->subs[a].owner->lock);
01305    }
01306 #ifdef HAVE_PRI
01307    if (pri)
01308       ast_mutex_lock(&pri->lock);
01309 #endif         
01310 }

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

Definition at line 3657 of file chan_dahdi.c.

References dahdi_accept_r2_call_exec().

Referenced by load_module().

03658 {
03659    return dahdi_accept_r2_call_exec(chan, data);
03660 }

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

Definition at line 13829 of file chan_dahdi.c.

References __action_dialoffhook().

13830 {
13831    return __action_dialoffhook(s, m, 1);
13832 }

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

Definition at line 13729 of file chan_dahdi.c.

References __action_dnd().

13730 {
13731    return __action_dnd(s, m, 1, 0);
13732 }

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

Definition at line 13719 of file chan_dahdi.c.

References __action_dnd().

13720 {
13721    return __action_dnd(s, m, 1, 1);
13722 }

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

Definition at line 13908 of file chan_dahdi.c.

References __action_restart().

13909 {
13910    return __action_restart(s, m, 1);
13911 }

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

Definition at line 13884 of file chan_dahdi.c.

References __action_showchannels().

13885 {
13886    return __action_showchannels(s, m, 1);
13887 }

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

Definition at line 13758 of file chan_dahdi.c.

References __action_transfer().

13759 {
13760    return __action_transfer(s, m, 1);
13761 }

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

Definition at line 13786 of file chan_dahdi.c.

References __action_transferhangup().

13787 {
13788    return __action_transferhangup(s, m, 1);
13789 }

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

Definition at line 3450 of file chan_dahdi.c.

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

Referenced by load_module().

03451 {
03452    ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);  
03453    return send_keypad_facility_exec(chan, data);
03454 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 15311 of file chan_dahdi.c.

int alarm

Definition at line 2157 of file chan_dahdi.c.

Referenced by __action_showchannels().

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

Referenced by alarm2str(), and dahdi_show_status().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 15311 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 1220 of file chan_dahdi.c.

struct ast_channel_tech* chan_tech [static]

Definition at line 1188 of file chan_dahdi.c.

Referenced by ast_device_state().

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 1231 of file chan_dahdi.c.

Initial value:
 {
   { "zap", "destroy", "channel", NULL },
   dahdi_destroy_channel, NULL,
   NULL }

Definition at line 13625 of file chan_dahdi.c.

Initial value:
 {
   { "zap", "restart", NULL },
   dahdi_restart_cmd, NULL,
   NULL }

Definition at line 13630 of file chan_dahdi.c.

Initial value:
 {
   { "zap", "show", "cadences", NULL },
   handle_dahdi_show_cadences, NULL,
   NULL }

Definition at line 13610 of file chan_dahdi.c.

Initial value:
 {
   { "zap", "show", "channel", NULL },
   dahdi_show_channel, NULL,
   NULL }

Definition at line 13620 of file chan_dahdi.c.

Initial value:
 {
   { "zap", "show", "channels", NULL },
   dahdi_show_channels, NULL,
   NULL }

Definition at line 13615 of file chan_dahdi.c.

Initial value:
 {
   { "zap", "show", "status", NULL },
   dahdi_show_status, NULL,
   NULL }

Definition at line 13635 of file chan_dahdi.c.

char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static]

Definition at line 3542 of file chan_dahdi.c.

Initial value:
 
"  DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n"
"  You can specify yes or no as argument to accept with or without charge.\n"

Definition at line 3548 of file chan_dahdi.c.

char* dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" [static]

Definition at line 3545 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 13640 of file chan_dahdi.c.

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 13050 of file chan_dahdi.c.

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 12704 of file chan_dahdi.c.

const char dahdi_r2_callfiles_help[] [static]
Initial value:
         "Usage: mfcr2 call files [on|off] <channel>\n"
         "       Enable call files creation on the specified channel.\n"
         "       If no channel is specified call files creation policy will be applied to all channels.\n"

Definition at line 13035 of file chan_dahdi.c.

openr2_event_interface_t dahdi_r2_event_iface [static]

Definition at line 1809 of file chan_dahdi.c.

const char dahdi_r2_setblocked_help[] [static]
Initial value:
         "Usage: mfcr2 set blocked <channel>\n"
         "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
         "       Force the given channel into BLOCKED state.\n"
         "       If no channel is specified, all channels will be set to BLOCKED.\n"

Definition at line 13044 of file chan_dahdi.c.

const char dahdi_r2_setdebug_help[] [static]
Initial value:
         "Usage: mfcr2 set debug <loglevel> <channel>\n"
         "       Set a new logging level for the specified channel.\n"
         "       If no channel is specified the logging level will be applied to all channels.\n"

Definition at line 13031 of file chan_dahdi.c.

const char dahdi_r2_setidle_help[] [static]
Initial value:
         "Usage: mfcr2 set idle <channel>\n"
         "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
         "       Force the given channel into IDLE state.\n"
         "       If no channel is specified, all channels will be set to IDLE.\n"

Definition at line 13039 of file chan_dahdi.c.

const char dahdi_r2_showchannels_help[] [static]
Initial value:
         "Usage: mfcr2 show channels [group <group> | context <context>]\n"
         "       Shows the zap channels configured with MFC/R2 signaling.\n"

Definition at line 13028 of file chan_dahdi.c.

openr2_transcoder_interface_t dahdi_r2_transcode_iface [static]
Initial value:

Definition at line 1840 of file chan_dahdi.c.

const char dahdi_r2_variants_help[] [static]
Initial value:
 
         "Usage: mfcr2 show variants\n"
         "       Show supported MFC/R2 variants.\n"

Definition at line 13025 of file chan_dahdi.c.

const char dahdi_r2_version_help[] [static]
Initial value:
 
         "Usage: mfcr2 show version\n"
         "       Shows the version of the OpenR2 library being used.\n"

Definition at line 13022 of file chan_dahdi.c.

char dahdi_restart_usage[] [static]

Definition at line 13603 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 3392 of file chan_dahdi.c.

Initial value:
 
"  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
"  IE over the current channel.\n"

Definition at line 3398 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static]

Definition at line 3395 of file chan_dahdi.c.

char dahdi_show_cadences_usage[] [static]
Initial value:
"Usage: dahdi show cadences\n"
"       Shows all cadences currently defined\n"

Definition at line 13496 of file chan_dahdi.c.

char dahdi_show_status_usage[] [static]
Initial value:
   "Usage: dahdi show status\n"
   "       Shows a list of DAHDI cards with status\n"

Definition at line 13595 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1144 of file chan_dahdi.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 115 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 228 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 229 of file chan_dahdi.c.

char destroy_channel_usage[] [static]
Initial value:
   "Usage: dahdi 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 13599 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 233 of file chan_dahdi.c.

struct dahdi_distRings drings [static]

Definition at line 471 of file chan_dahdi.c.

Referenced by mkintf(), and process_dahdi().

int dtmfcid_level = 256 [static]

Definition at line 236 of file chan_dahdi.c.

char* events[] [static]

Definition at line 2134 of file chan_dahdi.c.

Referenced by authenticate().

int firstdigittimeout = 16000 [static]

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

Definition at line 248 of file chan_dahdi.c.

Referenced by disa_exec().

int gendigittimeout = 8000 [static]

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

Definition at line 251 of file chan_dahdi.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 122 of file chan_dahdi.c.

Referenced by dahdi_new(), process_dahdi(), and setup_dahdi().

int ifcount = 0 [static]

Definition at line 260 of file chan_dahdi.c.

struct dahdi_pvt * ifend [static]
struct dahdi_pvt * iflist [static]
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]
struct ast_channel inuse [static]
int matchdigittimeout = 3000 [static]

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

Definition at line 254 of file chan_dahdi.c.

int mfcr2_cur_accept_on_offer = 1 [static]

Definition at line 350 of file chan_dahdi.c.

Definition at line 349 of file chan_dahdi.c.

int mfcr2_cur_call_files = 0 [static]

Definition at line 348 of file chan_dahdi.c.

openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER [static]

Definition at line 365 of file chan_dahdi.c.

int mfcr2_cur_charge_calls = 1 [static]

Definition at line 351 of file chan_dahdi.c.

int mfcr2_cur_context_index = 0 [static]

Definition at line 347 of file chan_dahdi.c.

int mfcr2_cur_double_answer = 0 [static]

Definition at line 353 of file chan_dahdi.c.

int mfcr2_cur_forced_release = 0 [static]

Definition at line 352 of file chan_dahdi.c.

int mfcr2_cur_get_ani_first = -1 [static]

Definition at line 345 of file chan_dahdi.c.

int mfcr2_cur_immediate_accept = -1 [static]

Definition at line 354 of file chan_dahdi.c.

char mfcr2_cur_logdir[OR2_MAX_PATH] [static]

Definition at line 362 of file chan_dahdi.c.

openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING [static]

Definition at line 364 of file chan_dahdi.c.

int mfcr2_cur_max_ani = 10 [static]

Definition at line 343 of file chan_dahdi.c.

int mfcr2_cur_max_dnis = 4 [static]

Definition at line 344 of file chan_dahdi.c.

Definition at line 342 of file chan_dahdi.c.

int mfcr2_cur_mfback_timeout = -1 [static]

Definition at line 341 of file chan_dahdi.c.

char mfcr2_cur_r2proto_file[OR2_MAX_PATH] [static]

Definition at line 363 of file chan_dahdi.c.

int mfcr2_cur_skip_category = -1 [static]

Definition at line 346 of file chan_dahdi.c.

openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN [static]

Definition at line 340 of file chan_dahdi.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 272 of file chan_dahdi.c.

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

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

Definition at line 268 of file chan_dahdi.c.

Referenced by __unload_module(), dahdi_restart(), and restart_monitor().

char* name

Definition at line 2158 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1217 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 277 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 235 of file chan_dahdi.c.

const char pri_debug_help[] [static]
Initial value:
 
   "Usage: pri debug span <span>\n"
   "       Enables debugging on a given PRI span\n"

Definition at line 12684 of file chan_dahdi.c.

const char pri_no_debug_help[] [static]
Initial value:
 
   "Usage: pri no debug span <span>\n"
   "       Disables debugging on a given PRI span\n"

Definition at line 12688 of file chan_dahdi.c.

const char pri_really_debug_help[] [static]
Initial value:
 
   "Usage: pri intensive debug span <span>\n"
   "       Enables debugging down to the Q.921 level\n"

Definition at line 12692 of file chan_dahdi.c.

const char pri_show_span_help[] [static]
Initial value:
 
   "Usage: pri show span <span>\n"
   "       Displays PRI Information on a given PRI span\n"

Definition at line 12696 of file chan_dahdi.c.

const char pri_show_spans_help[] [static]
Initial value:
 
   "Usage: pri show spans\n"
   "       Displays PRI Information\n"

Definition at line 12700 of file chan_dahdi.c.

int pridebugfd = -1 [static]

Definition at line 243 of file chan_dahdi.c.

ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]
char pridebugfilename[1024] = "" [static]

Definition at line 244 of file chan_dahdi.c.

struct dahdi_pri pris[NUM_SPANS] [static]
char progzone[10] = "" [static]

Definition at line 231 of file chan_dahdi.c.

struct dahdi_mfcr2 r2links[NUM_SPANS] [static]
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 275 of file chan_dahdi.c.

Referenced by dahdi_restart().

int ringt_base = DEFAULT_RINGT [static]

Configured ring timeout base.

Note:
Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.

Definition at line 328 of file chan_dahdi.c.

struct dahdi_pvt* round_robin[32]

Definition at line 1196 of file chan_dahdi.c.

char show_channel_usage[] [static]
Initial value:
   "Usage: dahdi show channel <chan num>\n"
   "  Detailed information about a given channel\n"

Definition at line 13591 of file chan_dahdi.c.

char show_channels_usage[] [static]
Initial value:
   "Usage: dahdi show channels\n"
   "  Shows a list of available channels\n"

Definition at line 13587 of file chan_dahdi.c.

Definition at line 273 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 276 of file chan_dahdi.c.

ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 274 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

char* subnames[] [static]
Initial value:
 {
   "Real",
   "Callwait",
   "Threeway"
}

Definition at line 484 of file chan_dahdi.c.

const char tdesc[] [static]

Definition at line 174 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 1218 of file chan_dahdi.c.

char* zap_accept_r2_call_app = "ZapAcceptR2Call" [static]

Definition at line 3543 of file chan_dahdi.c.

Initial value:
 
"  ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
"  You can specify yes or no as argument to accept with or without charge.\n"

Definition at line 3552 of file chan_dahdi.c.

char* zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" [static]

Definition at line 3546 of file chan_dahdi.c.

char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static]

Definition at line 3393 of file chan_dahdi.c.

Initial value:
 
"  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
"  IE over the current channel.\n"

Definition at line 3401 of file chan_dahdi.c.

char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static]

Definition at line 3396 of file chan_dahdi.c.

struct ast_channel_tech zap_tech [static]

Definition at line 1166 of file chan_dahdi.c.


Generated on 31 Jan 2014 for Asterisk - the Open Source PBX by  doxygen 1.6.1