Wed Apr 6 11:29:54 2011

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <math.h>
#include <ctype.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include "sig_analog.h"
#include "sig_pri.h"
#include "sig_ss7.h"
#include <openr2.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.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/cel.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/event.h"
#include "asterisk/devicestate.h"
#include "asterisk/paths.h"
#include "asterisk/ccss.h"
#include "asterisk/data.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_mfcr2_conf
struct  dahdi_parms_pseudo
struct  dahdi_pri
struct  dahdi_pvt
struct  dahdi_ss7
struct  dahdi_starting_point
struct  dahdi_subchannel
struct  distRingData
struct  mwi_thread_data
struct  mwisend_info
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 CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
#define CALLPROGRESS_FAX_INCOMING   4
#define CALLPROGRESS_FAX_OUTGOING   2
#define CALLPROGRESS_PROGRESS   1
#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 CHAN_TAG   "Chan "
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define CONTEXT_TAG   "Context - "
#define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
#define DATA_EXPORT_DAHDI_PVT(MEMBER)
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID.
#define DEFAULT_RINGT   ((8000 * 8) / READ_SIZE)
#define END_SILENCE_LEN   400
#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\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 %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define GET_CHANNEL(p)   ((p)->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_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_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
#define R2_LINK_CAPACITY   10
#define READ_SIZE   160
#define REPORT_CHANNEL_ALARMS   1
#define REPORT_SPAN_ALARMS   2
#define sig2str   dahdi_sig2str
#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)
#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)
#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_MFCR2   DAHDI_SIG_CAS
#define SIG_MFCR2_MAX_CHANNELS   672
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_PRI_LIB_HANDLE_CASES
#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 SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define TRAILER_MS   5
#define TRANSFER   0

Enumerations

enum  DAHDI_IFLIST { DAHDI_IFLIST_NONE, DAHDI_IFLIST_MAIN, DAHDI_IFLIST_NO_B_CHAN }
enum  mwisend_states {
  MWI_SEND_NULL = 0, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE,
  MWI_SEND_SPILL, MWI_SEND_CLEANUP, MWI_SEND_DONE
}

Functions

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 int action_dahdidialoffhook (struct mansession *s, const struct message *m)
static int action_dahdidndoff (struct mansession *s, const struct message *m)
static int action_dahdidndon (struct mansession *s, const struct message *m)
static int action_dahdirestart (struct mansession *s, const struct message *m)
static int action_dahdishowchannels (struct mansession *s, const struct message *m)
static int action_transfer (struct mansession *s, const struct message *m)
static int action_transferhangup (struct mansession *s, const struct message *m)
static char * alarm2str (int alm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static int analog_lib_handles (int signalling, int radio, int oprmode)
static void * analog_ss_thread (void *data)
static int analog_tone_to_dahditone (enum analog_tone tone)
static int analogsub_to_dahdisub (enum analog_sub analogsub)
 AST_DATA_STRUCTURE (dahdi_pvt, DATA_EXPORT_DAHDI_PVT)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt **pvt, int is_specific_channel)
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct dahdi_pvt *p)
static int calc_energy (const unsigned char *buf, int len, format_t law)
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_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 struct ast_strcreate_channel_name (struct dahdi_pvt *i, int is_outgoing, char *address)
static int dahdi_accept_r2_call_exec (struct ast_channel *chan, const char *data)
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 int dahdi_cc_callback (struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
 Callback made when dial failed to get a channel out of dahdi_request().
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static int dahdi_channels_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_close (int fd)
static void dahdi_close_pri_fd (struct dahdi_pri *pri, int fd_num)
static void dahdi_close_ss7_fd (struct dahdi_ss7 *ss7, 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 char * dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_destroy_channel_bynum (int channel)
static int dahdi_devicestate (void *data)
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 int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
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, const char *function, char *data, char *buf, size_t len)
static int dahdi_func_write (struct ast_channel *chan, const 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 idx, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
static void dahdi_iflist_extract (struct dahdi_pvt *pvt)
static void dahdi_iflist_insert (struct dahdi_pvt *pvt)
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 idx, int law, const char *linkedid)
static int dahdi_new_pri_nobch_channel (struct sig_pri_span *pri)
static void dahdi_nobch_extract (struct sig_pri_span *pri, struct dahdi_pvt *pvt)
static void dahdi_nobch_insert (struct sig_pri_span *pri, struct dahdi_pvt *pvt)
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_pri_update_span_devstate (struct sig_pri_span *pri)
static int dahdi_queryoption (struct ast_channel *chan, int option, void *data, int *datalen)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f)
static int16_t dahdi_r2_alaw_to_linear (uint8_t sample)
static int dahdi_r2_answer (struct dahdi_pvt *p)
static int dahdi_r2_cause_to_ast_cause (openr2_call_disconnect_cause_t cause)
static void dahdi_r2_destroy_links (void)
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 struct dahdi_mfcr2dahdi_r2_get_link (void)
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 int dahdi_r2_set_context (struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
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, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static int dahdi_restart (void)
static char * dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_ring_phone (struct dahdi_pvt *p)
static int dahdi_send_callrerouting_facility_exec (struct ast_channel *chan, const char *data)
static int dahdi_send_keypad_facility_exec (struct ast_channel *chan, const char *digits)
static int dahdi_sendtext (struct ast_channel *c, const char *text)
static char * dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_set_hook (int fd, int hs)
static char * dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 char * dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_sig2str (int sig)
static int dahdi_sig_pri_lib_handles (int signaling)
static void dahdi_softhangup_all (void)
static void dahdi_ss7_error (struct ss7 *ss7, char *s)
static void dahdi_ss7_message (struct ss7 *ss7, char *s)
static int dahdi_status_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_train_ec (struct dahdi_pvt *p)
static void dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
static void dahdi_unlink_pri_pvt (struct dahdi_pvt *pvt)
static void dahdi_unlink_ss7_pvt (struct dahdi_pvt *pvt)
static int dahdi_version_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
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 enum analog_event dahdievent_to_analogevent (int event)
static enum analog_sigtype dahdisig_to_analogsig (int sig)
static void deep_copy_dahdi_chan_conf (struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
static void destroy_all_channels (void)
static void destroy_channel (struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt *pvt)
static struct dahdi_pvtdetermine_starting_point (const char *data, struct dahdi_starting_point *param)
static int device2chan (const char *subdir, int channel, char *path, int pathlen)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_monitor (void *data)
static int drc_sample (int sample, float drc)
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static const char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, float drc, int law)
static struct dahdi_pvtfind_channel (int channel)
static struct dahdi_pvtfind_next_iface_in_span (struct dahdi_pvt *cur)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alms)
static void handle_clear_alarms (struct dahdi_pvt *p)
static char * handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
static char * handle_mfcr2_call_files (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_blocked (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_idle (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_show_variants (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_disable_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_enable_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_generic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
static char * handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_block_cic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_block_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_show_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_unblock_cic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_unblock_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int has_voicemail (struct dahdi_pvt *p)
static int is_group_or_channel_match (struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
static int isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
static int linkset_addsigchan (int sigchan)
static int load_module (void)
static void * mfcr2_monitor (void *data)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
static void mwi_event_cb (const struct ast_event *event, void *userdata)
static int mwi_send_init (struct dahdi_pvt *pvt)
static int mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read)
static int mwi_send_process_event (struct dahdi_pvt *pvt, int event)
static void * mwi_thread (void *data)
static void my_all_subchannels_hungup (void *pvt)
static int my_allocate_sub (void *pvt, enum analog_sub analogsub)
static void my_answer_polarityswitch (void *pvt)
static int my_callwait (void *pvt)
static void my_cancel_cidspill (void *pvt)
static int my_check_confirmanswer (void *pvt)
static int my_check_for_conference (void *pvt)
static int my_check_waitingfordt (void *pvt)
static int my_complete_conference_update (void *pvt, int needconference)
static int my_conf_add (void *pvt, enum analog_sub sub)
static int my_conf_del (void *pvt, enum analog_sub sub)
static int my_confmute (void *pvt, int mute)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
static void my_deadlock_avoidance_private (void *pvt)
static void my_decrease_ss_count (void)
static int my_dial_digits (void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
static int my_distinctive_ring (struct ast_channel *chan, void *pvt, int idx, int *ringdata)
static int my_dsp_reset_and_flush_digits (void *pvt)
static int my_dsp_set_digitmode (void *pvt, enum analog_dsp_digitmode mode)
static int my_flash (void *pvt)
static void my_get_and_handle_alarms (void *pvt)
static int my_get_callerid (void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
static int my_get_event (void *pvt)
static const char * my_get_orig_dialstring (void *pvt)
static void * my_get_sigpvt_bridged_channel (struct ast_channel *chan)
static int my_get_sub_fd (void *pvt, enum analog_sub sub)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static void my_handle_dchan_exception (struct sig_pri_span *pri, int index)
static void my_handle_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
static void my_handle_link_exception (struct sig_ss7_linkset *linkset, int which)
static void my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
static void my_hangup_polarityswitch (void *pvt)
static int my_has_voicemail (void *pvt)
static void my_increase_ss_count (void)
static int my_is_dialing (void *pvt, enum analog_sub sub)
static int my_is_off_hook (void *pvt)
static void my_lock_private (void *pvt)
static void my_module_ref (void)
static void my_module_unref (void)
static struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
static struct ast_channelmy_new_pri_ast_channel (void *pvt, int state, enum sig_pri_law law, char *exten, const struct ast_channel *requestor)
static struct ast_channelmy_new_ss7_ast_channel (void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
static int my_off_hook (void *pvt)
static int my_on_hook (void *pvt)
static int my_play_tone (void *pvt, enum analog_sub sub, enum analog_tone tone)
static void my_pri_fixup_chans (void *chan_old, void *chan_new)
static void my_pri_make_cc_dialstring (void *priv, char *buf, size_t buf_size)
static void my_pri_open_media (void *p)
static int my_pri_play_tone (void *pvt, enum sig_pri_tone tone)
static int my_ring (void *pvt)
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
static void my_set_alarm (void *pvt, int in_alarm)
static void my_set_cadence (void *pvt, int *cidrings, struct ast_channel *ast)
static void my_set_callerid (void *pvt, const struct ast_party_caller *caller)
static void my_set_callwaiting (void *pvt, int callwaiting_enable)
static void my_set_confirmanswer (void *pvt, int flag)
static void my_set_dialing (void *pvt, int is_dialing)
static void my_set_digital (void *pvt, int is_digital)
static void my_set_dnid (void *pvt, const char *dnid)
static int my_set_echocanceller (void *pvt, int enable)
static void my_set_inservice (void *pvt, int is_inservice)
static void my_set_inthreeway (void *pvt, enum analog_sub sub, int inthreeway)
static int my_set_linear_mode (void *pvt, enum analog_sub sub, int linear_mode)
static void my_set_locallyblocked (void *pvt, int is_blocked)
static void my_set_needringing (void *pvt, int value)
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
static void my_set_polarity (void *pvt, int value)
static void my_set_pulsedial (void *pvt, int flag)
static void my_set_rdnis (void *pvt, const char *rdnis)
static void my_set_remotelyblocked (void *pvt, int is_blocked)
static void my_set_ringtimeout (void *pvt, int ringt)
static void my_set_waitingfordt (void *pvt, struct ast_channel *ast)
static int my_ss7_play_tone (void *pvt, enum sig_ss7_tone tone)
static void my_ss7_set_loopback (void *pvt, int enable)
static int my_start (void *pvt)
static int my_start_cid_detect (void *pvt, int cid_signalling)
static void my_start_polarityswitch (void *pvt)
static int my_stop_callwait (void *pvt)
static int my_stop_cid_detect (void *pvt)
static void my_swap_subchannels (void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
static int my_train_echocanceller (void *pvt)
static int my_unallocate_sub (void *pvt, enum analog_sub analogsub)
static void my_unlock_private (void *pvt)
static int my_wait_event (void *pvt)
static int my_wink (void *pvt, enum analog_sub sub)
static void notify_message (char *mailbox_full, int thereornot)
 Send MWI state change.
static int parse_buffers_policy (const char *parse, int *num_buffers, int *policy)
static unsigned int parse_pointcode (const char *pcstring)
static char * parse_spanchan (char *chanstr, char **subdir)
static int prepare_pri (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 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 options)
static void process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line)
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 revert_fax_buffers (struct dahdi_pvt *p, struct ast_channel *ast)
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 set_actual_gain (int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
static int set_actual_rxgain (int fd, float gain, float drc, int law)
static int set_actual_txgain (int fd, float gain, float drc, int law)
static int setup_dahdi (int reload)
static int setup_dahdi_int (int reload, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
static int sig_pri_tone_to_dahditone (enum sig_pri_tone tone)
static int sig_ss7_tone_to_dahditone (enum sig_ss7_tone tone)
static int sigtype_to_signalling (int sigtype)
static struct dahdi_ss7ss7_resolve_linkset (int linkset)
static void string_replace (char *str, int char1, int char2)
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)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", }
struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "chan_dahdi.conf"
static int cur_adjpointcode = -1
static int cur_cicbeginswith = -1
static int cur_defaultdpc = -1
static int cur_linkset = -1
static int cur_networkindicator = -1
static int cur_pointcode = -1
static int cur_ss7type = -1
static const char *const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call"
static struct analog_callback dahdi_analog_callbacks
static struct ast_data_handler dahdi_channels_data_provider
static struct ast_cli_entry dahdi_cli []
static struct ast_data_entry dahdi_data_providers []
static struct ast_cli_entry dahdi_mfcr2_cli []
static struct sig_pri_callback dahdi_pri_callbacks
static struct ast_cli_entry dahdi_pri_cli []
static struct dahdi_parms_pseudo dahdi_pseudo_parms
static openr2_event_interface_t dahdi_r2_event_iface
static openr2_transcoder_interface_t dahdi_r2_transcode_iface
static char * dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility"
static char * dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility"
static struct sig_ss7_callback dahdi_ss7_callbacks
static struct ast_cli_entry dahdi_ss7_cli []
static struct ast_data_handler dahdi_status_data_provider
static struct ast_channel_tech dahdi_tech
static struct ast_data_handler dahdi_version_data_provider
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static int distinctiveringaftercid = 0
static int dtmfcid_level = 256
static const char *const 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 = NULL
static struct dahdi_pvtiflist = NULL
static ast_mutex_t iflock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
 Protect the interface list (of dahdi_pvt's).
static const char *const lbostr []
static struct dahdi_ss7 linksets [NUM_SPANS]
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static char parkinglot [AST_MAX_EXTENSION] = ""
static int pridebugfd = -1
static ast_mutex_t pridebugfdlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static char pridebugfilename [1024] = ""
static struct dahdi_pri pris [NUM_SPANS]
static char progzone [10] = ""
static struct dahdi_mfcr2 ** r2links
static int r2links_count = 0
static int report_alarms = REPORT_CHANNEL_ALARMS
static ast_mutex_t restart_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
static struct dahdi_pvtround_robin [32]
static ast_cond_t ss_thread_complete
static int ss_thread_count = 0
static ast_mutex_t ss_thread_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static const char *const subnames []
static const char tdesc []
static int usedistinctiveringdetection = 0
static int user_has_defined_cadences = 0


Detailed Description

DAHDI for Pseudo TDM.

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

Definition at line 292 of file chan_dahdi.c.

Referenced by analog_ss_thread(), dahdi_callwait(), dahdi_sendtext(), mwi_send_init(), mwi_thread(), my_callwait(), my_get_callerid(), my_send_callerid(), and send_cwcidspill().

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 359 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmf(), and my_handle_dtmf().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 358 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 357 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_PROGRESS   1

Definition at line 356 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

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

10,000 ms

Definition at line 496 of file chan_dahdi.c.

Referenced by dahdi_callwait(), and my_callwait().

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

300 ms

Definition at line 495 of file chan_dahdi.c.

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

100 ms

Definition at line 497 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 389 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 390 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), dahdi_new(), and my_set_waitingfordt().

#define CHAN_PSEUDO   -2

Definition at line 354 of file chan_dahdi.c.

Referenced by build_channels(), create_channel_name(), dahdi_new(), dahdi_new_pri_nobch_channel(), dahdi_request(), determine_starting_point(), enable_dtmf_detect(), my_dsp_set_digitmode(), and my_set_polarity().

#define CHAN_TAG   "Chan "

Referenced by dahdi_r2_on_chan_log().

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

500 ms

Definition at line 498 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 632 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 633 of file chan_dahdi.c.

#define CONTEXT_TAG   "Context - "

Referenced by dahdi_r2_on_context_log().

#define dahdi_get_index ( ast,
p,
nullok   )     _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)

Definition at line 3599 of file chan_dahdi.c.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_answer(), dahdi_bridge(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), and dahdi_write().

#define DATA_EXPORT_DAHDI_PVT ( MEMBER   ) 

Definition at line 1224 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

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

Definition at line 290 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 500 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"

#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"

#define FORMAT   "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"

#define FORMAT   "%4s %40s\n"

Referenced by __iax2_show_peers(), _sip_show_peers(), alias_show(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), gtalk_show_channels(), handle_cli_core_show_channeltypes(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_cli_keys_show(), handle_core_show_image_formats(), handle_manager_show_settings(), handle_mfcr2_show_channels(), handle_mfcr2_show_variants(), handle_show_calendar(), handle_show_calendars(), handle_show_routes(), handle_show_version_files(), jingle_show_channels(), show_channels_cb(), show_chanstats_cb(), sip_show_domains(), sip_show_inuse(), sip_show_mwi(), sip_show_registry(), sip_show_tcp(), and sip_show_users().

#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"

#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"

Referenced by __iax2_show_peers(), _sip_show_peers(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_core_show_image_formats(), handle_manager_show_settings(), handle_show_calendar(), sip_show_channels(), sip_show_channelstats(), sip_show_inuse(), sip_show_registry(), and sip_show_tcp().

#define GET_CHANNEL (  )     ((p)->channel)

Definition at line 1517 of file chan_dahdi.c.

Referenced by my_complete_conference_update().

#define HANGUP   1

Definition at line 15420 of file chan_dahdi.c.

Referenced by action_transferhangup(), and dahdi_fake_event().

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

Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), and parse_setup_acknowledge().

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

Referenced by __analog_ss_thread(), analog_ss_thread(), and dahdi_indicate().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 492 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_dahdi().

#define MAX_SLAVES   4

Definition at line 635 of file chan_dahdi.c.

Referenced by isslavenative(), and my_complete_conference_update().

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

Definition at line 499 of file chan_dahdi.c.

Referenced by __analog_handle_event(), and 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 296 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and dahdi_new().

#define NUM_CADENCE_MAX   25

Definition at line 361 of file chan_dahdi.c.

#define NUM_SPANS   32

Definition at line 351 of file chan_dahdi.c.

Referenced by destroy_all_channels(), pri_create_trunkgroup(), pri_resolve_span(), and ss7_resolve_linkset().

#define POLARITY_IDLE   0

Definition at line 592 of file chan_dahdi.c.

Referenced by __analog_handle_event(), __analog_ss_thread(), analog_hangup(), dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().

#define POLARITY_REV   1

Definition at line 593 of file chan_dahdi.c.

Referenced by __analog_handle_event(), __analog_ss_thread(), analog_handle_init_event(), dahdi_handle_event(), and handle_init_event().

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 16433 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

process_dahdi() - No warnings on non-existing cofiguration keywords

Definition at line 16435 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

#define R2_LINK_CAPACITY   10

Definition at line 11784 of file chan_dahdi.c.

Referenced by dahdi_r2_get_link().

#define READ_SIZE   160

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

Definition at line 490 of file chan_dahdi.c.

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

#define REPORT_CHANNEL_ALARMS   1

Definition at line 413 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

#define REPORT_SPAN_ALARMS   2

Definition at line 414 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

#define sig2str   dahdi_sig2str

Definition at line 4525 of file chan_dahdi.c.

Referenced by action_dahdishowchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), and handle_init_event().

#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)

Definition at line 337 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), and sig_pri_start_pri().

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 338 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), pri_dchannel(), sig_pri_cc_generic_check(), and sig_pri_start_pri().

#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)

Definition at line 326 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_EM   DAHDI_SIG_EM

Definition at line 321 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_EM_E1   DAHDI_SIG_EM_E1

Definition at line 346 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)

Definition at line 322 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)

Definition at line 325 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)

Definition at line 323 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)

Definition at line 324 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)

Definition at line 327 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)

Definition at line 328 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)

Definition at line 329 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FXOGS   DAHDI_SIG_FXOGS

Definition at line 334 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FXOKS   DAHDI_SIG_FXOKS

Definition at line 335 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FXOLS   DAHDI_SIG_FXOLS

Definition at line 333 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FXSGS   DAHDI_SIG_FXSGS

Definition at line 331 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), handle_init_event(), and my_is_off_hook().

#define SIG_FXSKS   DAHDI_SIG_FXSKS

Definition at line 332 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), handle_init_event(), and my_is_off_hook().

#define SIG_FXSLS   DAHDI_SIG_FXSLS

Definition at line 330 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), and handle_init_event().

#define SIG_MFCR2   DAHDI_SIG_CAS

Definition at line 340 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), and handle_mfcr2_show_channels().

#define SIG_MFCR2_MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 83 of file chan_dahdi.c.

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 336 of file chan_dahdi.c.

Referenced by dahdi_indicate(), and dahdi_sig2str().

#define SIG_PRI_LIB_HANDLE_CASES

Value:

SIG_PRI:                \
   case SIG_BRI:              \
   case SIG_BRI_PTMP

Definition at line 1519 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_bridge(), dahdi_confmute(), dahdi_digit_begin(), dahdi_enable_ec(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_send_callrerouting_facility_exec(), dahdi_sig_pri_lib_handles(), destroy_dahdi_pvt(), handle_init_event(), and my_new_pri_ast_channel().

#define SIG_SF   DAHDI_SIG_SF

Definition at line 341 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)

Definition at line 345 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)

Definition at line 343 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)

Definition at line 344 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)

Definition at line 342 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)

Definition at line 339 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), destroy_dahdi_pvt(), and handle_init_event().

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 254 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 588 of file chan_dahdi.c.

Referenced by _dahdi_get_index(), analog_ss_thread(), analogsub_to_dahdisub(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), and dahdi_show_channel().

#define SUB_REAL   0

Active call

Definition at line 587 of file chan_dahdi.c.

Referenced by __dahdi_exception(), _dahdi_get_index(), analog_ss_thread(), analogsub_to_dahdisub(), attempt_transfer(), build_device(), bump_gains(), check_for_conference(), close_call(), close_client(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_func_write(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_answered(), dahdi_r2_on_call_disconnect(), dahdi_r2_on_call_offered(), dahdi_read(), dahdi_request(), dahdi_ring_phone(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_setoption(), dahdi_show_channel(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), duplicate_pseudo(), enable_dtmf_detect(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mfcr2_monitor(), mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), my_all_subchannels_hungup(), my_complete_conference_update(), my_flash(), my_get_callerid(), my_get_event(), my_is_off_hook(), my_new_pri_ast_channel(), my_new_ss7_ast_channel(), my_off_hook(), my_pri_fixup_chans(), my_pri_open_media(), my_pri_play_tone(), my_set_cadence(), my_set_needringing(), my_set_polarity(), my_ss7_play_tone(), my_ss7_set_loopback(), my_start(), my_start_cid_detect(), my_stop_cid_detect(), my_wait_event(), my_wink(), process_request(), rcv_mac_addr(), reset_conf(), restore_conference(), restore_gains(), revert_fax_buffers(), save_conference(), send_callerid(), TransferCallStep1(), unistim_do_senddigit(), unistim_hangup(), and unistim_senddigit_end().

#define SUB_THREEWAY   2

Three-way call

Definition at line 589 of file chan_dahdi.c.

Referenced by _dahdi_get_index(), analog_ss_thread(), analogsub_to_dahdisub(), attempt_transfer(), close_call(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), HandleCallOutgoing(), TransferCallStep1(), unistim_answer(), and unistim_hangup().

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Definition at line 15419 of file chan_dahdi.c.

Referenced by action_transfer(), and dahdi_fake_event().


Enumeration Type Documentation

enum DAHDI_IFLIST

Specify the lists dahdi_pvt can be put in.

Enumerator:
DAHDI_IFLIST_NONE  The dahdi_pvt is not in any list.
DAHDI_IFLIST_MAIN  The dahdi_pvt is in the main interface list
DAHDI_IFLIST_NO_B_CHAN  The dahdi_pvt is in a no B channel interface list

Definition at line 656 of file chan_dahdi.c.

00656                   {
00657    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00658    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00659 #if defined(HAVE_PRI)
00660    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00661 #endif   /* defined(HAVE_PRI) */
00662 };

enum mwisend_states

Enumerator:
MWI_SEND_NULL 
MWI_SEND_SA 
MWI_SEND_SA_WAIT 
MWI_SEND_PAUSE 
MWI_SEND_SPILL 
MWI_SEND_CLEANUP 
MWI_SEND_DONE 

Definition at line 640 of file chan_dahdi.c.

00640              {
00641    MWI_SEND_NULL = 0,
00642    MWI_SEND_SA,
00643    MWI_SEND_SA_WAIT,
00644    MWI_SEND_PAUSE,
00645    MWI_SEND_SPILL,
00646    MWI_SEND_CLEANUP,
00647    MWI_SEND_DONE,
00648 } mwisend_states;


Function Documentation

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

Definition at line 8512 of file chan_dahdi.c.

References ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::channel, 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, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

Referenced by dahdi_exception(), and dahdi_read().

08513 {
08514    int res;
08515    int idx;
08516    struct ast_frame *f;
08517    int usedindex = -1;
08518    struct dahdi_pvt *p = ast->tech_pvt;
08519 
08520    idx = dahdi_get_index(ast, p, 1);
08521 
08522    p->subs[idx].f.frametype = AST_FRAME_NULL;
08523    p->subs[idx].f.datalen = 0;
08524    p->subs[idx].f.samples = 0;
08525    p->subs[idx].f.mallocd = 0;
08526    p->subs[idx].f.offset = 0;
08527    p->subs[idx].f.subclass.integer = 0;
08528    p->subs[idx].f.delivery = ast_tv(0,0);
08529    p->subs[idx].f.src = "dahdi_exception";
08530    p->subs[idx].f.data.ptr = NULL;
08531 
08532 
08533    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08534       /* If nobody owns us, absorb the event appropriately, otherwise
08535          we loop indefinitely.  This occurs when, during call waiting, the
08536          other end hangs up our channel so that it no longer exists, but we
08537          have neither FLASH'd nor ONHOOK'd to signify our desire to
08538          change to the other channel. */
08539       if (p->fake_event) {
08540          res = p->fake_event;
08541          p->fake_event = 0;
08542       } else
08543          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08544       /* Switch to real if there is one and this isn't something really silly... */
08545       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08546          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08547          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08548          p->owner = p->subs[SUB_REAL].owner;
08549          if (p->owner && ast_bridged_channel(p->owner))
08550             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08551          p->subs[SUB_REAL].needunhold = 1;
08552       }
08553       switch (res) {
08554       case DAHDI_EVENT_ONHOOK:
08555          dahdi_disable_ec(p);
08556          if (p->owner) {
08557             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08558             dahdi_ring_phone(p);
08559             p->callwaitingrepeat = 0;
08560             p->cidcwexpire = 0;
08561             p->cid_suppress_expire = 0;
08562          } else
08563             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08564          update_conf(p);
08565          break;
08566       case DAHDI_EVENT_RINGOFFHOOK:
08567          dahdi_enable_ec(p);
08568          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08569          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08570             p->subs[SUB_REAL].needanswer = 1;
08571             p->dialing = 0;
08572          }
08573          break;
08574       case DAHDI_EVENT_HOOKCOMPLETE:
08575       case DAHDI_EVENT_RINGERON:
08576       case DAHDI_EVENT_RINGEROFF:
08577          /* Do nothing */
08578          break;
08579       case DAHDI_EVENT_WINKFLASH:
08580          p->flashtime = ast_tvnow();
08581          if (p->owner) {
08582             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08583             if (p->owner->_state != AST_STATE_UP) {
08584                /* Answer if necessary */
08585                usedindex = dahdi_get_index(p->owner, p, 0);
08586                if (usedindex > -1) {
08587                   p->subs[usedindex].needanswer = 1;
08588                }
08589                ast_setstate(p->owner, AST_STATE_UP);
08590             }
08591             p->callwaitingrepeat = 0;
08592             p->cidcwexpire = 0;
08593             p->cid_suppress_expire = 0;
08594             if (ast_bridged_channel(p->owner))
08595                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08596             p->subs[SUB_REAL].needunhold = 1;
08597          } else
08598             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08599          update_conf(p);
08600          break;
08601       default:
08602          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08603       }
08604       f = &p->subs[idx].f;
08605       return f;
08606    }
08607    if (!(p->radio || (p->oprmode < 0)))
08608       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08609    /* If it's not us, return NULL immediately */
08610    if (ast != p->owner) {
08611       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08612       f = &p->subs[idx].f;
08613       return f;
08614    }
08615    f = dahdi_handle_event(ast);
08616 
08617    /* tell the cdr this zap device hung up */
08618    if (f == NULL) {
08619       ast_set_hangupsource(ast, ast->name, 0);
08620    }
08621 
08622    return f;
08623 }

static void __reg_module ( void   )  [static]

Definition at line 18173 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 16179 of file chan_dahdi.c.

References ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_data_unregister, ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), dahdi_cli, dahdi_close_pri_fd(), dahdi_close_ss7_fd(), dahdi_mfcr2_cli, dahdi_pri_cli, dahdi_r2_destroy_links(), dahdi_ss7_cli, dahdi_tech, destroy_all_channels(), iflist, sig_ss7_linkset::master, sig_pri_span::master, monitor_thread, monlock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::pri, sig_pri_stop_pri(), sig_pri_unload(), dahdi_pvt::ss7, and ss_thread_complete.

Referenced by load_module(), and unload_module().

16180 {
16181    struct dahdi_pvt *p;
16182 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16183    int i, j;
16184 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16185 
16186 #ifdef HAVE_PRI
16187    for (i = 0; i < NUM_SPANS; i++) {
16188       if (pris[i].pri.master != AST_PTHREADT_NULL)
16189          pthread_cancel(pris[i].pri.master);
16190    }
16191    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16192    ast_unregister_application(dahdi_send_keypad_facility_app);
16193 #ifdef HAVE_PRI_PROG_W_CAUSE
16194    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16195 #endif
16196 #endif
16197 #if defined(HAVE_SS7)
16198    for (i = 0; i < NUM_SPANS; i++) {
16199       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16200          pthread_cancel(linksets[i].ss7.master);
16201       }
16202    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16203 #endif   /* defined(HAVE_SS7) */
16204 #if defined(HAVE_OPENR2)
16205    dahdi_r2_destroy_links();
16206    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16207    ast_unregister_application(dahdi_accept_r2_call_app);
16208 #endif
16209 
16210    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16211    ast_manager_unregister("DAHDIDialOffhook");
16212    ast_manager_unregister("DAHDIHangup");
16213    ast_manager_unregister("DAHDITransfer");
16214    ast_manager_unregister("DAHDIDNDoff");
16215    ast_manager_unregister("DAHDIDNDon");
16216    ast_manager_unregister("DAHDIShowChannels");
16217    ast_manager_unregister("DAHDIRestart");
16218    ast_data_unregister(NULL);
16219    ast_channel_unregister(&dahdi_tech);
16220 
16221    /* Hangup all interfaces if they have an owner */
16222    ast_mutex_lock(&iflock);
16223    for (p = iflist; p; p = p->next) {
16224       if (p->owner)
16225          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16226    }
16227    ast_mutex_unlock(&iflock);
16228 
16229    ast_mutex_lock(&monlock);
16230    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16231       pthread_cancel(monitor_thread);
16232       pthread_kill(monitor_thread, SIGURG);
16233       pthread_join(monitor_thread, NULL);
16234    }
16235    monitor_thread = AST_PTHREADT_STOP;
16236    ast_mutex_unlock(&monlock);
16237 
16238    destroy_all_channels();
16239 
16240 #if defined(HAVE_PRI)
16241    for (i = 0; i < NUM_SPANS; i++) {
16242       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16243          pthread_join(pris[i].pri.master, NULL);
16244       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16245          dahdi_close_pri_fd(&(pris[i]), j);
16246       }
16247       sig_pri_stop_pri(&pris[i].pri);
16248    }
16249 #if defined(HAVE_PRI_CCSS)
16250    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16251    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16252 #endif   /* defined(HAVE_PRI_CCSS) */
16253    sig_pri_unload();
16254 #endif
16255 
16256 #if defined(HAVE_SS7)
16257    for (i = 0; i < NUM_SPANS; i++) {
16258       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16259          pthread_join(linksets[i].ss7.master, NULL);
16260       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16261          dahdi_close_ss7_fd(&(linksets[i]), j);
16262       }
16263    }
16264 #endif   /* defined(HAVE_SS7) */
16265    ast_cond_destroy(&ss_thread_complete);
16266    return 0;
16267 }

static void __unreg_module ( void   )  [static]

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

References ast_log(), dahdi_pvt::channel, LOG_WARNING, ast_channel::name, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

03601 {
03602    int res;
03603    if (p->subs[SUB_REAL].owner == ast)
03604       res = 0;
03605    else if (p->subs[SUB_CALLWAIT].owner == ast)
03606       res = 1;
03607    else if (p->subs[SUB_THREEWAY].owner == ast)
03608       res = 2;
03609    else {
03610       res = -1;
03611       if (!nullok)
03612          ast_log(LOG_WARNING,
03613             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03614             ast ? ast->name : "", p->channel, fname, line);
03615    }
03616    return res;
03617 }

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

Definition at line 15528 of file chan_dahdi.c.

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

Referenced by load_module().

15529 {
15530    struct dahdi_pvt *p = NULL;
15531    const char *channel = astman_get_header(m, "DAHDIChannel");
15532    const char *number = astman_get_header(m, "Number");
15533    int i;
15534 
15535    if (ast_strlen_zero(channel)) {
15536       astman_send_error(s, m, "No channel specified");
15537       return 0;
15538    }
15539    if (ast_strlen_zero(number)) {
15540       astman_send_error(s, m, "No number specified");
15541       return 0;
15542    }
15543    p = find_channel(atoi(channel));
15544    if (!p) {
15545       astman_send_error(s, m, "No such channel");
15546       return 0;
15547    }
15548    if (!p->owner) {
15549       astman_send_error(s, m, "Channel does not have it's owner");
15550       return 0;
15551    }
15552    for (i = 0; i < strlen(number); i++) {
15553       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15554       dahdi_queue_frame(p, &f);
15555    }
15556    astman_send_ack(s, m, "DAHDIDialOffhook");
15557    return 0;
15558 }

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

Definition at line 15471 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_dnd(), and find_channel().

Referenced by load_module().

15472 {
15473    struct dahdi_pvt *p = NULL;
15474    const char *channel = astman_get_header(m, "DAHDIChannel");
15475 
15476    if (ast_strlen_zero(channel)) {
15477       astman_send_error(s, m, "No channel specified");
15478       return 0;
15479    }
15480    p = find_channel(atoi(channel));
15481    if (!p) {
15482       astman_send_error(s, m, "No such channel");
15483       return 0;
15484    }
15485    dahdi_dnd(p, 0);
15486    astman_send_ack(s, m, "DND Disabled");
15487    return 0;
15488 }

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

Definition at line 15452 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_dnd(), and find_channel().

Referenced by load_module().

15453 {
15454    struct dahdi_pvt *p = NULL;
15455    const char *channel = astman_get_header(m, "DAHDIChannel");
15456 
15457    if (ast_strlen_zero(channel)) {
15458       astman_send_error(s, m, "No channel specified");
15459       return 0;
15460    }
15461    p = find_channel(atoi(channel));
15462    if (!p) {
15463       astman_send_error(s, m, "No such channel");
15464       return 0;
15465    }
15466    dahdi_dnd(p, 1);
15467    astman_send_ack(s, m, "DND Enabled");
15468    return 0;
15469 }

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

Definition at line 14760 of file chan_dahdi.c.

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

Referenced by load_module().

14761 {
14762    if (dahdi_restart() != 0) {
14763       astman_send_error(s, m, "Failed rereading DAHDI configuration");
14764       return 1;
14765    }
14766    astman_send_ack(s, m, "DAHDIRestart: Success");
14767    return 0;
14768 }

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

Definition at line 15560 of file chan_dahdi.c.

References ast_channel::accountcode, alarm2str(), ast_mutex_lock, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), dahdi_pvt::channel, channels, dahdi_pvt::context, dahdi_dnd(), get_alarms(), iflist, ast_channel::name, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, sig2str, and ast_channel::uniqueid.

Referenced by load_module().

15561 {
15562    struct dahdi_pvt *tmp = NULL;
15563    const char *id = astman_get_header(m, "ActionID");
15564    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15565    char idText[256] = "";
15566    int channels = 0;
15567    int dahdichanquery = -1;
15568    if (!ast_strlen_zero(dahdichannel)) {
15569       dahdichanquery = atoi(dahdichannel);
15570    }
15571 
15572    astman_send_ack(s, m, "DAHDI channel status will follow");
15573    if (!ast_strlen_zero(id))
15574       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15575 
15576    ast_mutex_lock(&iflock);
15577 
15578    for (tmp = iflist; tmp; tmp = tmp->next) {
15579       if (tmp->channel > 0) {
15580          int alm;
15581 
15582          /* If a specific channel is queried for, only deliver status for that channel */
15583          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15584             continue;
15585 
15586          alm = get_alarms(tmp);
15587          channels++;
15588          if (tmp->owner) {
15589             /* Add data if we have a current call */
15590             astman_append(s,
15591                "Event: DAHDIShowChannels\r\n"
15592                "DAHDIChannel: %d\r\n"
15593                "Channel: %s\r\n"
15594                "Uniqueid: %s\r\n"
15595                "AccountCode: %s\r\n"
15596                "Signalling: %s\r\n"
15597                "SignallingCode: %d\r\n"
15598                "Context: %s\r\n"
15599                "DND: %s\r\n"
15600                "Alarm: %s\r\n"
15601                "%s"
15602                "\r\n",
15603                tmp->channel,
15604                tmp->owner->name,
15605                tmp->owner->uniqueid,
15606                tmp->owner->accountcode,
15607                sig2str(tmp->sig),
15608                tmp->sig,
15609                tmp->context,
15610                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15611                alarm2str(alm), idText);
15612          } else {
15613             astman_append(s,
15614                "Event: DAHDIShowChannels\r\n"
15615                "DAHDIChannel: %d\r\n"
15616                "Signalling: %s\r\n"
15617                "SignallingCode: %d\r\n"
15618                "Context: %s\r\n"
15619                "DND: %s\r\n"
15620                "Alarm: %s\r\n"
15621                "%s"
15622                "\r\n",
15623                tmp->channel, sig2str(tmp->sig), tmp->sig,
15624                tmp->context,
15625                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15626                alarm2str(alm), idText);
15627          }
15628       }
15629    }
15630 
15631    ast_mutex_unlock(&iflock);
15632 
15633    astman_append(s,
15634       "Event: DAHDIShowChannelsComplete\r\n"
15635       "%s"
15636       "Items: %d\r\n"
15637       "\r\n",
15638       idText,
15639       channels);
15640    return 0;
15641 }

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

Definition at line 15490 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), and TRANSFER.

Referenced by load_module().

15491 {
15492    struct dahdi_pvt *p = NULL;
15493    const char *channel = astman_get_header(m, "DAHDIChannel");
15494 
15495    if (ast_strlen_zero(channel)) {
15496       astman_send_error(s, m, "No channel specified");
15497       return 0;
15498    }
15499    p = find_channel(atoi(channel));
15500    if (!p) {
15501       astman_send_error(s, m, "No such channel");
15502       return 0;
15503    }
15504    dahdi_fake_event(p,TRANSFER);
15505    astman_send_ack(s, m, "DAHDITransfer");
15506    return 0;
15507 }

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

Definition at line 15509 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), and HANGUP.

Referenced by load_module().

15510 {
15511    struct dahdi_pvt *p = NULL;
15512    const char *channel = astman_get_header(m, "DAHDIChannel");
15513 
15514    if (ast_strlen_zero(channel)) {
15515       astman_send_error(s, m, "No channel specified");
15516       return 0;
15517    }
15518    p = find_channel(atoi(channel));
15519    if (!p) {
15520       astman_send_error(s, m, "No such channel");
15521       return 0;
15522    }
15523    dahdi_fake_event(p,HANGUP);
15524    astman_send_ack(s, m, "DAHDIHangup");
15525    return 0;
15526 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4442 of file chan_dahdi.c.

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04443 {
04444    int x;
04445    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04446       if (alarms[x].alarm & alm)
04447          return alarms[x].name;
04448    }
04449    return alm ? "Unknown Alarm" : "No Alarm";
04450 }

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

Definition at line 4246 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), build_device(), dahdi_handle_event(), HandleCallOutgoing(), my_allocate_sub(), and rcv_mac_addr().

04247 {
04248    struct dahdi_bufferinfo bi;
04249    int res;
04250    if (p->subs[x].dfd >= 0) {
04251       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04252       return -1;
04253    }
04254 
04255    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04256    if (p->subs[x].dfd <= -1) {
04257       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04258       return -1;
04259    }
04260 
04261    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04262    if (!res) {
04263       bi.txbufpolicy = p->buf_policy;
04264       bi.rxbufpolicy = p->buf_policy;
04265       bi.numbufs = p->buf_no;
04266       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04267       if (res < 0) {
04268          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04269       }
04270    } else
04271       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04272 
04273    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04274       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04275       dahdi_close_sub(p, x);
04276       p->subs[x].dfd = -1;
04277       return -1;
04278    }
04279    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04280    return 0;
04281 }

static int analog_lib_handles ( int  signalling,
int  radio,
int  oprmode 
) [static]

Definition at line 4527 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_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_dnd(), dahdi_exception(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_request(), destroy_dahdi_pvt(), do_monitor(), and mwi_thread().

04528 {
04529    switch (signalling) {
04530    case SIG_FXOLS:
04531    case SIG_FXOGS:
04532    case SIG_FXOKS:
04533    case SIG_FXSLS:
04534    case SIG_FXSGS:
04535    case SIG_FXSKS:
04536    case SIG_EMWINK:
04537    case SIG_EM:
04538    case SIG_EM_E1:
04539    case SIG_FEATD:
04540    case SIG_FEATDMF:
04541    case SIG_E911:
04542    case SIG_FGC_CAMA:
04543    case SIG_FGC_CAMAMF:
04544    case SIG_FEATB:
04545    case SIG_SFWINK:
04546    case SIG_SF:
04547    case SIG_SF_FEATD:
04548    case SIG_SF_FEATDMF:
04549    case SIG_FEATDMF_TA:
04550    case SIG_SF_FEATB:
04551       break;
04552    default:
04553       /* The rest of the function should cover the remainder of signalling types */
04554       return 0;
04555    }
04556 
04557    if (radio)
04558       return 0;
04559 
04560    if (oprmode)
04561       return 0;
04562 
04563    return 1;
04564 }

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

Definition at line 9565 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_clear_flag, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, 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_valid(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), bump_gains(), dahdi_pvt::call_forward, ast_channel::caller, 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, dahdi_pvt::cid_name, 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_POLARITY_IN, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_pvt::cs, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, exten, f, firstdigittimeout, ast_smdi_md_message::fwd_st, gendigittimeout, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, ast_party_caller::id, dahdi_pvt::immediate, dahdi_pvt::inalarm, ISTRUNK, ast_channel::language, len(), dahdi_subchannel::linear, LOG_NOTICE, matchdigittimeout, my_getsigstr(), ast_party_id::name, ast_channel::name, name, NEED_MFDETECT, ast_party_id::number, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, 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_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_count, ss_thread_lock, ast_party_number::str, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, 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, and ast_party_number::valid.

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

09566 {
09567    struct ast_channel *chan = data;
09568    struct dahdi_pvt *p = chan->tech_pvt;
09569    char exten[AST_MAX_EXTENSION] = "";
09570    char exten2[AST_MAX_EXTENSION] = "";
09571    unsigned char buf[256];
09572    char dtmfcid[300];
09573    char dtmfbuf[300];
09574    struct callerid_state *cs = NULL;
09575    char *name = NULL, *number = NULL;
09576    int distMatches;
09577    int curRingData[3];
09578    int receivedRingT;
09579    int counter1;
09580    int counter;
09581    int samples = 0;
09582    struct ast_smdi_md_message *smdi_msg = NULL;
09583    int flags = 0;
09584    int i;
09585    int timeout;
09586    int getforward = 0;
09587    char *s1, *s2;
09588    int len = 0;
09589    int res;
09590    int idx;
09591 
09592    ast_mutex_lock(&ss_thread_lock);
09593    ss_thread_count++;
09594    ast_mutex_unlock(&ss_thread_lock);
09595    /* in the bizarre case where the channel has become a zombie before we
09596       even get started here, abort safely
09597    */
09598    if (!p) {
09599       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09600       ast_hangup(chan);
09601       goto quit;
09602    }
09603    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09604    idx = dahdi_get_index(chan, p, 1);
09605    if (idx < 0) {
09606       ast_log(LOG_WARNING, "Huh?\n");
09607       ast_hangup(chan);
09608       goto quit;
09609    }
09610    if (p->dsp)
09611       ast_dsp_digitreset(p->dsp);
09612    switch (p->sig) {
09613    case SIG_FEATD:
09614    case SIG_FEATDMF:
09615    case SIG_FEATDMF_TA:
09616    case SIG_E911:
09617    case SIG_FGC_CAMAMF:
09618    case SIG_FEATB:
09619    case SIG_EMWINK:
09620    case SIG_SF_FEATD:
09621    case SIG_SF_FEATDMF:
09622    case SIG_SF_FEATB:
09623    case SIG_SFWINK:
09624       if (dahdi_wink(p, idx))
09625          goto quit;
09626       /* Fall through */
09627    case SIG_EM:
09628    case SIG_EM_E1:
09629    case SIG_SF:
09630    case SIG_FGC_CAMA:
09631       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09632       if (p->dsp)
09633          ast_dsp_digitreset(p->dsp);
09634       /* set digit mode appropriately */
09635       if (p->dsp) {
09636          if (NEED_MFDETECT(p))
09637             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09638          else
09639             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09640       }
09641       memset(dtmfbuf, 0, sizeof(dtmfbuf));
09642       /* Wait for the first digit only if immediate=no */
09643       if (!p->immediate)
09644          /* Wait for the first digit (up to 5 seconds). */
09645          res = ast_waitfordigit(chan, 5000);
09646       else
09647          res = 0;
09648       if (res > 0) {
09649          /* save first char */
09650          dtmfbuf[0] = res;
09651          switch (p->sig) {
09652          case SIG_FEATD:
09653          case SIG_SF_FEATD:
09654             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09655             if (res > 0)
09656                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09657             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09658             break;
09659          case SIG_FEATDMF_TA:
09660             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09661             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09662             if (dahdi_wink(p, idx)) goto quit;
09663             dtmfbuf[0] = 0;
09664             /* Wait for the first digit (up to 5 seconds). */
09665             res = ast_waitfordigit(chan, 5000);
09666             if (res <= 0) break;
09667             dtmfbuf[0] = res;
09668             /* fall through intentionally */
09669          case SIG_FEATDMF:
09670          case SIG_E911:
09671          case SIG_FGC_CAMAMF:
09672          case SIG_SF_FEATDMF:
09673             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09674             /* if international caca, do it again to get real ANO */
09675             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09676             {
09677                if (dahdi_wink(p, idx)) goto quit;
09678                dtmfbuf[0] = 0;
09679                /* Wait for the first digit (up to 5 seconds). */
09680                res = ast_waitfordigit(chan, 5000);
09681                if (res <= 0) break;
09682                dtmfbuf[0] = res;
09683                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09684             }
09685             if (res > 0) {
09686                /* if E911, take off hook */
09687                if (p->sig == SIG_E911)
09688                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09689                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09690             }
09691             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09692             break;
09693          case SIG_FEATB:
09694          case SIG_SF_FEATB:
09695             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09696             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09697             break;
09698          case SIG_EMWINK:
09699             /* if we received a '*', we are actually receiving Feature Group D
09700                dial syntax, so use that mode; otherwise, fall through to normal
09701                mode
09702             */
09703             if (res == '*') {
09704                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09705                if (res > 0)
09706                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09707                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09708                break;
09709             }
09710          default:
09711             /* If we got the first digit, get the rest */
09712             len = 1;
09713             dtmfbuf[len] = '\0';
09714             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09715                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09716                   timeout = matchdigittimeout;
09717                } else {
09718                   timeout = gendigittimeout;
09719                }
09720                res = ast_waitfordigit(chan, timeout);
09721                if (res < 0) {
09722                   ast_debug(1, "waitfordigit returned < 0...\n");
09723                   ast_hangup(chan);
09724                   goto quit;
09725                } else if (res) {
09726                   dtmfbuf[len++] = res;
09727                   dtmfbuf[len] = '\0';
09728                } else {
09729                   break;
09730                }
09731             }
09732             break;
09733          }
09734       }
09735       if (res == -1) {
09736          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09737          ast_hangup(chan);
09738          goto quit;
09739       } else if (res < 0) {
09740          ast_debug(1, "Got hung up before digits finished\n");
09741          ast_hangup(chan);
09742          goto quit;
09743       }
09744 
09745       if (p->sig == SIG_FGC_CAMA) {
09746          char anibuf[100];
09747 
09748          if (ast_safe_sleep(chan,1000) == -1) {
09749             ast_hangup(chan);
09750             goto quit;
09751          }
09752          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09753          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09754          res = my_getsigstr(chan, anibuf, "#", 10000);
09755          if ((res > 0) && (strlen(anibuf) > 2)) {
09756             if (anibuf[strlen(anibuf) - 1] == '#')
09757                anibuf[strlen(anibuf) - 1] = 0;
09758             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09759          }
09760          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09761       }
09762 
09763       ast_copy_string(exten, dtmfbuf, sizeof(exten));
09764       if (ast_strlen_zero(exten))
09765          ast_copy_string(exten, "s", sizeof(exten));
09766       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09767          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
09768          if (exten[0] == '*') {
09769             char *stringp=NULL;
09770             ast_copy_string(exten2, exten, sizeof(exten2));
09771             /* Parse out extension and callerid */
09772             stringp=exten2 +1;
09773             s1 = strsep(&stringp, "*");
09774             s2 = strsep(&stringp, "*");
09775             if (s2) {
09776                if (!ast_strlen_zero(p->cid_num))
09777                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09778                else
09779                   ast_set_callerid(chan, s1, NULL, s1);
09780                ast_copy_string(exten, s2, sizeof(exten));
09781             } else
09782                ast_copy_string(exten, s1, sizeof(exten));
09783          } else if (p->sig == SIG_FEATD)
09784             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09785       }
09786       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09787          if (exten[0] == '*') {
09788             char *stringp=NULL;
09789             ast_copy_string(exten2, exten, sizeof(exten2));
09790             /* Parse out extension and callerid */
09791             stringp=exten2 +1;
09792             s1 = strsep(&stringp, "#");
09793             s2 = strsep(&stringp, "#");
09794             if (s2) {
09795                if (!ast_strlen_zero(p->cid_num))
09796                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09797                else
09798                   if (*(s1 + 2))
09799                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
09800                ast_copy_string(exten, s2 + 1, sizeof(exten));
09801             } else
09802                ast_copy_string(exten, s1 + 2, sizeof(exten));
09803          } else
09804             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09805       }
09806       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
09807          if (exten[0] == '*') {
09808             char *stringp=NULL;
09809             ast_copy_string(exten2, exten, sizeof(exten2));
09810             /* Parse out extension and callerid */
09811             stringp=exten2 +1;
09812             s1 = strsep(&stringp, "#");
09813             s2 = strsep(&stringp, "#");
09814             if (s2 && (*(s2 + 1) == '0')) {
09815                if (*(s2 + 2))
09816                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
09817             }
09818             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
09819             else ast_copy_string(exten, "911", sizeof(exten));
09820          } else
09821             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09822       }
09823       if (p->sig == SIG_FEATB) {
09824          if (exten[0] == '*') {
09825             char *stringp=NULL;
09826             ast_copy_string(exten2, exten, sizeof(exten2));
09827             /* Parse out extension and callerid */
09828             stringp=exten2 +1;
09829             s1 = strsep(&stringp, "#");
09830             ast_copy_string(exten, exten2 + 1, sizeof(exten));
09831          } else
09832             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09833       }
09834       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09835          dahdi_wink(p, idx);
09836          /* some switches require a minimum guard time between
09837             the last FGD wink and something that answers
09838             immediately. This ensures it */
09839          if (ast_safe_sleep(chan,100)) goto quit;
09840       }
09841       dahdi_enable_ec(p);
09842       if (NEED_MFDETECT(p)) {
09843          if (p->dsp) {
09844             if (!p->hardwaredtmf)
09845                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09846             else {
09847                ast_dsp_free(p->dsp);
09848                p->dsp = NULL;
09849             }
09850          }
09851       }
09852 
09853       if (ast_exists_extension(chan, chan->context, exten, 1,
09854          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09855          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09856          if (p->dsp) ast_dsp_digitreset(p->dsp);
09857          res = ast_pbx_run(chan);
09858          if (res) {
09859             ast_log(LOG_WARNING, "PBX exited non-zero\n");
09860             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09861          }
09862          goto quit;
09863       } else {
09864          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
09865          sleep(2);
09866          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
09867          if (res < 0)
09868             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
09869          else
09870             sleep(1);
09871          res = ast_streamfile(chan, "ss-noservice", chan->language);
09872          if (res >= 0)
09873             ast_waitstream(chan, "");
09874          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09875          ast_hangup(chan);
09876          goto quit;
09877       }
09878       break;
09879    case SIG_FXOLS:
09880    case SIG_FXOGS:
09881    case SIG_FXOKS:
09882       /* Read the first digit */
09883       timeout = firstdigittimeout;
09884       /* If starting a threeway call, never timeout on the first digit so someone
09885          can use flash-hook as a "hold" feature */
09886       if (p->subs[SUB_THREEWAY].owner)
09887          timeout = 999999;
09888       while (len < AST_MAX_EXTENSION-1) {
09889          /* Read digit unless it's supposed to be immediate, in which case the
09890             only answer is 's' */
09891          if (p->immediate)
09892             res = 's';
09893          else
09894             res = ast_waitfordigit(chan, timeout);
09895          timeout = 0;
09896          if (res < 0) {
09897             ast_debug(1, "waitfordigit returned < 0...\n");
09898             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09899             ast_hangup(chan);
09900             goto quit;
09901          } else if (res) {
09902             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
09903             exten[len++]=res;
09904             exten[len] = '\0';
09905          }
09906          if (!ast_ignore_pattern(chan->context, exten))
09907             tone_zone_play_tone(p->subs[idx].dfd, -1);
09908          else
09909             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09910          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
09911             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
09912                if (getforward) {
09913                   /* Record this as the forwarding extension */
09914                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
09915                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
09916                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09917                   if (res)
09918                      break;
09919                   usleep(500000);
09920                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09921                   sleep(1);
09922                   memset(exten, 0, sizeof(exten));
09923                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09924                   len = 0;
09925                   getforward = 0;
09926                } else {
09927                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09928                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09929                   if (!ast_strlen_zero(p->cid_num)) {
09930                      if (!p->hidecallerid)
09931                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09932                      else
09933                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
09934                   }
09935                   if (!ast_strlen_zero(p->cid_name)) {
09936                      if (!p->hidecallerid)
09937                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
09938                   }
09939                   ast_setstate(chan, AST_STATE_RING);
09940                   dahdi_enable_ec(p);
09941                   res = ast_pbx_run(chan);
09942                   if (res) {
09943                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
09944                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09945                   }
09946                   goto quit;
09947                }
09948             } else {
09949                /* It's a match, but they just typed a digit, and there is an ambiguous match,
09950                   so just set the timeout to matchdigittimeout and wait some more */
09951                timeout = matchdigittimeout;
09952             }
09953          } else if (res == 0) {
09954             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
09955             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09956             dahdi_wait_event(p->subs[idx].dfd);
09957             ast_hangup(chan);
09958             goto quit;
09959          } else if (p->callwaiting && !strcmp(exten, "*70")) {
09960             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
09961             /* Disable call waiting if enabled */
09962             p->callwaiting = 0;
09963             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09964             if (res) {
09965                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09966                   chan->name, strerror(errno));
09967             }
09968             len = 0;
09969             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
09970             memset(exten, 0, sizeof(exten));
09971             timeout = firstdigittimeout;
09972 
09973          } else if (!strcmp(exten,ast_pickup_ext())) {
09974             /* Scan all channels and see if there are any
09975              * ringing channels that have call groups
09976              * that equal this channels pickup group
09977              */
09978             if (idx == SUB_REAL) {
09979                /* Switch us from Third call to Call Wait */
09980                if (p->subs[SUB_THREEWAY].owner) {
09981                   /* If you make a threeway call and the *8# a call, it should actually
09982                      look like a callwait */
09983                   alloc_sub(p, SUB_CALLWAIT);
09984                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
09985                   unalloc_sub(p, SUB_THREEWAY);
09986                }
09987                dahdi_enable_ec(p);
09988                if (ast_pickup_call(chan)) {
09989                   ast_debug(1, "No call pickup possible...\n");
09990                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09991                   dahdi_wait_event(p->subs[idx].dfd);
09992                }
09993                ast_hangup(chan);
09994                goto quit;
09995             } else {
09996                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
09997                ast_hangup(chan);
09998                goto quit;
09999             }
10000 
10001          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10002             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10003             /* Disable Caller*ID if enabled */
10004             p->hidecallerid = 1;
10005             ast_party_number_free(&chan->caller.id.number);
10006             ast_party_number_init(&chan->caller.id.number);
10007             ast_party_name_free(&chan->caller.id.name);
10008             ast_party_name_init(&chan->caller.id.name);
10009             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10010             if (res) {
10011                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10012                   chan->name, strerror(errno));
10013             }
10014             len = 0;
10015             memset(exten, 0, sizeof(exten));
10016             timeout = firstdigittimeout;
10017          } else if (p->callreturn && !strcmp(exten, "*69")) {
10018             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10019             break;
10020          } else if (!strcmp(exten, "*78")) {
10021             dahdi_dnd(p, 1);
10022             /* Do not disturb */
10023             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10024             getforward = 0;
10025             memset(exten, 0, sizeof(exten));
10026             len = 0;
10027          } else if (!strcmp(exten, "*79")) {
10028             dahdi_dnd(p, 0);
10029             /* Do not disturb */
10030             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10031             getforward = 0;
10032             memset(exten, 0, sizeof(exten));
10033             len = 0;
10034          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10035             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10036             getforward = 1;
10037             memset(exten, 0, sizeof(exten));
10038             len = 0;
10039          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10040             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10041             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10042             memset(p->call_forward, 0, sizeof(p->call_forward));
10043             getforward = 0;
10044             memset(exten, 0, sizeof(exten));
10045             len = 0;
10046          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10047                   p->subs[SUB_THREEWAY].owner &&
10048                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10049             /* This is a three way call, the main call being a real channel,
10050                and we're parking the first call. */
10051             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
10052             ast_verb(3, "Parking call to '%s'\n", chan->name);
10053             break;
10054          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10055             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10056             /* Enable Caller*ID if enabled */
10057             p->hidecallerid = 0;
10058             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10059             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10060             if (res) {
10061                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10062                   chan->name, strerror(errno));
10063             }
10064             len = 0;
10065             memset(exten, 0, sizeof(exten));
10066             timeout = firstdigittimeout;
10067          } else if (!strcmp(exten, "*0")) {
10068             struct ast_channel *nbridge =
10069                p->subs[SUB_THREEWAY].owner;
10070             struct dahdi_pvt *pbridge = NULL;
10071             /* set up the private struct of the bridged one, if any */
10072             if (nbridge && ast_bridged_channel(nbridge))
10073                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10074             if (nbridge && pbridge &&
10075                (nbridge->tech == &dahdi_tech) &&
10076                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10077                ISTRUNK(pbridge)) {
10078                int func = DAHDI_FLASH;
10079                /* Clear out the dial buffer */
10080                p->dop.dialstr[0] = '\0';
10081                /* flash hookswitch */
10082                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10083                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10084                      nbridge->name, strerror(errno));
10085                }
10086                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10087                unalloc_sub(p, SUB_THREEWAY);
10088                p->owner = p->subs[SUB_REAL].owner;
10089                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10090                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10091                ast_hangup(chan);
10092                goto quit;
10093             } else {
10094                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10095                dahdi_wait_event(p->subs[idx].dfd);
10096                tone_zone_play_tone(p->subs[idx].dfd, -1);
10097                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10098                unalloc_sub(p, SUB_THREEWAY);
10099                p->owner = p->subs[SUB_REAL].owner;
10100                ast_hangup(chan);
10101                goto quit;
10102             }
10103          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10104             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10105             && ((exten[0] != '*') || (strlen(exten) > 2))) {
10106             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10107                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10108                chan->context);
10109             break;
10110          }
10111          if (!timeout)
10112             timeout = gendigittimeout;
10113          if (len && !ast_ignore_pattern(chan->context, exten))
10114             tone_zone_play_tone(p->subs[idx].dfd, -1);
10115       }
10116       break;
10117    case SIG_FXSLS:
10118    case SIG_FXSGS:
10119    case SIG_FXSKS:
10120       /* check for SMDI messages */
10121       if (p->use_smdi && p->smdi_iface) {
10122          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10123 
10124          if (smdi_msg != NULL) {
10125             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10126 
10127             if (smdi_msg->type == 'B')
10128                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10129             else if (smdi_msg->type == 'N')
10130                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10131 
10132             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10133          } else {
10134             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10135          }
10136       }
10137 
10138       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10139          number = smdi_msg->calling_st;
10140 
10141       /* If we want caller id, we're in a prering state due to a polarity reversal
10142        * and we're set to use a polarity reversal to trigger the start of caller id,
10143        * grab the caller id and wait for ringing to start... */
10144       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10145                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10146          /* If set to use DTMF CID signalling, listen for DTMF */
10147          if (p->cid_signalling == CID_SIG_DTMF) {
10148             int k = 0;
10149             cs = NULL;
10150             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10151             dahdi_setlinear(p->subs[idx].dfd, 0);
10152             /*
10153              * We are the only party interested in the Rx stream since
10154              * we have not answered yet.  We don't need or even want DTMF
10155              * emulation.  The DTMF digits can come so fast that emulation
10156              * can drop some of them.
10157              */
10158             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10159             res = 4000;/* This is a typical OFF time between rings. */
10160             for (;;) {
10161                struct ast_frame *f;
10162                res = ast_waitfor(chan, res);
10163                if (res <= 0) {
10164                   /*
10165                    * We do not need to restore the dahdi_setlinear()
10166                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10167                    * are hanging up the channel.
10168                    */
10169                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10170                      "Exiting simple switch\n");
10171                   ast_hangup(chan);
10172                   goto quit;
10173                }
10174                f = ast_read(chan);
10175                if (!f)
10176                   break;
10177                if (f->frametype == AST_FRAME_DTMF) {
10178                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10179                      dtmfbuf[k++] = f->subclass.integer;
10180                   }
10181                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10182                   res = 4000;/* This is a typical OFF time between rings. */
10183                }
10184                ast_frfree(f);
10185                if (chan->_state == AST_STATE_RING ||
10186                   chan->_state == AST_STATE_RINGING)
10187                   break; /* Got ring */
10188             }
10189             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10190             dtmfbuf[k] = '\0';
10191             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10192             /* Got cid and ring. */
10193             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10194             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10195             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10196             /* If first byte is NULL, we have no cid */
10197             if (!ast_strlen_zero(dtmfcid))
10198                number = dtmfcid;
10199             else
10200                number = NULL;
10201          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10202          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10203             cs = callerid_new(p->cid_signalling);
10204             if (cs) {
10205                samples = 0;
10206 #if 1
10207                bump_gains(p);
10208 #endif
10209                /* Take out of linear mode for Caller*ID processing */
10210                dahdi_setlinear(p->subs[idx].dfd, 0);
10211 
10212                /* First we wait and listen for the Caller*ID */
10213                for (;;) {
10214                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10215                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10216                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10217                      callerid_free(cs);
10218                      ast_hangup(chan);
10219                      goto quit;
10220                   }
10221                   if (i & DAHDI_IOMUX_SIGEVENT) {
10222                      res = dahdi_get_event(p->subs[idx].dfd);
10223                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10224                      if (res == DAHDI_EVENT_NOALARM) {
10225                         p->inalarm = 0;
10226                      }
10227 
10228                      if (p->cid_signalling == CID_SIG_V23_JP) {
10229                         if (res == DAHDI_EVENT_RINGBEGIN) {
10230                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10231                            usleep(1);
10232                         }
10233                      } else {
10234                         res = 0;
10235                         break;
10236                      }
10237                   } else if (i & DAHDI_IOMUX_READ) {
10238                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10239                      if (res < 0) {
10240                         if (errno != ELAST) {
10241                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10242                            callerid_free(cs);
10243                            ast_hangup(chan);
10244                            goto quit;
10245                         }
10246                         break;
10247                      }
10248                      samples += res;
10249 
10250                      if (p->cid_signalling == CID_SIG_V23_JP) {
10251                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10252                      } else {
10253                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10254                      }
10255                      if (res < 0) {
10256                         /*
10257                          * The previous diagnostic message output likely
10258                          * explains why it failed.
10259                          */
10260                         ast_log(LOG_WARNING,
10261                            "Failed to decode CallerID on channel '%s'\n",
10262                            chan->name);
10263                         break;
10264                      } else if (res)
10265                         break;
10266                      else if (samples > (8000 * 10))
10267                         break;
10268                   }
10269                }
10270                if (res == 1) {
10271                   callerid_get(cs, &name, &number, &flags);
10272                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10273                }
10274 
10275                if (p->cid_signalling == CID_SIG_V23_JP) {
10276                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10277                   usleep(1);
10278                }
10279 
10280                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10281                res = 4000;/* This is a typical OFF time between rings. */
10282                for (;;) {
10283                   struct ast_frame *f;
10284                   res = ast_waitfor(chan, res);
10285                   if (res <= 0) {
10286                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10287                         "Exiting simple switch\n");
10288                      ast_hangup(chan);
10289                      goto quit;
10290                   }
10291                   if (!(f = ast_read(chan))) {
10292                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10293                      ast_hangup(chan);
10294                      goto quit;
10295                   }
10296                   ast_frfree(f);
10297                   if (chan->_state == AST_STATE_RING ||
10298                      chan->_state == AST_STATE_RINGING)
10299                      break; /* Got ring */
10300                }
10301 
10302                /* We must have a ring by now, so, if configured, lets try to listen for
10303                 * distinctive ringing */
10304                if (p->usedistinctiveringdetection) {
10305                   len = 0;
10306                   distMatches = 0;
10307                   /* Clear the current ring data array so we don't have old data in it. */
10308                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10309                      curRingData[receivedRingT] = 0;
10310                   receivedRingT = 0;
10311                   counter = 0;
10312                   counter1 = 0;
10313                   /* Check to see if context is what it should be, if not set to be. */
10314                   if (strcmp(p->context,p->defcontext) != 0) {
10315                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10316                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10317                   }
10318 
10319                   for (;;) {
10320                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10321                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10322                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10323                         callerid_free(cs);
10324                         ast_hangup(chan);
10325                         goto quit;
10326                      }
10327                      if (i & DAHDI_IOMUX_SIGEVENT) {
10328                         res = dahdi_get_event(p->subs[idx].dfd);
10329                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10330                         if (res == DAHDI_EVENT_NOALARM) {
10331                            p->inalarm = 0;
10332                         }
10333                         res = 0;
10334                         /* Let us detect distinctive ring */
10335 
10336                         curRingData[receivedRingT] = p->ringt;
10337 
10338                         if (p->ringt < p->ringt_base/2)
10339                            break;
10340                         /* Increment the ringT counter so we can match it against
10341                            values in chan_dahdi.conf for distinctive ring */
10342                         if (++receivedRingT == ARRAY_LEN(curRingData))
10343                            break;
10344                      } else if (i & DAHDI_IOMUX_READ) {
10345                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10346                         if (res < 0) {
10347                            if (errno != ELAST) {
10348                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10349                               callerid_free(cs);
10350                               ast_hangup(chan);
10351                               goto quit;
10352                            }
10353                            break;
10354                         }
10355                         if (p->ringt > 0) {
10356                            if (!(--p->ringt)) {
10357                               res = -1;
10358                               break;
10359                            }
10360                         }
10361                      }
10362                   }
10363                      /* this only shows up if you have n of the dring patterns filled in */
10364                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10365                   for (counter = 0; counter < 3; counter++) {
10366                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10367                      channel */
10368                      distMatches = 0;
10369                      for (counter1 = 0; counter1 < 3; counter1++) {
10370                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10371                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10372                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10373                            curRingData[counter1]);
10374                            distMatches++;
10375                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10376                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10377                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10378                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10379                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10380                            distMatches++;
10381                         }
10382                      }
10383 
10384                      if (distMatches == 3) {
10385                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10386                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10387                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10388                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10389                         break;
10390                      }
10391                   }
10392                }
10393                /* Restore linear mode (if appropriate) for Caller*ID processing */
10394                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10395 #if 1
10396                restore_gains(p);
10397 #endif
10398             } else
10399                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10400          } else {
10401             ast_log(LOG_WARNING, "Channel %s in prering "
10402                "state, but I have nothing to do. "
10403                "Terminating simple switch, should be "
10404                "restarted by the actual ring.\n",
10405                chan->name);
10406             ast_hangup(chan);
10407             goto quit;
10408          }
10409       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10410          if (p->cid_signalling == CID_SIG_DTMF) {
10411             int k = 0;
10412             cs = NULL;
10413             dahdi_setlinear(p->subs[idx].dfd, 0);
10414             res = 2000;
10415             for (;;) {
10416                struct ast_frame *f;
10417                res = ast_waitfor(chan, res);
10418                if (res <= 0) {
10419                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10420                      "Exiting simple switch\n");
10421                   ast_hangup(chan);
10422                   return NULL;
10423                }
10424                f = ast_read(chan);
10425                if (f->frametype == AST_FRAME_DTMF) {
10426                   dtmfbuf[k++] = f->subclass.integer;
10427                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10428                   res = 2000;
10429                }
10430                ast_frfree(f);
10431 
10432                if (p->ringt_base == p->ringt)
10433                   break;
10434             }
10435             dtmfbuf[k] = '\0';
10436             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10437             /* Got cid and ring. */
10438             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10439             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10440                dtmfcid, flags);
10441             /* If first byte is NULL, we have no cid */
10442             if (!ast_strlen_zero(dtmfcid))
10443                number = dtmfcid;
10444             else
10445                number = NULL;
10446             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10447          } else {
10448             /* FSK Bell202 callerID */
10449             cs = callerid_new(p->cid_signalling);
10450             if (cs) {
10451 #if 1
10452                bump_gains(p);
10453 #endif
10454                samples = 0;
10455                len = 0;
10456                distMatches = 0;
10457                /* Clear the current ring data array so we don't have old data in it. */
10458                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10459                   curRingData[receivedRingT] = 0;
10460                receivedRingT = 0;
10461                counter = 0;
10462                counter1 = 0;
10463                /* Check to see if context is what it should be, if not set to be. */
10464                if (strcmp(p->context,p->defcontext) != 0) {
10465                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10466                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10467                }
10468 
10469                /* Take out of linear mode for Caller*ID processing */
10470                dahdi_setlinear(p->subs[idx].dfd, 0);
10471                for (;;) {
10472                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10473                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10474                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10475                      callerid_free(cs);
10476                      ast_hangup(chan);
10477                      goto quit;
10478                   }
10479                   if (i & DAHDI_IOMUX_SIGEVENT) {
10480                      res = dahdi_get_event(p->subs[idx].dfd);
10481                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10482                      if (res == DAHDI_EVENT_NOALARM) {
10483                         p->inalarm = 0;
10484                      }
10485                      /* If we get a PR event, they hung up while processing calerid */
10486                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10487                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10488                         p->polarity = POLARITY_IDLE;
10489                         callerid_free(cs);
10490                         ast_hangup(chan);
10491                         goto quit;
10492                      }
10493                      res = 0;
10494                      /* Let us detect callerid when the telco uses distinctive ring */
10495 
10496                      curRingData[receivedRingT] = p->ringt;
10497 
10498                      if (p->ringt < p->ringt_base/2)
10499                         break;
10500                      /* Increment the ringT counter so we can match it against
10501                         values in chan_dahdi.conf for distinctive ring */
10502                      if (++receivedRingT == ARRAY_LEN(curRingData))
10503                         break;
10504                   } else if (i & DAHDI_IOMUX_READ) {
10505                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10506                      if (res < 0) {
10507                         if (errno != ELAST) {
10508                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10509                            callerid_free(cs);
10510                            ast_hangup(chan);
10511                            goto quit;
10512                         }
10513                         break;
10514                      }
10515                      if (p->ringt > 0) {
10516                         if (!(--p->ringt)) {
10517                            res = -1;
10518                            break;
10519                         }
10520                      }
10521                      samples += res;
10522                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10523                      if (res < 0) {
10524                         /*
10525                          * The previous diagnostic message output likely
10526                          * explains why it failed.
10527                          */
10528                         ast_log(LOG_WARNING,
10529                            "Failed to decode CallerID on channel '%s'\n",
10530                            chan->name);
10531                         break;
10532                      } else if (res)
10533                         break;
10534                      else if (samples > (8000 * 10))
10535                         break;
10536                   }
10537                }
10538                if (res == 1) {
10539                   callerid_get(cs, &name, &number, &flags);
10540                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10541                }
10542                if (distinctiveringaftercid == 1) {
10543                   /* Clear the current ring data array so we don't have old data in it. */
10544                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10545                      curRingData[receivedRingT] = 0;
10546                   }
10547                   receivedRingT = 0;
10548                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10549                   for (;;) {
10550                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10551                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10552                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10553                         callerid_free(cs);
10554                         ast_hangup(chan);
10555                         goto quit;
10556                      }
10557                      if (i & DAHDI_IOMUX_SIGEVENT) {
10558                         res = dahdi_get_event(p->subs[idx].dfd);
10559                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10560                         if (res == DAHDI_EVENT_NOALARM) {
10561                            p->inalarm = 0;
10562                         }
10563                         res = 0;
10564                         /* Let us detect callerid when the telco uses distinctive ring */
10565 
10566                         curRingData[receivedRingT] = p->ringt;
10567 
10568                         if (p->ringt < p->ringt_base/2)
10569                            break;
10570                         /* Increment the ringT counter so we can match it against
10571                            values in chan_dahdi.conf for distinctive ring */
10572                         if (++receivedRingT == ARRAY_LEN(curRingData))
10573                            break;
10574                      } else if (i & DAHDI_IOMUX_READ) {
10575                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10576                         if (res < 0) {
10577                            if (errno != ELAST) {
10578                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10579                               callerid_free(cs);
10580                               ast_hangup(chan);
10581                               goto quit;
10582                            }
10583                            break;
10584                         }
10585                         if (p->ringt > 0) {
10586                            if (!(--p->ringt)) {
10587                               res = -1;
10588                               break;
10589                            }
10590                         }
10591                      }
10592                   }
10593                }
10594                if (p->usedistinctiveringdetection) {
10595                   /* this only shows up if you have n of the dring patterns filled in */
10596                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10597 
10598                   for (counter = 0; counter < 3; counter++) {
10599                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10600                      channel */
10601                      /* this only shows up if you have n of the dring patterns filled in */
10602                      ast_verb(3, "Checking %d,%d,%d\n",
10603                            p->drings.ringnum[counter].ring[0],
10604                            p->drings.ringnum[counter].ring[1],
10605                            p->drings.ringnum[counter].ring[2]);
10606                      distMatches = 0;
10607                      for (counter1 = 0; counter1 < 3; counter1++) {
10608                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10609                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10610                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10611                            curRingData[counter1]);
10612                            distMatches++;
10613                         }
10614                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10615                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10616                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10617                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10618                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10619                            distMatches++;
10620                         }
10621                      }
10622                      if (distMatches == 3) {
10623                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10624                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10625                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10626                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10627                         break;
10628                      }
10629                   }
10630                }
10631                /* Restore linear mode (if appropriate) for Caller*ID processing */
10632                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10633 #if 1
10634                restore_gains(p);
10635 #endif
10636                if (res < 0) {
10637                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10638                }
10639             } else
10640                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10641          }
10642       } else
10643          cs = NULL;
10644 
10645       if (number)
10646          ast_shrink_phone_number(number);
10647       ast_set_callerid(chan, number, name, number);
10648 
10649       if (smdi_msg)
10650          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10651 
10652       if (cs)
10653          callerid_free(cs);
10654 
10655       my_handle_notify_message(chan, p, flags, -1);
10656 
10657       ast_setstate(chan, AST_STATE_RING);
10658       chan->rings = 1;
10659       p->ringt = p->ringt_base;
10660       res = ast_pbx_run(chan);
10661       if (res) {
10662          ast_hangup(chan);
10663          ast_log(LOG_WARNING, "PBX exited non-zero\n");
10664       }
10665       goto quit;
10666    default:
10667       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10668       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10669       if (res < 0)
10670             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10671    }
10672    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10673    if (res < 0)
10674          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10675    ast_hangup(chan);
10676 quit:
10677    ast_mutex_lock(&ss_thread_lock);
10678    ss_thread_count--;
10679    ast_cond_signal(&ss_thread_complete);
10680    ast_mutex_unlock(&ss_thread_lock);
10681    return NULL;
10682 }

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

Definition at line 1600 of file chan_dahdi.c.

References ANALOG_TONE_CONGESTION, ANALOG_TONE_DIALRECALL, ANALOG_TONE_DIALTONE, ANALOG_TONE_INFO, ANALOG_TONE_RINGTONE, and ANALOG_TONE_STUTTER.

Referenced by my_play_tone().

01601 {
01602    switch (tone) {
01603    case ANALOG_TONE_RINGTONE:
01604       return DAHDI_TONE_RINGTONE;
01605    case ANALOG_TONE_STUTTER:
01606       return DAHDI_TONE_STUTTER;
01607    case ANALOG_TONE_CONGESTION:
01608       return DAHDI_TONE_CONGESTION;
01609    case ANALOG_TONE_DIALTONE:
01610       return DAHDI_TONE_DIALTONE;
01611    case ANALOG_TONE_DIALRECALL:
01612       return DAHDI_TONE_DIALRECALL;
01613    case ANALOG_TONE_INFO:
01614       return DAHDI_TONE_INFO;
01615    default:
01616       return -1;
01617    }
01618 }

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

Definition at line 1620 of file chan_dahdi.c.

References ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY, ast_log(), LOG_ERROR, SUB_CALLWAIT, SUB_REAL, and SUB_THREEWAY.

Referenced by my_allocate_sub(), my_conf_add(), my_conf_del(), my_dial_digits(), my_get_sub_fd(), my_handle_dtmf(), my_is_dialing(), my_new_analog_ast_channel(), my_play_tone(), my_set_inthreeway(), my_set_linear_mode(), my_swap_subchannels(), my_unallocate_sub(), and my_wink().

01621 {
01622    int index;
01623 
01624    switch (analogsub) {
01625    case ANALOG_SUB_REAL:
01626       index = SUB_REAL;
01627       break;
01628    case ANALOG_SUB_CALLWAIT:
01629       index = SUB_CALLWAIT;
01630       break;
01631    case ANALOG_SUB_THREEWAY:
01632       index = SUB_THREEWAY;
01633       break;
01634    default:
01635       ast_log(LOG_ERROR, "Unidentified sub!\n");
01636       index = SUB_REAL;
01637    }
01638 
01639    return index;
01640 }

AST_DATA_STRUCTURE ( dahdi_pvt  ,
DATA_EXPORT_DAHDI_PVT   
)

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 7420 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_unlock, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().

Referenced by close_call(), dahdi_handle_event(), handle_request(), and local_attended_transfer().

07421 {
07422    /* In order to transfer, we need at least one of the channels to
07423       actually be in a call bridge.  We can't conference two applications
07424       together (but then, why would we want to?) */
07425    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07426       /* The three-way person we're about to transfer to could still be in MOH, so
07427          stop if now if appropriate */
07428       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07429          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07430       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07431          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07432       }
07433       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07434          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07435       }
07436        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07437          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07438                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07439          return -1;
07440       }
07441       /* Orphan the channel after releasing the lock */
07442       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07443       unalloc_sub(p, SUB_THREEWAY);
07444    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07445       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07446       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07447          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07448       }
07449       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07450          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07451       }
07452       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07453          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07454                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07455          return -1;
07456       }
07457       /* Three-way is now the REAL */
07458       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07459       ast_channel_unlock(p->subs[SUB_REAL].owner);
07460       unalloc_sub(p, SUB_THREEWAY);
07461       /* Tell the caller not to hangup */
07462       return 1;
07463    } else {
07464       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07465          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07466       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07467       return -1;
07468    }
07469    return 0;
07470 }

static int available ( struct dahdi_pvt **  pvt,
int  is_specific_channel 
) [static]

Definition at line 12829 of file chan_dahdi.c.

References analog_available(), analog_lib_handles(), sig_pri_chan::chan_pvt, dahdi_pvt::inalarm, dahdi_pvt::locallyblocked, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2call, dahdi_pvt::oprmode, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::remotelyblocked, dahdi_pvt::sig, sig_pri_available(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, and sig_ss7_available().

Referenced by __ast_string_field_ptr_build_va(), ast_logger_register_level(), and dahdi_request().

12830 {
12831    struct dahdi_pvt *p = *pvt;
12832 
12833    if (p->inalarm)
12834       return 0;
12835 
12836    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
12837       return analog_available(p->sig_pvt);
12838 
12839    switch (p->sig) {
12840 #if defined(HAVE_PRI)
12841    case SIG_PRI_LIB_HANDLE_CASES:
12842       {
12843          struct sig_pri_chan *pvt_chan;
12844          int res;
12845 
12846          pvt_chan = p->sig_pvt;
12847          res = sig_pri_available(&pvt_chan, is_specific_channel);
12848          *pvt = pvt_chan->chan_pvt;
12849          return res;
12850       }
12851 #endif   /* defined(HAVE_PRI) */
12852 #if defined(HAVE_SS7)
12853    case SIG_SS7:
12854       return sig_ss7_available(p->sig_pvt);
12855 #endif   /* defined(HAVE_SS7) */
12856    default:
12857       break;
12858    }
12859 
12860    if (p->locallyblocked || p->remotelyblocked) {
12861       return 0;
12862    }
12863 
12864    /* If no owner definitely available */
12865    if (!p->owner) {
12866 #ifdef HAVE_OPENR2
12867       /* Trust MFC/R2 */
12868       if (p->mfcr2) {
12869          if (p->mfcr2call) {
12870             return 0;
12871          } else {
12872             return 1;
12873          }
12874       }
12875 #endif
12876       return 1;
12877    }
12878 
12879    return 0;
12880 }

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

Definition at line 16308 of file chan_dahdi.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), ast_verb, dahdi_chan_conf::chan, CHAN_PSEUDO, device2chan(), dahdi_chan_conf::ignore_failed_channels, dahdi_chan_conf::is_sig_auto, mkintf(), parse_spanchan(), dahdi_pvt::sig, sig2str, and strsep().

Referenced by process_dahdi().

16309 {
16310    char *c, *chan;
16311    char *subdir;
16312    int x, start, finish;
16313    struct dahdi_pvt *tmp;
16314 
16315    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16316       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16317       return -1;
16318    }
16319 
16320    c = ast_strdupa(value);
16321    c = parse_spanchan(c, &subdir);
16322 
16323    while ((chan = strsep(&c, ","))) {
16324       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16325          /* Range */
16326       } else if (sscanf(chan, "%30d", &start)) {
16327          /* Just one */
16328          finish = start;
16329       } else if (!strcasecmp(chan, "pseudo")) {
16330          finish = start = CHAN_PSEUDO;
16331          if (found_pseudo)
16332             *found_pseudo = 1;
16333       } else {
16334          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16335          return -1;
16336       }
16337       if (finish < start) {
16338          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16339          x = finish;
16340          finish = start;
16341          start = x;
16342       }
16343 
16344       for (x = start; x <= finish; x++) {
16345          char fn[PATH_MAX];
16346          int real_channel = x;
16347 
16348          if (!ast_strlen_zero(subdir)) {
16349             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16350             if (real_channel < 0) {
16351                if (conf->ignore_failed_channels) {
16352                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16353                         subdir, x, real_channel);
16354                   continue;
16355                } else {
16356                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16357                         subdir, x, real_channel);
16358                   return -1;
16359                }
16360             }
16361          }
16362          tmp = mkintf(real_channel, conf, reload);
16363 
16364          if (tmp) {
16365             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16366          } else {
16367             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16368                   (reload == 1) ? "reconfigure" : "register", value);
16369             return -1;
16370          }
16371       }
16372    }
16373 
16374    return 0;
16375 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 4984 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::cid_rxgain, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, and dahdi_pvt::txgain.

Referenced by analog_ss_thread(), mwi_thread(), and my_start_cid_detect().

04985 {
04986    int res;
04987 
04988    /* Bump receive gain by value stored in cid_rxgain */
04989    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04990    if (res) {
04991       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
04992       return -1;
04993    }
04994 
04995    return 0;
04996 }

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

Definition at line 10690 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by mwi_thread().

10691 {
10692    int x;
10693    int sum = 0;
10694 
10695    if (!len)
10696       return 0;
10697 
10698    for (x = 0; x < len; x++)
10699       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10700 
10701    return sum / len;
10702 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 7472 of file chan_dahdi.c.

References ast_log(), ast_verb, dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), and my_check_for_conference().

07473 {
07474    struct dahdi_confinfo ci;
07475    /* Fine if we already have a master, etc */
07476    if (p->master || (p->confno > -1))
07477       return 0;
07478    memset(&ci, 0, sizeof(ci));
07479    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07480       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07481       return 0;
07482    }
07483    /* If we have no master and don't have a confno, then
07484       if we're in a conference, it's probably a MeetMe room or
07485       some such, so don't let us 3-way out! */
07486    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07487       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07488       return 1;
07489    }
07490    return 0;
07491 }

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

Definition at line 13845 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

13846 {
13847    return complete_span_helper(line,word,pos,state,3);
13848 }

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

Definition at line 13824 of file chan_dahdi.c.

References asprintf, ast_log(), errno, dahdi_pri::pri, and pris.

Referenced by complete_span_4().

13825 {
13826    int which, span;
13827    char *ret = NULL;
13828 
13829    if (pos != rpos)
13830       return ret;
13831 
13832    for (which = span = 0; span < NUM_SPANS; span++) {
13833       if (pris[span].pri.pri && ++which > state) {
13834          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
13835             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13836          }
13837          break;
13838       }
13839    }
13840    return ret;
13841 }

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

Definition at line 4566 of file chan_dahdi.c.

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

Referenced by my_complete_conference_update(), my_conf_add(), and update_conf().

04567 {
04568    /* If the conference already exists, and we're already in it
04569       don't bother doing anything */
04570    struct dahdi_confinfo zi;
04571 
04572    memset(&zi, 0, sizeof(zi));
04573    zi.chan = 0;
04574 
04575    if (slavechannel > 0) {
04576       /* If we have only one slave, do a digital mon */
04577       zi.confmode = DAHDI_CONF_DIGITALMON;
04578       zi.confno = slavechannel;
04579    } else {
04580       if (!idx) {
04581          /* Real-side and pseudo-side both participate in conference */
04582          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04583             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04584       } else
04585          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04586       zi.confno = p->confno;
04587    }
04588    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04589       return 0;
04590    if (c->dfd < 0)
04591       return 0;
04592    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04593       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04594       return -1;
04595    }
04596    if (slavechannel < 1) {
04597       p->confno = zi.confno;
04598    }
04599    c->curconf = zi;
04600    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04601    return 0;
04602 }

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

Definition at line 4615 of file chan_dahdi.c.

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

Referenced by dahdi_unlink(), my_conf_del(), and update_conf().

04616 {
04617    struct dahdi_confinfo zi;
04618    if (/* Can't delete if there's no dfd */
04619       (c->dfd < 0) ||
04620       /* Don't delete from the conference if it's not our conference */
04621       !isourconf(p, c)
04622       /* Don't delete if we don't think it's conferenced at all (implied) */
04623       ) return 0;
04624    memset(&zi, 0, sizeof(zi));
04625    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04626       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04627       return -1;
04628    }
04629    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04630    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04631    return 0;
04632 }

static struct ast_str* create_channel_name ( struct dahdi_pvt i,
int  is_outgoing,
char *  address 
) [static]

Definition at line 9233 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero(), and CHAN_PSEUDO.

Referenced by dahdi_cc_callback(), and dahdi_new().

09237 {
09238    struct ast_str *chan_name;
09239    int x, y;
09240 
09241    /* Create the new channel name tail. */
09242    if (!(chan_name = ast_str_create(32))) {
09243       return NULL;
09244    }
09245    if (i->channel == CHAN_PSEUDO) {
09246       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09247 #if defined(HAVE_PRI)
09248    } else if (i->pri) {
09249       ast_mutex_lock(&i->pri->lock);
09250       y = ++i->pri->new_chan_seq;
09251       if (is_outgoing) {
09252          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09253          address[0] = '\0';
09254       } else if (ast_strlen_zero(i->cid_subaddr)) {
09255          /* Put in caller-id number only since there is no subaddress. */
09256          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09257       } else {
09258          /* Put in caller-id number and subaddress. */
09259          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09260             i->cid_subaddr, y);
09261       }
09262       ast_mutex_unlock(&i->pri->lock);
09263 #endif   /* defined(HAVE_PRI) */
09264    } else {
09265       y = 1;
09266       do {
09267          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09268          for (x = 0; x < 3; ++x) {
09269             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09270                i->subs[x].owner->name + 6)) {
09271                break;
09272             }
09273          }
09274          ++y;
09275       } while (x < 3);
09276    }
09277    return chan_name;
09278 }

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

Definition at line 5841 of file chan_dahdi.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_strlen_zero(), dahdi_tech, f, LOG_DEBUG, parse(), and ast_channel::tech.

Referenced by load_module().

05842 {
05843    /* data is whether to accept with charge or no charge */
05844    openr2_call_mode_t accept_mode;
05845    int res, timeout, maxloops;
05846    struct ast_frame *f;
05847    struct dahdi_pvt *p;
05848    char *parse;
05849    AST_DECLARE_APP_ARGS(args,
05850          AST_APP_ARG(charge);
05851    );
05852 
05853    if (ast_strlen_zero(data)) {
05854       ast_log(LOG_DEBUG, "No data sent to application!\n");
05855       return -1;
05856    }
05857 
05858    if (chan->tech != &dahdi_tech) {
05859       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05860       return -1;
05861    }
05862 
05863    p = (struct dahdi_pvt *)chan->tech_pvt;
05864    if (!p) {
05865       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05866       return -1;
05867    }
05868 
05869    parse = ast_strdupa(data);
05870    AST_STANDARD_APP_ARGS(args, parse);
05871 
05872    if (ast_strlen_zero(args.charge)) {
05873       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05874       return -1;
05875    }
05876 
05877    ast_mutex_lock(&p->lock);
05878    if (!p->mfcr2 || !p->mfcr2call) {
05879       ast_mutex_unlock(&p->lock);
05880       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05881       return -1;
05882    }
05883 
05884    if (p->mfcr2_call_accepted) {
05885       ast_mutex_unlock(&p->lock);
05886       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05887       return 0;
05888    }
05889    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05890    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05891       ast_mutex_unlock(&p->lock);
05892       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05893       return -1;
05894    }
05895    ast_mutex_unlock(&p->lock);
05896 
05897    res = 0;
05898    timeout = 100;
05899    maxloops = 50; /* wait up to 5 seconds */
05900    /* we need to read() until the call is accepted */
05901    while (maxloops > 0) {
05902       maxloops--;
05903       if (ast_check_hangup(chan)) {
05904          break;
05905       }
05906       res = ast_waitfor(chan, timeout);
05907       if (res < 0) {
05908          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05909          res = -1;
05910          break;
05911       }
05912       if (res == 0) {
05913          continue;
05914       }
05915       f = ast_read(chan);
05916       if (!f) {
05917          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05918          res = -1;
05919          break;
05920       }
05921       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05922          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05923          ast_frfree(f);
05924          res = -1;
05925          break;
05926       }
05927       ast_frfree(f);
05928       ast_mutex_lock(&p->lock);
05929       if (p->mfcr2_call_accepted) {
05930          ast_mutex_unlock(&p->lock);
05931          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05932          break;
05933       }
05934       ast_mutex_unlock(&p->lock);
05935    }
05936    if (res == -1) {
05937       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05938    }
05939    return res;
05940 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 6396 of file chan_dahdi.c.

References analog_answer(), analog_lib_handles(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, dahdi_pvt::channel, dahdi_get_index, dahdi_r2_answer(), dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::oprmode, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::sig, SIG_MFCR2, sig_pri_answer(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_answer(), SUB_REAL, and ast_channel::tech_pvt.

06397 {
06398    struct dahdi_pvt *p = ast->tech_pvt;
06399    int res = 0;
06400    int idx;
06401    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06402    ast_mutex_lock(&p->lock);
06403    idx = dahdi_get_index(ast, p, 0);
06404    if (idx < 0)
06405       idx = SUB_REAL;
06406    /* nothing to do if a radio channel */
06407    if ((p->radio || (p->oprmode < 0))) {
06408       ast_mutex_unlock(&p->lock);
06409       return 0;
06410    }
06411 
06412    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06413       res = analog_answer(p->sig_pvt, ast);
06414       ast_mutex_unlock(&p->lock);
06415       return res;
06416    }
06417 
06418    switch (p->sig) {
06419 #if defined(HAVE_PRI)
06420    case SIG_PRI_LIB_HANDLE_CASES:
06421       res = sig_pri_answer(p->sig_pvt, ast);
06422       break;
06423 #endif   /* defined(HAVE_PRI) */
06424 #if defined(HAVE_SS7)
06425    case SIG_SS7:
06426       res = sig_ss7_answer(p->sig_pvt, ast);
06427       break;
06428 #endif   /* defined(HAVE_SS7) */
06429 #ifdef HAVE_OPENR2
06430    case SIG_MFCR2:
06431       if (!p->mfcr2_call_accepted) {
06432          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06433             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06434          p->mfcr2_answer_pending = 1;
06435          if (p->mfcr2_charge_calls) {
06436             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06437             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06438          } else {
06439             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06440             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06441          }
06442       } else {
06443          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06444          dahdi_r2_answer(p);
06445       }
06446       break;
06447 #endif
06448    case 0:
06449       ast_mutex_unlock(&p->lock);
06450       return 0;
06451    default:
06452       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06453       res = -1;
06454       break;
06455    }
06456    ast_mutex_unlock(&p->lock);
06457    return res;
06458 }

static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause ( int  cause  )  [static]

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

05943 {
05944    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
05945    switch (cause) {
05946    case AST_CAUSE_USER_BUSY:
05947    case AST_CAUSE_CALL_REJECTED:
05948    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
05949       r2cause = OR2_CAUSE_BUSY_NUMBER;
05950       break;
05951 
05952    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
05953    case AST_CAUSE_SWITCH_CONGESTION:
05954       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
05955       break;
05956 
05957    case AST_CAUSE_UNALLOCATED:
05958       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
05959       break;
05960 
05961    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
05962    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
05963       r2cause = OR2_CAUSE_OUT_OF_ORDER;
05964       break;
05965 
05966    case AST_CAUSE_NO_ANSWER:
05967    case AST_CAUSE_NO_USER_RESPONSE:
05968       r2cause = OR2_CAUSE_NO_ANSWER;
05969       break;
05970 
05971    default:
05972       r2cause = OR2_CAUSE_NORMAL_CLEARING;
05973       break;
05974    }
05975    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
05976          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
05977    return r2cause;
05978 }

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 6997 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_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, 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_verb, ast_waitfor_n(), ast_write(), sig_pri_chan::call, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_link(), dahdi_sig_pri_lib_handles(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, sig_pri_span::lock, dahdi_pvt::lock, LOG_NOTICE, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::pulsedial, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, subnames, dahdi_pvt::subs, t1, ast_channel::tech_pvt, sig_pri_span::transfer, and update_conf().

06998 {
06999    struct ast_channel *who;
07000    struct dahdi_pvt *p0, *p1, *op0, *op1;
07001    struct dahdi_pvt *master = NULL, *slave = NULL;
07002    struct ast_frame *f;
07003    int inconf = 0;
07004    int nothingok = 1;
07005    int ofd0, ofd1;
07006    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07007    int os0 = -1, os1 = -1;
07008    int priority = 0;
07009    struct ast_channel *oc0, *oc1;
07010    enum ast_bridge_result res;
07011 #ifdef PRI_2BCT
07012    int triedtopribridge = 0;
07013    q931_call *q931c0;
07014    q931_call *q931c1;
07015 #endif
07016 
07017    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07018       There is code below to handle it properly until DTMF is actually seen,
07019       but due to currently unresolved issues it's ignored...
07020    */
07021 
07022    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07023       return AST_BRIDGE_FAILED_NOWARN;
07024 
07025    ast_channel_lock(c0);
07026    while (ast_channel_trylock(c1)) {
07027       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07028    }
07029 
07030    p0 = c0->tech_pvt;
07031    p1 = c1->tech_pvt;
07032    /* cant do pseudo-channels here */
07033    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07034       ast_channel_unlock(c0);
07035       ast_channel_unlock(c1);
07036       return AST_BRIDGE_FAILED_NOWARN;
07037    }
07038 
07039    oi0 = dahdi_get_index(c0, p0, 0);
07040    oi1 = dahdi_get_index(c1, p1, 0);
07041    if ((oi0 < 0) || (oi1 < 0)) {
07042       ast_channel_unlock(c0);
07043       ast_channel_unlock(c1);
07044       return AST_BRIDGE_FAILED;
07045    }
07046 
07047    op0 = p0 = c0->tech_pvt;
07048    op1 = p1 = c1->tech_pvt;
07049    ofd0 = c0->fds[0];
07050    ofd1 = c1->fds[0];
07051    oc0 = p0->owner;
07052    oc1 = p1->owner;
07053 
07054    if (ast_mutex_trylock(&p0->lock)) {
07055       /* Don't block, due to potential for deadlock */
07056       ast_channel_unlock(c0);
07057       ast_channel_unlock(c1);
07058       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07059       return AST_BRIDGE_RETRY;
07060    }
07061    if (ast_mutex_trylock(&p1->lock)) {
07062       /* Don't block, due to potential for deadlock */
07063       ast_mutex_unlock(&p0->lock);
07064       ast_channel_unlock(c0);
07065       ast_channel_unlock(c1);
07066       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07067       return AST_BRIDGE_RETRY;
07068    }
07069 
07070    if ((p0->callwaiting && p0->callwaitingcallerid)
07071       || (p1->callwaiting && p1->callwaitingcallerid)) {
07072       /*
07073        * Call Waiting Caller ID requires DTMF detection to know if it
07074        * can send the CID spill.
07075        *
07076        * For now, don't attempt to native bridge if either channel
07077        * needs DTMF detection.  There is code below to handle it
07078        * properly until DTMF is actually seen, but due to currently
07079        * unresolved issues it's ignored...
07080        */
07081       ast_mutex_unlock(&p0->lock);
07082       ast_mutex_unlock(&p1->lock);
07083       ast_channel_unlock(c0);
07084       ast_channel_unlock(c1);
07085       return AST_BRIDGE_FAILED_NOWARN;
07086    }
07087 
07088 #if defined(HAVE_PRI)
07089    if ((dahdi_sig_pri_lib_handles(p0->sig)
07090          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07091       || (dahdi_sig_pri_lib_handles(p1->sig)
07092          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07093       /*
07094        * PRI nobch channels (hold and call waiting) are equivalent to
07095        * pseudo channels and cannot be done here.
07096        */
07097       ast_mutex_unlock(&p0->lock);
07098       ast_mutex_unlock(&p1->lock);
07099       ast_channel_unlock(c0);
07100       ast_channel_unlock(c1);
07101       return AST_BRIDGE_FAILED_NOWARN;
07102    }
07103 #endif   /* defined(HAVE_PRI) */
07104 
07105    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07106       if (p0->owner && p1->owner) {
07107          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07108          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07109             master = p0;
07110             slave = p1;
07111             inconf = 1;
07112          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07113             master = p1;
07114             slave = p0;
07115             inconf = 1;
07116          } else {
07117             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07118             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07119                p0->channel,
07120                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07121                p0->subs[SUB_REAL].inthreeway, p0->channel,
07122                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07123                p1->subs[SUB_REAL].inthreeway);
07124          }
07125          nothingok = 0;
07126       }
07127    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07128       if (p1->subs[SUB_THREEWAY].inthreeway) {
07129          master = p1;
07130          slave = p0;
07131          nothingok = 0;
07132       }
07133    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07134       if (p0->subs[SUB_THREEWAY].inthreeway) {
07135          master = p0;
07136          slave = p1;
07137          nothingok = 0;
07138       }
07139    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07140       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07141          don't put us in anything */
07142       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07143          master = p1;
07144          slave = p0;
07145          nothingok = 0;
07146       }
07147    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07148       /* Same as previous */
07149       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07150          master = p0;
07151          slave = p1;
07152          nothingok = 0;
07153       }
07154    }
07155    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07156       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07157    if (master && slave) {
07158       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07159          in an active threeway call with a channel that is ringing, we should
07160          indicate ringing. */
07161       if ((oi1 == SUB_THREEWAY) &&
07162          p1->subs[SUB_THREEWAY].inthreeway &&
07163          p1->subs[SUB_REAL].owner &&
07164          p1->subs[SUB_REAL].inthreeway &&
07165          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07166          ast_debug(1,
07167             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07168             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07169          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07170          os1 = p1->subs[SUB_REAL].owner->_state;
07171       } else {
07172          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07173             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07174          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07175       }
07176       if ((oi0 == SUB_THREEWAY) &&
07177          p0->subs[SUB_THREEWAY].inthreeway &&
07178          p0->subs[SUB_REAL].owner &&
07179          p0->subs[SUB_REAL].inthreeway &&
07180          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07181          ast_debug(1,
07182             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07183             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07184          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07185          os0 = p0->subs[SUB_REAL].owner->_state;
07186       } else {
07187          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07188             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07189          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07190       }
07191       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07192          if (!p0->echocanbridged || !p1->echocanbridged) {
07193             /* Disable echo cancellation if appropriate */
07194             dahdi_disable_ec(p0);
07195             dahdi_disable_ec(p1);
07196          }
07197       }
07198       dahdi_link(slave, master);
07199       master->inconference = inconf;
07200    } else if (!nothingok)
07201       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07202 
07203    update_conf(p0);
07204    update_conf(p1);
07205    t0 = p0->subs[SUB_REAL].inthreeway;
07206    t1 = p1->subs[SUB_REAL].inthreeway;
07207 
07208    ast_mutex_unlock(&p0->lock);
07209    ast_mutex_unlock(&p1->lock);
07210 
07211    ast_channel_unlock(c0);
07212    ast_channel_unlock(c1);
07213 
07214    /* Native bridge failed */
07215    if ((!master || !slave) && !nothingok) {
07216       dahdi_enable_ec(p0);
07217       dahdi_enable_ec(p1);
07218       return AST_BRIDGE_FAILED;
07219    }
07220 
07221    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07222 
07223    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07224       disable_dtmf_detect(op0);
07225 
07226    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07227       disable_dtmf_detect(op1);
07228 
07229    for (;;) {
07230       struct ast_channel *c0_priority[2] = {c0, c1};
07231       struct ast_channel *c1_priority[2] = {c1, c0};
07232 
07233       /* Here's our main loop...  Start by locking things, looking for private parts,
07234          and then balking if anything is wrong */
07235 
07236       ast_channel_lock(c0);
07237       while (ast_channel_trylock(c1)) {
07238          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07239       }
07240 
07241       p0 = c0->tech_pvt;
07242       p1 = c1->tech_pvt;
07243 
07244       if (op0 == p0)
07245          i0 = dahdi_get_index(c0, p0, 1);
07246       if (op1 == p1)
07247          i1 = dahdi_get_index(c1, p1, 1);
07248 
07249       ast_channel_unlock(c0);
07250       ast_channel_unlock(c1);
07251 
07252       if (!timeoutms ||
07253          (op0 != p0) ||
07254          (op1 != p1) ||
07255          (ofd0 != c0->fds[0]) ||
07256          (ofd1 != c1->fds[0]) ||
07257          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07258          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07259          (oc0 != p0->owner) ||
07260          (oc1 != p1->owner) ||
07261          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07262          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07263          (oi0 != i0) ||
07264          (oi1 != i1)) {
07265          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07266             op0->channel, oi0, op1->channel, oi1);
07267          res = AST_BRIDGE_RETRY;
07268          goto return_from_bridge;
07269       }
07270 
07271 #ifdef PRI_2BCT
07272       if (!triedtopribridge) {
07273          triedtopribridge = 1;
07274          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07275             ast_mutex_lock(&p0->pri->lock);
07276             switch (p0->sig) {
07277             case SIG_PRI_LIB_HANDLE_CASES:
07278                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07279                break;
07280             default:
07281                q931c0 = NULL;
07282                break;
07283             }
07284             switch (p1->sig) {
07285             case SIG_PRI_LIB_HANDLE_CASES:
07286                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07287                break;
07288             default:
07289                q931c1 = NULL;
07290                break;
07291             }
07292             if (q931c0 && q931c1) {
07293                pri_channel_bridge(q931c0, q931c1);
07294             }
07295             ast_mutex_unlock(&p0->pri->lock);
07296          }
07297       }
07298 #endif
07299 
07300       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07301       if (!who) {
07302          ast_debug(1, "Ooh, empty read...\n");
07303          continue;
07304       }
07305       f = ast_read(who);
07306       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07307          *fo = f;
07308          *rc = who;
07309          res = AST_BRIDGE_COMPLETE;
07310          goto return_from_bridge;
07311       }
07312       if (f->frametype == AST_FRAME_DTMF) {
07313          if ((who == c0) && p0->pulsedial) {
07314             ast_write(c1, f);
07315          } else if ((who == c1) && p1->pulsedial) {
07316             ast_write(c0, f);
07317          } else {
07318             *fo = f;
07319             *rc = who;
07320             res = AST_BRIDGE_COMPLETE;
07321             goto return_from_bridge;
07322          }
07323       }
07324       ast_frfree(f);
07325 
07326       /* Swap who gets priority */
07327       priority = !priority;
07328    }
07329 
07330 return_from_bridge:
07331    if (op0 == p0)
07332       dahdi_enable_ec(p0);
07333 
07334    if (op1 == p1)
07335       dahdi_enable_ec(p1);
07336 
07337    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07338       enable_dtmf_detect(op0);
07339 
07340    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07341       enable_dtmf_detect(op1);
07342 
07343    dahdi_unlink(slave, master, 1);
07344 
07345    return res;
07346 }

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

Definition at line 5218 of file chan_dahdi.c.

References ast_channel::_state, analog_call(), analog_lib_handles(), ast_copy_string(), ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, ast_channel::caller, dahdi_pvt::callwaitrings, dahdi_pvt::channel, dahdi_r2_get_channel_category(), dahdi_sig_pri_lib_handles(), dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, errno, dahdi_pvt::hidecallerid, ast_party_caller::id, IS_DIGITAL, dahdi_pvt::law, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_progress, ast_channel::name, dahdi_subchannel::needbusy, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), dahdi_pvt::sig, SIG_MFCR2, sig_pri_call(), dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_call(), ast_party_number::str, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_party_number::valid, and dahdi_pvt::waitingfordt.

05219 {
05220    struct dahdi_pvt *p = ast->tech_pvt;
05221    int x, res, mysig;
05222    char dest[256]; /* must be same length as p->dialdest */
05223 
05224    ast_mutex_lock(&p->lock);
05225    ast_copy_string(dest, rdest, sizeof(dest));
05226    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05227    if ((ast->_state == AST_STATE_BUSY)) {
05228       p->subs[SUB_REAL].needbusy = 1;
05229       ast_mutex_unlock(&p->lock);
05230       return 0;
05231    }
05232    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05233       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05234       ast_mutex_unlock(&p->lock);
05235       return -1;
05236    }
05237    p->waitingfordt.tv_sec = 0;
05238    p->dialednone = 0;
05239    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05240    {
05241       /* Special pseudo -- automatically up */
05242       ast_setstate(ast, AST_STATE_UP);
05243       ast_mutex_unlock(&p->lock);
05244       return 0;
05245    }
05246    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05247    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05248    if (res)
05249       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05250    p->outgoing = 1;
05251 
05252    if (IS_DIGITAL(ast->transfercapability)){
05253       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05254    } else {
05255       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05256    }  
05257 
05258 #ifdef HAVE_PRI
05259    if (dahdi_sig_pri_lib_handles(p->sig)) {
05260       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05261          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05262       ast_mutex_unlock(&p->lock);
05263       return res;
05264    }
05265 #endif
05266 
05267 #if defined(HAVE_SS7)
05268    if (p->sig == SIG_SS7) {
05269       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05270       ast_mutex_unlock(&p->lock);
05271       return res;
05272    }
05273 #endif   /* defined(HAVE_SS7) */
05274 
05275    /* If this is analog signalling we can exit here */
05276    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05277       p->callwaitrings = 0;
05278       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05279       ast_mutex_unlock(&p->lock);
05280       return res;
05281    }
05282 
05283    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05284    switch (mysig) {
05285    case 0:
05286       /* Special pseudo -- automatically up*/
05287       ast_setstate(ast, AST_STATE_UP);
05288       break;
05289    case SIG_MFCR2:
05290       break;
05291    default:
05292       ast_debug(1, "not yet implemented\n");
05293       ast_mutex_unlock(&p->lock);
05294       return -1;
05295    }
05296 
05297 #ifdef HAVE_OPENR2
05298    if (p->mfcr2) {
05299       openr2_calling_party_category_t chancat;
05300       int callres = 0;
05301       char *c, *l;
05302 
05303       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05304       p->dialdest[0] = '\0';
05305 
05306       c = strchr(dest, '/');
05307       if (c) {
05308          c++;
05309       } else {
05310          c = "";
05311       }
05312       if (!p->hidecallerid) {
05313          l = ast->caller.id.number.valid ? ast->caller.id.number.str : NULL;
05314       } else {
05315          l = NULL;
05316       }
05317       if (strlen(c) < p->stripmsd) {
05318          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05319          ast_mutex_unlock(&p->lock);
05320          return -1;
05321       }
05322       p->dialing = 1;
05323       chancat = dahdi_r2_get_channel_category(ast);
05324       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05325       if (-1 == callres) {
05326          ast_mutex_unlock(&p->lock);
05327          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05328          return -1;
05329       }
05330       p->mfcr2_call_accepted = 0;
05331       p->mfcr2_progress = 0;
05332       ast_setstate(ast, AST_STATE_DIALING);
05333    }
05334 #endif /* HAVE_OPENR2 */
05335    ast_mutex_unlock(&p->lock);
05336    return 0;
05337 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 5185 of file chan_dahdi.c.

References ast_free, 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, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.

Referenced by dahdi_read().

05186 {
05187    struct dahdi_pvt *p = ast->tech_pvt;
05188    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05189    if (p->cidspill) {
05190       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05191       ast_free(p->cidspill);
05192    }
05193 
05194    /*
05195     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05196     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05197     */
05198    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05199       return -1;
05200    save_conference(p);
05201    /* Silence */
05202    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05203    if (!p->callwaitrings && p->callwaitingcallerid) {
05204       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05205       p->callwaitcas = 1;
05206       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05207    } else {
05208       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05209       p->callwaitcas = 0;
05210       p->cidlen = 2400 + READ_SIZE * 4;
05211    }
05212    p->cidpos = 0;
05213    send_callerid(p);
05214 
05215    return 0;
05216 }

static int dahdi_cc_callback ( struct ast_channel inbound,
const char *  dest,
ast_cc_callback_fn  callback 
) [static]

Callback made when dial failed to get a channel out of dahdi_request().

Since:
1.8
Parameters:
inbound Incoming asterisk channel.
dest Same dial string passed to dahdi_request().
callback Callback into CC core to announce a busy channel available for CC.
This callback acts like a forked dial with all prongs of the fork busy. Essentially, for each channel that could have taken the call, indicate that it is busy.

Return values:
0 on success.
-1 on error.

Definition at line 13475 of file chan_dahdi.c.

References AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, AST_CHANNEL_NAME, ast_free, ast_get_cc_monitor_policy(), ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), dahdi_pvt::cc_params, sig_pri_span::cc_params, dahdi_starting_point::channelmatch, create_channel_name(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_starting_point::groupmatch, iflock, is_group_or_channel_match(), dahdi_pvt::pri, and dahdi_starting_point::span.

13476 {
13477    struct dahdi_pvt *p;
13478    struct dahdi_pvt *exitpvt;
13479    struct dahdi_starting_point start;
13480    int groupmatched = 0;
13481    int channelmatched = 0;
13482 
13483    ast_mutex_lock(&iflock);
13484    p = determine_starting_point(dest, &start);
13485    if (!p) {
13486       ast_mutex_unlock(&iflock);
13487       return -1;
13488    }
13489    exitpvt = p;
13490    for (;;) {
13491       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13492          /* We found a potential match. call the callback */
13493          struct ast_str *device_name;
13494          char *dash;
13495          const char *monitor_type;
13496          char dialstring[AST_CHANNEL_NAME];
13497          char full_device_name[AST_CHANNEL_NAME];
13498 
13499          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13500          case AST_CC_MONITOR_NEVER:
13501             break;
13502          case AST_CC_MONITOR_NATIVE:
13503          case AST_CC_MONITOR_ALWAYS:
13504          case AST_CC_MONITOR_GENERIC:
13505 #if defined(HAVE_PRI)
13506             if (dahdi_sig_pri_lib_handles(p->sig)) {
13507                /*
13508                 * ISDN is in a trunk busy condition so we need to monitor
13509                 * the span congestion device state.
13510                 */
13511                snprintf(full_device_name, sizeof(full_device_name),
13512                   "DAHDI/I%d/congestion", p->pri->span);
13513             } else
13514 #endif   /* defined(HAVE_PRI) */
13515             {
13516 #if defined(HAVE_PRI)
13517                device_name = create_channel_name(p, 1, "");
13518 #else
13519                device_name = create_channel_name(p);
13520 #endif   /* defined(HAVE_PRI) */
13521                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13522                   device_name ? ast_str_buffer(device_name) : "");
13523                ast_free(device_name);
13524                /*
13525                 * The portion after the '-' in the channel name is either a random
13526                 * number, a sequence number, or a subchannel number. None are
13527                 * necessary so strip them off.
13528                 */
13529                dash = strrchr(full_device_name, '-');
13530                if (dash) {
13531                   *dash = '\0';
13532                }
13533             }
13534             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13535 
13536             /*
13537              * Analog can only do generic monitoring.
13538              * ISDN is in a trunk busy condition and any "device" is going
13539              * to be busy until a B channel becomes available.  The generic
13540              * monitor can do this task.
13541              */
13542             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13543             callback(inbound,
13544 #if defined(HAVE_PRI)
13545                p->pri ? p->pri->cc_params : p->cc_params,
13546 #else
13547                p->cc_params,
13548 #endif   /* defined(HAVE_PRI) */
13549                monitor_type, full_device_name, dialstring, NULL);
13550             break;
13551          }
13552       }
13553       p = start.backwards ? p->prev : p->next;
13554       if (!p) {
13555          p = start.backwards ? ifend : iflist;
13556       }
13557       if (p == exitpvt) {
13558          break;
13559       }
13560    }
13561    ast_mutex_unlock(&iflock);
13562    return 0;
13563 }

static struct dahdi_chan_conf dahdi_chan_conf_default ( void   )  [static]

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

Definition at line 1343 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

01344 {
01345    /* recall that if a field is not included here it is initialized
01346     * to 0 or equivalent
01347     */
01348    struct dahdi_chan_conf conf = {
01349 #ifdef HAVE_PRI
01350       .pri.pri = {
01351          .nsf = PRI_NSF_NONE,
01352          .switchtype = PRI_SWITCH_NI2,
01353          .dialplan = PRI_UNKNOWN + 1,
01354          .localdialplan = PRI_NATIONAL_ISDN + 1,
01355          .nodetype = PRI_CPE,
01356          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01357 
01358 #if defined(HAVE_PRI_CCSS)
01359          .cc_ptmp_recall_mode = 1,/* specificRecall */
01360          .cc_qsig_signaling_link_req = 1,/* retain */
01361          .cc_qsig_signaling_link_rsp = 1,/* retain */
01362 #endif   /* defined(HAVE_PRI_CCSS) */
01363 
01364          .minunused = 2,
01365          .idleext = "",
01366          .idledial = "",
01367          .internationalprefix = "",
01368          .nationalprefix = "",
01369          .localprefix = "",
01370          .privateprefix = "",
01371          .unknownprefix = "",
01372          .resetinterval = -1,
01373       },
01374 #endif
01375 #if defined(HAVE_SS7)
01376       .ss7.ss7 = {
01377          .called_nai = SS7_NAI_NATIONAL,
01378          .calling_nai = SS7_NAI_NATIONAL,
01379          .internationalprefix = "",
01380          .nationalprefix = "",
01381          .subscriberprefix = "",
01382          .unknownprefix = ""
01383       },
01384 #endif   /* defined(HAVE_SS7) */
01385 #ifdef HAVE_OPENR2
01386       .mfcr2 = {
01387          .variant = OR2_VAR_ITU,
01388          .mfback_timeout = -1,
01389          .metering_pulse_timeout = -1,
01390          .max_ani = 10,
01391          .max_dnis = 4,
01392          .get_ani_first = -1,
01393 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01394          .skip_category_request = -1,
01395 #endif
01396          .call_files = 0,
01397          .allow_collect_calls = 0,
01398          .charge_calls = 1,
01399          .accept_on_offer = 1,
01400          .forced_release = 0,
01401          .double_answer = 0,
01402          .immediate_accept = -1,
01403          .logdir = "",
01404          .r2proto_file = "",
01405          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01406          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01407       },
01408 #endif
01409       .chan = {
01410          .context = "default",
01411          .cid_num = "",
01412          .cid_name = "",
01413          .cid_tag = "",
01414          .mohinterpret = "default",
01415          .mohsuggest = "",
01416          .parkinglot = "",
01417          .transfertobusy = 1,
01418 
01419          .cid_signalling = CID_SIG_BELL,
01420          .cid_start = CID_START_RING,
01421          .dahditrcallerid = 0,
01422          .use_callerid = 1,
01423          .sig = -1,
01424          .outsigmod = -1,
01425 
01426          .cid_rxgain = +5.0,
01427 
01428          .tonezone = -1,
01429 
01430          .echocancel.head.tap_length = 1,
01431 
01432          .busycount = 3,
01433          .busycompare = 0,
01434          .busytonelength = 0,
01435          .busyquietlength = 0,
01436          .busyfuzziness = 0,
01437          .silencethreshold = 0,
01438 
01439          .accountcode = "",
01440 
01441          .mailbox = "",
01442 
01443 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01444          .mwisend_fsk = 1,
01445 #endif
01446          .polarityonanswerdelay = 600,
01447 
01448          .sendcalleridafter = DEFAULT_CIDRINGS,
01449 
01450          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01451          .buf_no = numbufs,
01452          .usefaxbuffers = 0,
01453          .cc_params = ast_cc_config_params_init(),
01454       },
01455       .timing = {
01456          .prewinktime = -1,
01457          .preflashtime = -1,
01458          .winktime = -1,
01459          .flashtime = -1,
01460          .starttime = -1,
01461          .rxwinktime = -1,
01462          .rxflashtime = -1,
01463          .debouncetime = -1
01464       },
01465       .is_sig_auto = 1,
01466       .smdi_port = "/dev/ttyS0",
01467    };
01468 
01469    return conf;
01470 }

static int dahdi_channels_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 17891 of file chan_dahdi.c.

References ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), ast_mutex_lock, ast_mutex_unlock, iflist, and dahdi_pvt::next.

17893 {
17894    struct dahdi_pvt *tmp;
17895    struct ast_data *data_channel;
17896 
17897    ast_mutex_lock(&iflock);
17898    for (tmp = iflist; tmp; tmp = tmp->next) {
17899       data_channel = ast_data_add_node(data_root, "channel");
17900       if (!data_channel) {
17901          continue;
17902       }
17903 
17904       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
17905 
17906       /* if this channel doesn't match remove it. */
17907       if (!ast_data_search_match(search, data_channel)) {
17908          ast_data_remove_node(data_root, data_channel);
17909       }
17910    }
17911    ast_mutex_unlock(&iflock);
17912 
17913    return 0;
17914 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4212 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), dahdi_close_ss7_fd(), and dahdi_close_sub().

04213 {
04214    if (fd > 0)
04215       close(fd);
04216 }

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

Definition at line 4225 of file chan_dahdi.c.

References dahdi_close(), sig_pri_span::fds, and dahdi_pri::pri.

Referenced by __unload_module(), and prepare_pri().

04226 {
04227    dahdi_close(pri->pri.fds[fd_num]);
04228    pri->pri.fds[fd_num] = -1;
04229 }

static void dahdi_close_ss7_fd ( struct dahdi_ss7 ss7,
int  fd_num 
) [static]

Definition at line 4233 of file chan_dahdi.c.

References dahdi_close(), sig_ss7_linkset::fds, and dahdi_ss7::ss7.

Referenced by __unload_module(), and linkset_addsigchan().

04234 {
04235    dahdi_close(ss7->ss7.fds[fd_num]);
04236    ss7->ss7.fds[fd_num] = -1;
04237 }

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

Definition at line 4218 of file chan_dahdi.c.

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

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

04219 {
04220    dahdi_close(chan_pvt->subs[sub_num].dfd);
04221    chan_pvt->subs[sub_num].dfd = -1;
04222 }

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

Definition at line 5028 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_dtmf(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_read(), my_confmute(), and my_handle_dtmf().

05029 {
05030    int x, res;
05031 
05032    x = muted;
05033 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05034    switch (p->sig) {
05035 #if defined(HAVE_PRI)
05036    case SIG_PRI_LIB_HANDLE_CASES:
05037       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05038          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05039          break;
05040       }
05041       /* Fall through */
05042 #endif   /* defined(HAVE_PRI) */
05043 #if defined(HAVE_SS7)
05044    case SIG_SS7:
05045 #endif   /* defined(HAVE_SS7) */
05046       {
05047          int y = 1;
05048 
05049          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05050          if (res)
05051             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05052                p->channel, strerror(errno));
05053       }
05054       break;
05055    default:
05056       break;
05057    }
05058 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05059    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05060    if (res < 0)
05061       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05062    return res;
05063 }

static char* dahdi_destroy_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14575 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_bynum(), RESULT_SUCCESS, and ast_cli_entry::usage.

14576 {
14577    int channel;
14578    int ret;
14579    switch (cmd) {
14580    case CLI_INIT:
14581       e->command = "dahdi destroy channel";
14582       e->usage =
14583          "Usage: dahdi destroy channel <chan num>\n"
14584          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14585       return NULL;
14586    case CLI_GENERATE:
14587       return NULL;
14588    }
14589    if (a->argc != 4)
14590       return CLI_SHOWUSAGE;
14591 
14592    channel = atoi(a->argv[3]);
14593    ret = dahdi_destroy_channel_bynum(channel);
14594    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14595 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 11044 of file chan_dahdi.c.

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

Referenced by dahdi_destroy_channel().

11045 {
11046    struct dahdi_pvt *cur;
11047 
11048    ast_mutex_lock(&iflock);
11049    for (cur = iflist; cur; cur = cur->next) {
11050       if (cur->channel == channel) {
11051          int x = DAHDI_FLASH;
11052 
11053          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11054          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11055 
11056          destroy_channel(cur, 1);
11057          ast_mutex_unlock(&iflock);
11058          ast_module_unref(ast_module_info->self);
11059          return RESULT_SUCCESS;
11060       }
11061    }
11062    ast_mutex_unlock(&iflock);
11063    return RESULT_FAILURE;
11064 }

static int dahdi_devicestate ( void *  data  )  [static]

Definition at line 13413 of file chan_dahdi.c.

References AST_DEVICE_UNKNOWN, sig_pri_span::congestion_devstate, dahdi_pri::pri, and pris.

13414 {
13415 #if defined(HAVE_PRI)
13416    char *device;
13417    unsigned span;
13418    int res;
13419 
13420    device = data;
13421 
13422    if (*device != 'I') {
13423       /* The request is not for an ISDN span device. */
13424       return AST_DEVICE_UNKNOWN;
13425    }
13426    res = sscanf(device, "I%30u", &span);
13427    if (res != 1 || !span || NUM_SPANS < span) {
13428       /* Bad format for ISDN span device name. */
13429       return AST_DEVICE_UNKNOWN;
13430    }
13431    device = strchr(device, '/');
13432    if (!device) {
13433       /* Bad format for ISDN span device name. */
13434       return AST_DEVICE_UNKNOWN;
13435    }
13436 
13437    /*
13438     * Since there are currently no other span devstate's defined,
13439     * it must be congestion.
13440     */
13441 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13442    ++device;
13443    if (!strcmp(device, "congestion"))
13444 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13445    {
13446       return pris[span - 1].pri.congestion_devstate;
13447    }
13448 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13449    else if (!strcmp(device, "threshold")) {
13450       return pris[span - 1].pri.threshold_devstate;
13451    }
13452    return AST_DEVICE_UNKNOWN;
13453 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13454 #else
13455    return AST_DEVICE_UNKNOWN;
13456 #endif   /* defined(HAVE_PRI) */
13457 }

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

Definition at line 4316 of file chan_dahdi.c.

References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_get_index, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, sig_pri_digit_begin(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

04317 {
04318    struct dahdi_pvt *pvt;
04319    int idx;
04320    int dtmf = -1;
04321    int res;
04322 
04323    pvt = chan->tech_pvt;
04324 
04325    ast_mutex_lock(&pvt->lock);
04326 
04327    idx = dahdi_get_index(chan, pvt, 0);
04328 
04329    if ((idx != SUB_REAL) || !pvt->owner)
04330       goto out;
04331 
04332 #ifdef HAVE_PRI
04333    switch (pvt->sig) {
04334    case SIG_PRI_LIB_HANDLE_CASES:
04335       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04336       if (!res)
04337          goto out;
04338       break;
04339    default:
04340       break;
04341    }
04342 #endif
04343    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04344       goto out;
04345 
04346    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04347       struct dahdi_dialoperation zo = {
04348          .op = DAHDI_DIAL_OP_APPEND,
04349       };
04350 
04351       zo.dialstr[0] = 'T';
04352       zo.dialstr[1] = digit;
04353       zo.dialstr[2] = '\0';
04354       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04355          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04356       else
04357          pvt->dialing = 1;
04358    } else {
04359       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04360       pvt->dialing = 1;
04361       pvt->begindigit = digit;
04362    }
04363 
04364 out:
04365    ast_mutex_unlock(&pvt->lock);
04366 
04367    return 0;
04368 }

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

Definition at line 4370 of file chan_dahdi.c.

References ast_debug, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_get_index, dahdi_sig_pri_lib_handles(), dahdi_pvt::dialing, dahdi_pvt::lock, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

04371 {
04372    struct dahdi_pvt *pvt;
04373    int res = 0;
04374    int idx;
04375    int x;
04376 
04377    pvt = chan->tech_pvt;
04378 
04379    ast_mutex_lock(&pvt->lock);
04380 
04381    idx = dahdi_get_index(chan, pvt, 0);
04382 
04383    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04384       goto out;
04385 
04386 #ifdef HAVE_PRI
04387    /* This means that the digit was already sent via PRI signalling */
04388    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04389       goto out;
04390    }
04391 #endif
04392 
04393    if (pvt->begindigit) {
04394       x = -1;
04395       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04396       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04397       pvt->dialing = 0;
04398       pvt->begindigit = 0;
04399    }
04400 
04401 out:
04402    ast_mutex_unlock(&pvt->lock);
04403 
04404    return res;
04405 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4820 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::echocanon, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

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

04821 {
04822    int res;
04823 
04824    if (p->echocanon) {
04825       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04826 
04827       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04828 
04829       if (res)
04830          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04831       else
04832          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04833    }
04834 
04835    p->echocanon = 0;
04836 }

static int dahdi_dnd ( struct dahdi_pvt dahdichan,
int  flag 
) [static]

enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel

Parameters:
dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
flag on 1 to enable, 0 to disable, -1 return dnd value
chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical DAHDI channel). Use this to enable or disable it.

Bug:
the use of the word "channel" for those dahdichans is really confusing.

Definition at line 9542 of file chan_dahdi.c.

References analog_dnd(), analog_lib_handles(), ast_verb, dahdi_pvt::channel, dahdi_pvt::dnd, EVENT_FLAG_SYSTEM, manager_event, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.

Referenced by action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), analog_ss_thread(), dahdi_set_dnd(), and dahdi_show_channel().

09543 {
09544    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09545       return analog_dnd(dahdichan->sig_pvt, flag);
09546    }
09547 
09548    if (flag == -1) {
09549       return dahdichan->dnd;
09550    }
09551 
09552    /* Do not disturb */
09553    dahdichan->dnd = flag;
09554    ast_verb(3, "%s DND on channel %d\n",
09555          flag? "Enabled" : "Disabled",
09556          dahdichan->channel);
09557    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09558          "Channel: DAHDI/%d\r\n"
09559          "Status: %s\r\n", dahdichan->channel,
09560          flag? "enabled" : "disabled");
09561 
09562    return 0;
09563 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4748 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::head, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_bridge(), dahdi_func_write(), dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_setoption(), handle_init_event(), and my_set_echocanceller().

04749 {
04750    int res;
04751    if (!p)
04752       return;
04753    if (p->echocanon) {
04754       ast_debug(1, "Echo cancellation already on\n");
04755       return;
04756    }
04757    if (p->digital) {
04758       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04759       return;
04760    }
04761    if (p->echocancel.head.tap_length) {
04762 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04763       switch (p->sig) {
04764 #if defined(HAVE_PRI)
04765       case SIG_PRI_LIB_HANDLE_CASES:
04766          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04767             /*
04768              * PRI nobch pseudo channel.  Does not need ec anyway.
04769              * Does not handle ioctl(DAHDI_AUDIOMODE)
04770              */
04771             return;
04772          }
04773          /* Fall through */
04774 #endif   /* defined(HAVE_PRI) */
04775 #if defined(HAVE_SS7)
04776       case SIG_SS7:
04777 #endif   /* defined(HAVE_SS7) */
04778          {
04779             int x = 1;
04780 
04781             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04782             if (res)
04783                ast_log(LOG_WARNING,
04784                   "Unable to enable audio mode on channel %d (%s)\n",
04785                   p->channel, strerror(errno));
04786          }
04787          break;
04788       default:
04789          break;
04790       }
04791 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04792       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04793       if (res) {
04794          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04795       } else {
04796          p->echocanon = 1;
04797          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04798       }
04799    } else
04800       ast_debug(1, "No echo cancellation requested\n");
04801 }

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

Definition at line 8625 of file chan_dahdi.c.

References __dahdi_exception(), analog_exception(), analog_lib_handles(), ast_mutex_lock, ast_mutex_unlock, f, dahdi_pvt::lock, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.

08626 {
08627    struct dahdi_pvt *p = ast->tech_pvt;
08628    struct ast_frame *f;
08629    ast_mutex_lock(&p->lock);
08630    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08631       struct analog_pvt *analog_p = p->sig_pvt;
08632       f = analog_exception(analog_p, ast);
08633    } else {
08634       f = __dahdi_exception(ast);
08635    }
08636    ast_mutex_unlock(&p->lock);
08637    return f;
08638 }

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

Definition at line 15422 of file chan_dahdi.c.

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

Referenced by action_transfer(), and action_transferhangup().

15423 {
15424    if (p) {
15425       switch (mode) {
15426       case TRANSFER:
15427          p->fake_event = DAHDI_EVENT_WINKFLASH;
15428          break;
15429       case HANGUP:
15430          p->fake_event = DAHDI_EVENT_ONHOOK;
15431          break;
15432       default:
15433          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15434       }
15435    }
15436    return 0;
15437 }

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

Definition at line 7348 of file chan_dahdi.c.

References ast_debug, ast_mutex_lock, dahdi_pvt::channel, dahdi_unlink(), dahdi_pvt::lock, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, and ast_channel::tech_pvt.

07349 {
07350    struct dahdi_pvt *p = newchan->tech_pvt;
07351    int x;
07352 
07353    ast_mutex_lock(&p->lock);
07354 
07355    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07356    if (p->owner == oldchan) {
07357       p->owner = newchan;
07358    }
07359    for (x = 0; x < 3; x++) {
07360       if (p->subs[x].owner == oldchan) {
07361          if (!x) {
07362             dahdi_unlink(NULL, p, 0);
07363          }
07364          p->subs[x].owner = newchan;
07365       }
07366    }
07367    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07368       analog_fixup(oldchan, newchan, p->sig_pvt);
07369 #if defined(HAVE_PRI)
07370    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07371       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07372 #endif   /* defined(HAVE_PRI) */
07373 #if defined(HAVE_SS7)
07374    } else if (p->sig == SIG_SS7) {
07375       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07376 #endif   /* defined(HAVE_SS7) */
07377    }
07378    update_conf(p);
07379 
07380    ast_mutex_unlock(&p->lock);
07381 
07382    if (newchan->_state == AST_STATE_RINGING) {
07383       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07384    }
07385    return 0;
07386 }

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

Definition at line 6751 of file chan_dahdi.c.

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

06752 {
06753    struct dahdi_pvt *p = chan->tech_pvt;
06754    int res = 0;
06755 
06756    if (!strcasecmp(data, "rxgain")) {
06757       ast_mutex_lock(&p->lock);
06758       snprintf(buf, len, "%f", p->rxgain);
06759       ast_mutex_unlock(&p->lock);
06760    } else if (!strcasecmp(data, "txgain")) {
06761       ast_mutex_lock(&p->lock);
06762       snprintf(buf, len, "%f", p->txgain);
06763       ast_mutex_unlock(&p->lock);
06764 #if defined(HAVE_PRI)
06765 #if defined(HAVE_PRI_REVERSE_CHARGE)
06766    } else if (!strcasecmp(data, "reversecharge")) {
06767       ast_mutex_lock(&p->lock);
06768       switch (p->sig) {
06769       case SIG_PRI_LIB_HANDLE_CASES:
06770          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06771          break;
06772       default:
06773          *buf = '\0';
06774          res = -1;
06775          break;
06776       }
06777       ast_mutex_unlock(&p->lock);
06778 #endif
06779 #if defined(HAVE_PRI_SETUP_KEYPAD)
06780    } else if (!strcasecmp(data, "keypad_digits")) {
06781       ast_mutex_lock(&p->lock);
06782       switch (p->sig) {
06783       case SIG_PRI_LIB_HANDLE_CASES:
06784          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06785             len);
06786          break;
06787       default:
06788          *buf = '\0';
06789          res = -1;
06790          break;
06791       }
06792       ast_mutex_unlock(&p->lock);
06793 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06794    } else if (!strcasecmp(data, "no_media_path")) {
06795       ast_mutex_lock(&p->lock);
06796       switch (p->sig) {
06797       case SIG_PRI_LIB_HANDLE_CASES:
06798          /*
06799           * TRUE if the call is on hold or is call waiting because
06800           * there is no media path available.
06801           */
06802          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06803          break;
06804       default:
06805          *buf = '\0';
06806          res = -1;
06807          break;
06808       }
06809       ast_mutex_unlock(&p->lock);
06810 #endif   /* defined(HAVE_PRI) */
06811    } else {
06812       *buf = '\0';
06813       res = -1;
06814    }
06815 
06816    return res;
06817 }

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

Definition at line 6849 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_pvt::echocanon, errno, dahdi_pvt::lock, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

06850 {
06851    struct dahdi_pvt *p = chan->tech_pvt;
06852    int res = 0;
06853 
06854    if (!strcasecmp(data, "buffers")) {
06855       int num_bufs, policy;
06856 
06857       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06858          struct dahdi_bufferinfo bi = {
06859             .txbufpolicy = policy,
06860             .rxbufpolicy = policy,
06861             .bufsize = p->bufsize,
06862             .numbufs = num_bufs,
06863          };
06864          int bpres;
06865 
06866          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06867             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06868          } else {
06869             p->bufferoverrideinuse = 1;
06870          }
06871       } else {
06872          res = -1;
06873       }
06874    } else if (!strcasecmp(data, "echocan_mode")) {
06875       if (!strcasecmp(value, "on")) {
06876          ast_mutex_lock(&p->lock);
06877          dahdi_enable_ec(p);
06878          ast_mutex_unlock(&p->lock);
06879       } else if (!strcasecmp(value, "off")) {
06880          ast_mutex_lock(&p->lock);
06881          dahdi_disable_ec(p);
06882          ast_mutex_unlock(&p->lock);
06883 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
06884       } else if (!strcasecmp(value, "fax")) {
06885          int blah = 1;
06886 
06887          ast_mutex_lock(&p->lock);
06888          if (!p->echocanon) {
06889             dahdi_enable_ec(p);
06890          }
06891          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06892             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
06893          }
06894          ast_mutex_unlock(&p->lock);
06895       } else if (!strcasecmp(value, "voice")) {
06896          int blah = 0;
06897 
06898          ast_mutex_lock(&p->lock);
06899          if (!p->echocanon) {
06900             dahdi_enable_ec(p);
06901          }
06902          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06903             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
06904          }
06905          ast_mutex_unlock(&p->lock);
06906 #endif
06907       } else {
06908          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
06909          res = -1;
06910       }
06911    } else {
06912       res = -1;
06913    }
06914 
06915    return res;
06916 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 469 of file chan_dahdi.c.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), mwi_thread(), my_distinctive_ring(), my_get_callerid(), and my_get_event().

00470 {
00471    int j;
00472    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00473       return -1;
00474    return j;
00475 }

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

Definition at line 7525 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, ast_channel::caller, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, ast_channel::macrocontext, ast_channel::name, ast_party_id::number, pbx_builtin_setvar_helper(), S_COR, S_OR, send_cwcidspill(), ast_party_number::str, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::usefaxbuffers, and ast_party_number::valid.

Referenced by dahdi_handle_event(), and dahdi_read().

07526 {
07527    struct dahdi_pvt *p = ast->tech_pvt;
07528    struct ast_frame *f = *dest;
07529 
07530    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07531       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07532       f->subclass.integer, f->subclass.integer, ast->name);
07533 
07534    if (p->confirmanswer) {
07535       if (f->frametype == AST_FRAME_DTMF_END) {
07536          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07537          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07538             of a DTMF digit */
07539          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07540          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07541          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07542          p->confirmanswer = 0;
07543       } else {
07544          p->subs[idx].f.frametype = AST_FRAME_NULL;
07545          p->subs[idx].f.subclass.integer = 0;
07546       }
07547       *dest = &p->subs[idx].f;
07548    } else if (p->callwaitcas) {
07549       if (f->frametype == AST_FRAME_DTMF_END) {
07550          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07551             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07552             ast_free(p->cidspill);
07553             p->cidspill = NULL;
07554             send_cwcidspill(p);
07555          }
07556          p->callwaitcas = 0;
07557       }
07558       p->subs[idx].f.frametype = AST_FRAME_NULL;
07559       p->subs[idx].f.subclass.integer = 0;
07560       *dest = &p->subs[idx].f;
07561    } else if (f->subclass.integer == 'f') {
07562       if (f->frametype == AST_FRAME_DTMF_END) {
07563          /* Fax tone -- Handle and return NULL */
07564          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07565             /* If faxbuffers are configured, use them for the fax transmission */
07566             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07567                struct dahdi_bufferinfo bi = {
07568                   .txbufpolicy = p->faxbuf_policy,
07569                   .bufsize = p->bufsize,
07570                   .numbufs = p->faxbuf_no
07571                };
07572                int res;
07573 
07574                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07575                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07576                } else {
07577                   p->bufferoverrideinuse = 1;
07578                }
07579             }
07580             p->faxhandled = 1;
07581             if (p->dsp) {
07582                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07583                ast_dsp_set_features(p->dsp, p->dsp_features);
07584                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07585             }
07586             if (strcmp(ast->exten, "fax")) {
07587                const char *target_context = S_OR(ast->macrocontext, ast->context);
07588 
07589                /* We need to unlock 'ast' here because ast_exists_extension has the
07590                 * potential to start autoservice on the channel. Such action is prone
07591                 * to deadlock.
07592                 */
07593                ast_mutex_unlock(&p->lock);
07594                ast_channel_unlock(ast);
07595                if (ast_exists_extension(ast, target_context, "fax", 1,
07596                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07597                   ast_channel_lock(ast);
07598                   ast_mutex_lock(&p->lock);
07599                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07600                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07601                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07602                   if (ast_async_goto(ast, target_context, "fax", 1))
07603                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07604                } else {
07605                   ast_channel_lock(ast);
07606                   ast_mutex_lock(&p->lock);
07607                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07608                }
07609             } else {
07610                ast_debug(1, "Already in a fax extension, not redirecting\n");
07611             }
07612          } else {
07613             ast_debug(1, "Fax already handled\n");
07614          }
07615          dahdi_confmute(p, 0);
07616       }
07617       p->subs[idx].f.frametype = AST_FRAME_NULL;
07618       p->subs[idx].f.subclass.integer = 0;
07619       *dest = &p->subs[idx].f;
07620    }
07621 }

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

Definition at line 7644 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), analog_ss_thread(), ast_party_caller::ani, ast_party_caller::ani2, dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), 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_verb, attempt_transfer(), ast_channel::caller, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), dahdi_pvt::cid_name, cid_name, dahdi_pvt::cid_num, cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_handle_dtmf(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_sig_pri_lib_handles(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), ast_party_caller::id, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_party_id::name, ast_channel::name, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_party_id::number, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, sig_pri_span::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, sig_pri_span::pri, dahdi_pvt::pri, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, 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_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), ast_frame::src, ast_party_name::str, ast_party_number::str, 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(), update_conf(), ast_party_name::valid, ast_party_number::valid, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

07645 {
07646    int res, x;
07647    int idx, mysig;
07648    char *c;
07649    struct dahdi_pvt *p = ast->tech_pvt;
07650    pthread_t threadid;
07651    struct ast_channel *chan;
07652    struct ast_frame *f;
07653 
07654    idx = dahdi_get_index(ast, p, 0);
07655    mysig = p->sig;
07656    if (p->outsigmod > -1)
07657       mysig = p->outsigmod;
07658    p->subs[idx].f.frametype = AST_FRAME_NULL;
07659    p->subs[idx].f.subclass.integer = 0;
07660    p->subs[idx].f.datalen = 0;
07661    p->subs[idx].f.samples = 0;
07662    p->subs[idx].f.mallocd = 0;
07663    p->subs[idx].f.offset = 0;
07664    p->subs[idx].f.src = "dahdi_handle_event";
07665    p->subs[idx].f.data.ptr = NULL;
07666    f = &p->subs[idx].f;
07667 
07668    if (idx < 0)
07669       return &p->subs[idx].f;
07670    if (p->fake_event) {
07671       res = p->fake_event;
07672       p->fake_event = 0;
07673    } else
07674       res = dahdi_get_event(p->subs[idx].dfd);
07675 
07676    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07677 
07678    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07679       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07680       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07681 #if defined(HAVE_PRI)
07682       if (dahdi_sig_pri_lib_handles(p->sig)
07683          && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
07684          && p->pri
07685          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07686          /* absorb event */
07687       } else
07688 #endif   /* defined(HAVE_PRI) */
07689       {
07690          /* Unmute conference */
07691          dahdi_confmute(p, 0);
07692          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07693          p->subs[idx].f.subclass.integer = res & 0xff;
07694          dahdi_handle_dtmf(ast, idx, &f);
07695       }
07696       return f;
07697    }
07698 
07699    if (res & DAHDI_EVENT_DTMFDOWN) {
07700       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07701 #if defined(HAVE_PRI)
07702       if (dahdi_sig_pri_lib_handles(p->sig)
07703          && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
07704          && p->pri
07705          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07706          /* absorb event */
07707       } else
07708 #endif   /* defined(HAVE_PRI) */
07709       {
07710          /* Mute conference */
07711          dahdi_confmute(p, 1);
07712          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07713          p->subs[idx].f.subclass.integer = res & 0xff;
07714          dahdi_handle_dtmf(ast, idx, &f);
07715       }
07716       return &p->subs[idx].f;
07717    }
07718 
07719    switch (res) {
07720    case DAHDI_EVENT_EC_DISABLED:
07721       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07722       p->echocanon = 0;
07723       break;
07724 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07725    case DAHDI_EVENT_TX_CED_DETECTED:
07726       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07727       break;
07728    case DAHDI_EVENT_RX_CED_DETECTED:
07729       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07730       break;
07731    case DAHDI_EVENT_EC_NLP_DISABLED:
07732       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07733       break;
07734    case DAHDI_EVENT_EC_NLP_ENABLED:
07735       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07736       break;
07737 #endif
07738    case DAHDI_EVENT_BITSCHANGED:
07739 #ifdef HAVE_OPENR2
07740       if (p->sig != SIG_MFCR2) {
07741          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07742       } else {
07743          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07744          openr2_chan_handle_cas(p->r2chan);
07745       }
07746 #else
07747       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07748 #endif
07749    case DAHDI_EVENT_PULSE_START:
07750       /* Stop tone if there's a pulse start and the PBX isn't started */
07751       if (!ast->pbx)
07752          tone_zone_play_tone(p->subs[idx].dfd, -1);
07753       break;
07754    case DAHDI_EVENT_DIALCOMPLETE:
07755 #ifdef HAVE_OPENR2
07756       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07757          /* we don't need to do anything for this event for R2 signaling
07758             if the call is being setup */
07759          break;
07760       }
07761 #endif
07762       if (p->inalarm) break;
07763       if ((p->radio || (p->oprmode < 0))) break;
07764       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07765          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07766          return NULL;
07767       }
07768       if (!x) { /* if not still dialing in driver */
07769          dahdi_enable_ec(p);
07770          if (p->echobreak) {
07771             dahdi_train_ec(p);
07772             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07773             p->dop.op = DAHDI_DIAL_OP_REPLACE;
07774             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07775             p->echobreak = 0;
07776          } else {
07777             p->dialing = 0;
07778             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07779                /* if thru with dialing after offhook */
07780                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07781                   ast_setstate(ast, AST_STATE_UP);
07782                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07783                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07784                   break;
07785                } else { /* if to state wait for offhook to dial rest */
07786                   /* we now wait for off hook */
07787                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07788                }
07789             }
07790             if (ast->_state == AST_STATE_DIALING) {
07791                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07792                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07793                } else if (p->confirmanswer || (!p->dialednone
07794                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07795                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07796                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07797                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07798                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07799                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07800                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07801                      || (mysig == SIG_SF_FEATB)))) {
07802                   ast_setstate(ast, AST_STATE_RINGING);
07803                } else if (!p->answeronpolarityswitch) {
07804                   ast_setstate(ast, AST_STATE_UP);
07805                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07806                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07807                   /* If aops=0 and hops=1, this is necessary */
07808                   p->polarity = POLARITY_REV;
07809                } else {
07810                   /* Start clean, so we can catch the change to REV polarity when party answers */
07811                   p->polarity = POLARITY_IDLE;
07812                }
07813             }
07814          }
07815       }
07816       break;
07817    case DAHDI_EVENT_ALARM:
07818       switch (p->sig) {
07819 #if defined(HAVE_PRI)
07820       case SIG_PRI_LIB_HANDLE_CASES:
07821          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07822          break;
07823 #endif   /* defined(HAVE_PRI) */
07824 #if defined(HAVE_SS7)
07825       case SIG_SS7:
07826          sig_ss7_set_alarm(p->sig_pvt, 1);
07827          break;
07828 #endif   /* defined(HAVE_SS7) */
07829       default:
07830          p->inalarm = 1;
07831          break;
07832       }
07833       res = get_alarms(p);
07834       handle_alarms(p, res);
07835 #ifdef HAVE_PRI
07836       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07837          /* fall through intentionally */
07838       } else {
07839          break;
07840       }
07841 #endif
07842 #if defined(HAVE_SS7)
07843       if (p->sig == SIG_SS7)
07844          break;
07845 #endif   /* defined(HAVE_SS7) */
07846 #ifdef HAVE_OPENR2
07847       if (p->sig == SIG_MFCR2)
07848          break;
07849 #endif
07850    case DAHDI_EVENT_ONHOOK:
07851       if (p->radio) {
07852          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07853          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07854          break;
07855       }
07856       if (p->oprmode < 0)
07857       {
07858          if (p->oprmode != -1) break;
07859          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07860          {
07861             /* Make sure it starts ringing */
07862             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07863             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07864             save_conference(p->oprpeer);
07865             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07866          }
07867          break;
07868       }
07869       switch (p->sig) {
07870       case SIG_FXOLS:
07871       case SIG_FXOGS:
07872       case SIG_FXOKS:
07873          /* Check for some special conditions regarding call waiting */
07874          if (idx == SUB_REAL) {
07875             /* The normal line was hung up */
07876             if (p->subs[SUB_CALLWAIT].owner) {
07877                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
07878                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07879                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07880                unalloc_sub(p, SUB_CALLWAIT);
07881 #if 0
07882                p->subs[idx].needanswer = 0;
07883                p->subs[idx].needringing = 0;
07884 #endif
07885                p->callwaitingrepeat = 0;
07886                p->cidcwexpire = 0;
07887                p->cid_suppress_expire = 0;
07888                p->owner = NULL;
07889                /* Don't start streaming audio yet if the incoming call isn't up yet */
07890                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
07891                   p->dialing = 1;
07892                dahdi_ring_phone(p);
07893             } else if (p->subs[SUB_THREEWAY].owner) {
07894                unsigned int mssinceflash;
07895                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
07896                   the private structure -- not especially easy or clean */
07897                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
07898                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
07899                   DLA_UNLOCK(&p->lock);
07900                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
07901                   /* We can grab ast and p in that order, without worry.  We should make sure
07902                      nothing seriously bad has happened though like some sort of bizarre double
07903                      masquerade! */
07904                   DLA_LOCK(&p->lock);
07905                   if (p->owner != ast) {
07906                      ast_log(LOG_WARNING, "This isn't good...\n");
07907                      return NULL;
07908                   }
07909                }
07910                if (!p->subs[SUB_THREEWAY].owner) {
07911                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
07912                   return NULL;
07913                }
07914                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
07915                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
07916                if (mssinceflash < MIN_MS_SINCE_FLASH) {
07917                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
07918                      hanging up.  Hangup both channels now */
07919                   if (p->subs[SUB_THREEWAY].owner)
07920                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
07921                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07922                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
07923                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07924                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
07925                   if (p->transfer) {
07926                      /* In any case this isn't a threeway call anymore */
07927                      p->subs[SUB_REAL].inthreeway = 0;
07928                      p->subs[SUB_THREEWAY].inthreeway = 0;
07929                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
07930                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
07931                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07932                         /* Swap subs and dis-own channel */
07933                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
07934                         p->owner = NULL;
07935                         /* Ring the phone */
07936                         dahdi_ring_phone(p);
07937                      } else {
07938                         if ((res = attempt_transfer(p)) < 0) {
07939                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07940                            if (p->subs[SUB_THREEWAY].owner)
07941                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07942                         } else if (res) {
07943                            /* Don't actually hang up at this point */
07944                            if (p->subs[SUB_THREEWAY].owner)
07945                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07946                            break;
07947                         }
07948                      }
07949                   } else {
07950                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07951                      if (p->subs[SUB_THREEWAY].owner)
07952                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07953                   }
07954                } else {
07955                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07956                   /* Swap subs and dis-own channel */
07957                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
07958                   p->owner = NULL;
07959                   /* Ring the phone */
07960                   dahdi_ring_phone(p);
07961                }
07962             }
07963          } else {
07964             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
07965          }
07966          /* Fall through */
07967       default:
07968          dahdi_disable_ec(p);
07969          return NULL;
07970       }
07971       break;
07972    case DAHDI_EVENT_RINGOFFHOOK:
07973       if (p->inalarm) break;
07974       if (p->oprmode < 0)
07975       {
07976          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07977          {
07978             /* Make sure it stops ringing */
07979             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07980             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
07981             restore_conference(p->oprpeer);
07982          }
07983          break;
07984       }
07985       if (p->radio)
07986       {
07987          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07988          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
07989          break;
07990       }
07991       /* for E911, its supposed to wait for offhook then dial
07992          the second half of the dial string */
07993       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
07994          c = strchr(p->dialdest, '/');
07995          if (c)
07996             c++;
07997          else
07998             c = p->dialdest;
07999          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08000          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08001          if (strlen(p->dop.dialstr) > 4) {
08002             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08003             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08004             p->echorest[sizeof(p->echorest) - 1] = '\0';
08005             p->echobreak = 1;
08006             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08007          } else
08008             p->echobreak = 0;
08009          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08010             int saveerr = errno;
08011 
08012             x = DAHDI_ONHOOK;
08013             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08014             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08015             return NULL;
08016             }
08017          p->dialing = 1;
08018          return &p->subs[idx].f;
08019       }
08020       switch (p->sig) {
08021       case SIG_FXOLS:
08022       case SIG_FXOGS:
08023       case SIG_FXOKS:
08024          switch (ast->_state) {
08025          case AST_STATE_RINGING:
08026             dahdi_enable_ec(p);
08027             dahdi_train_ec(p);
08028             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08029             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08030             /* Make sure it stops ringing */
08031             p->subs[SUB_REAL].needringing = 0;
08032             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08033             ast_debug(1, "channel %d answered\n", p->channel);
08034 
08035             /* Cancel any running CallerID spill */
08036             ast_free(p->cidspill);
08037             p->cidspill = NULL;
08038             restore_conference(p);
08039 
08040             p->dialing = 0;
08041             p->callwaitcas = 0;
08042             if (p->confirmanswer) {
08043                /* Ignore answer if "confirm answer" is enabled */
08044                p->subs[idx].f.frametype = AST_FRAME_NULL;
08045                p->subs[idx].f.subclass.integer = 0;
08046             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08047                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08048                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08049                if (res < 0) {
08050                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08051                   p->dop.dialstr[0] = '\0';
08052                   return NULL;
08053                } else {
08054                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08055                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08056                   p->subs[idx].f.subclass.integer = 0;
08057                   p->dialing = 1;
08058                }
08059                p->dop.dialstr[0] = '\0';
08060                ast_setstate(ast, AST_STATE_DIALING);
08061             } else
08062                ast_setstate(ast, AST_STATE_UP);
08063             return &p->subs[idx].f;
08064          case AST_STATE_DOWN:
08065             ast_setstate(ast, AST_STATE_RING);
08066             ast->rings = 1;
08067             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08068             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08069             ast_debug(1, "channel %d picked up\n", p->channel);
08070             return &p->subs[idx].f;
08071          case AST_STATE_UP:
08072             /* Make sure it stops ringing */
08073             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08074             /* Okay -- probably call waiting*/
08075             if (ast_bridged_channel(p->owner))
08076                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08077             p->subs[idx].needunhold = 1;
08078             break;
08079          case AST_STATE_RESERVED:
08080             /* Start up dialtone */
08081             if (has_voicemail(p))
08082                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08083             else
08084                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08085             break;
08086          default:
08087             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08088          }
08089          break;
08090       case SIG_FXSLS:
08091       case SIG_FXSGS:
08092       case SIG_FXSKS:
08093          if (ast->_state == AST_STATE_RING) {
08094             p->ringt = p->ringt_base;
08095          }
08096 
08097          /* If we get a ring then we cannot be in
08098           * reversed polarity. So we reset to idle */
08099          ast_debug(1, "Setting IDLE polarity due "
08100             "to ring. Old polarity was %d\n",
08101             p->polarity);
08102          p->polarity = POLARITY_IDLE;
08103 
08104          /* Fall through */
08105       case SIG_EM:
08106       case SIG_EM_E1:
08107       case SIG_EMWINK:
08108       case SIG_FEATD:
08109       case SIG_FEATDMF:
08110       case SIG_FEATDMF_TA:
08111       case SIG_E911:
08112       case SIG_FGC_CAMA:
08113       case SIG_FGC_CAMAMF:
08114       case SIG_FEATB:
08115       case SIG_SF:
08116       case SIG_SFWINK:
08117       case SIG_SF_FEATD:
08118       case SIG_SF_FEATDMF:
08119       case SIG_SF_FEATB:
08120          if (ast->_state == AST_STATE_PRERING)
08121             ast_setstate(ast, AST_STATE_RING);
08122          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08123             ast_debug(1, "Ring detected\n");
08124             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08125             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08126          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08127             ast_debug(1, "Line answered\n");
08128             if (p->confirmanswer) {
08129                p->subs[idx].f.frametype = AST_FRAME_NULL;
08130                p->subs[idx].f.subclass.integer = 0;
08131             } else {
08132                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08133                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08134                ast_setstate(ast, AST_STATE_UP);
08135             }
08136          } else if (ast->_state != AST_STATE_RING)
08137             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08138          break;
08139       default:
08140          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08141       }
08142       break;
08143    case DAHDI_EVENT_RINGBEGIN:
08144       switch (p->sig) {
08145       case SIG_FXSLS:
08146       case SIG_FXSGS:
08147       case SIG_FXSKS:
08148          if (ast->_state == AST_STATE_RING) {
08149             p->ringt = p->ringt_base;
08150          }
08151          break;
08152       }
08153       break;
08154    case DAHDI_EVENT_RINGERON:
08155       break;
08156    case DAHDI_EVENT_NOALARM:
08157       switch (p->sig) {
08158 #if defined(HAVE_PRI)
08159       case SIG_PRI_LIB_HANDLE_CASES:
08160          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08161          break;
08162 #endif   /* defined(HAVE_PRI) */
08163 #if defined(HAVE_SS7)
08164       case SIG_SS7:
08165          sig_ss7_set_alarm(p->sig_pvt, 0);
08166          break;
08167 #endif   /* defined(HAVE_SS7) */
08168       default:
08169          p->inalarm = 0;
08170          break;
08171       }
08172       handle_clear_alarms(p);
08173       break;
08174    case DAHDI_EVENT_WINKFLASH:
08175       if (p->inalarm) break;
08176       if (p->radio) break;
08177       if (p->oprmode < 0) break;
08178       if (p->oprmode > 1)
08179       {
08180          struct dahdi_params par;
08181 
08182          memset(&par, 0, sizeof(par));
08183          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08184          {
08185             if (!par.rxisoffhook)
08186             {
08187                /* Make sure it stops ringing */
08188                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08189                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08190                save_conference(p);
08191                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08192             }
08193          }
08194          break;
08195       }
08196       /* Remember last time we got a flash-hook */
08197       p->flashtime = ast_tvnow();
08198       switch (mysig) {
08199       case SIG_FXOLS:
08200       case SIG_FXOGS:
08201       case SIG_FXOKS:
08202          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08203             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08204 
08205          /* Cancel any running CallerID spill */
08206          ast_free(p->cidspill);
08207          p->cidspill = NULL;
08208          restore_conference(p);
08209          p->callwaitcas = 0;
08210 
08211          if (idx != SUB_REAL) {
08212             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08213             goto winkflashdone;
08214          }
08215 
08216          if (p->subs[SUB_CALLWAIT].owner) {
08217             /* Swap to call-wait */
08218             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08219             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08220             p->owner = p->subs[SUB_REAL].owner;
08221             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08222             if (p->owner->_state == AST_STATE_RINGING) {
08223                ast_setstate(p->owner, AST_STATE_UP);
08224                p->subs[SUB_REAL].needanswer = 1;
08225             }
08226             p->callwaitingrepeat = 0;
08227             p->cidcwexpire = 0;
08228             p->cid_suppress_expire = 0;
08229             /* Start music on hold if appropriate */
08230             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08231                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08232                   S_OR(p->mohsuggest, NULL),
08233                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08234             }
08235             p->subs[SUB_CALLWAIT].needhold = 1;
08236             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08237                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08238                   S_OR(p->mohsuggest, NULL),
08239                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08240             }
08241             p->subs[SUB_REAL].needunhold = 1;
08242          } else if (!p->subs[SUB_THREEWAY].owner) {
08243             if (!p->threewaycalling) {
08244                /* Just send a flash if no 3-way calling */
08245                p->subs[SUB_REAL].needflash = 1;
08246                goto winkflashdone;
08247             } else if (!check_for_conference(p)) {
08248                char cid_num[256];
08249                char cid_name[256];
08250 
08251                cid_num[0] = 0;
08252                cid_name[0] = 0;
08253                if (p->dahditrcallerid && p->owner) {
08254                   if (p->owner->caller.id.number.valid
08255                      && p->owner->caller.id.number.str) {
08256                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08257                         sizeof(cid_num));
08258                   }
08259                   if (p->owner->caller.id.name.valid
08260                      && p->owner->caller.id.name.str) {
08261                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08262                         sizeof(cid_name));
08263                   }
08264                }
08265                /* XXX This section needs much more error checking!!! XXX */
08266                /* Start a 3-way call if feasible */
08267                if (!((ast->pbx) ||
08268                   (ast->_state == AST_STATE_UP) ||
08269                   (ast->_state == AST_STATE_RING))) {
08270                   ast_debug(1, "Flash when call not up or ringing\n");
08271                   goto winkflashdone;
08272                }
08273                if (alloc_sub(p, SUB_THREEWAY)) {
08274                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08275                   goto winkflashdone;
08276                }
08277                /* Make new channel */
08278                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08279                if (p->dahditrcallerid) {
08280                   if (!p->origcid_num)
08281                      p->origcid_num = ast_strdup(p->cid_num);
08282                   if (!p->origcid_name)
08283                      p->origcid_name = ast_strdup(p->cid_name);
08284                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08285                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08286                }
08287                /* Swap things around between the three-way and real call */
08288                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08289                /* Disable echo canceller for better dialing */
08290                dahdi_disable_ec(p);
08291                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08292                if (res)
08293                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08294                p->owner = chan;
08295                if (!chan) {
08296                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08297                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08298                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08299                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08300                   dahdi_enable_ec(p);
08301                   ast_hangup(chan);
08302                } else {
08303                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08304 
08305                   /* Start music on hold if appropriate */
08306                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08307                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08308                         S_OR(p->mohsuggest, NULL),
08309                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08310                   }
08311                   p->subs[SUB_THREEWAY].needhold = 1;
08312                }
08313             }
08314          } else {
08315             /* Already have a 3 way call */
08316             if (p->subs[SUB_THREEWAY].inthreeway) {
08317                /* Call is already up, drop the last person */
08318                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08319                /* If the primary call isn't answered yet, use it */
08320                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08321                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08322                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08323                   p->owner = p->subs[SUB_REAL].owner;
08324                }
08325                /* Drop the last call and stop the conference */
08326                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08327                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08328                p->subs[SUB_REAL].inthreeway = 0;
08329                p->subs[SUB_THREEWAY].inthreeway = 0;
08330             } else {
08331                /* Lets see what we're up to */
08332                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08333                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08334                   int otherindex = SUB_THREEWAY;
08335 
08336                   ast_verb(3, "Building conference call with %s and %s\n",
08337                      p->subs[SUB_THREEWAY].owner->name,
08338                      p->subs[SUB_REAL].owner->name);
08339                   /* Put them in the threeway, and flip */
08340                   p->subs[SUB_THREEWAY].inthreeway = 1;
08341                   p->subs[SUB_REAL].inthreeway = 1;
08342                   if (ast->_state == AST_STATE_UP) {
08343                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08344                      otherindex = SUB_REAL;
08345                   }
08346                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08347                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08348                   p->subs[otherindex].needunhold = 1;
08349                   p->owner = p->subs[SUB_REAL].owner;
08350                } else {
08351                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08352                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08353                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08354                   p->owner = p->subs[SUB_REAL].owner;
08355                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08356                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08357                   p->subs[SUB_REAL].needunhold = 1;
08358                   dahdi_enable_ec(p);
08359                }
08360             }
08361          }
08362 winkflashdone:
08363          update_conf(p);
08364          break;
08365       case SIG_EM:
08366       case SIG_EM_E1:
08367       case SIG_FEATD:
08368       case SIG_SF:
08369       case SIG_SFWINK:
08370       case SIG_SF_FEATD:
08371       case SIG_FXSLS:
08372       case SIG_FXSGS:
08373          if (p->dialing)
08374             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08375          else
08376             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08377          break;
08378       case SIG_FEATDMF_TA:
08379          switch (p->whichwink) {
08380          case 0:
08381             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08382                S_COR(p->owner->caller.ani.number.valid,
08383                   p->owner->caller.ani.number.str, ""));
08384             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08385                p->owner->caller.ani2,
08386                S_COR(p->owner->caller.ani.number.valid,
08387                   p->owner->caller.ani.number.str, ""));
08388             break;
08389          case 1:
08390             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08391             break;
08392          case 2:
08393             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08394             return NULL;
08395          }
08396          p->whichwink++;
08397          /* Fall through */
08398       case SIG_FEATDMF:
08399       case SIG_E911:
08400       case SIG_FGC_CAMAMF:
08401       case SIG_FGC_CAMA:
08402       case SIG_FEATB:
08403       case SIG_SF_FEATDMF:
08404       case SIG_SF_FEATB:
08405       case SIG_EMWINK:
08406          /* FGD MF and EMWINK *Must* wait for wink */
08407          if (!ast_strlen_zero(p->dop.dialstr)) {
08408             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08409             if (res < 0) {
08410                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08411                p->dop.dialstr[0] = '\0';
08412                return NULL;
08413             } else
08414                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08415          }
08416          p->dop.dialstr[0] = '\0';
08417          break;
08418       default:
08419          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08420       }
08421       break;
08422    case DAHDI_EVENT_HOOKCOMPLETE:
08423       if (p->inalarm) break;
08424       if ((p->radio || (p->oprmode < 0))) break;
08425       if (p->waitingfordt.tv_sec) break;
08426       switch (mysig) {
08427       case SIG_FXSLS:  /* only interesting for FXS */
08428       case SIG_FXSGS:
08429       case SIG_FXSKS:
08430       case SIG_EM:
08431       case SIG_EM_E1:
08432       case SIG_EMWINK:
08433       case SIG_FEATD:
08434       case SIG_SF:
08435       case SIG_SFWINK:
08436       case SIG_SF_FEATD:
08437          if (!ast_strlen_zero(p->dop.dialstr)) {
08438             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08439             if (res < 0) {
08440                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08441                p->dop.dialstr[0] = '\0';
08442                return NULL;
08443             } else
08444                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08445          }
08446          p->dop.dialstr[0] = '\0';
08447          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08448          break;
08449       case SIG_FEATDMF:
08450       case SIG_FEATDMF_TA:
08451       case SIG_E911:
08452       case SIG_FGC_CAMA:
08453       case SIG_FGC_CAMAMF:
08454       case SIG_FEATB:
08455       case SIG_SF_FEATDMF:
08456       case SIG_SF_FEATB:
08457          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08458          break;
08459       default:
08460          break;
08461       }
08462       break;
08463    case DAHDI_EVENT_POLARITY:
08464       /*
08465        * If we get a Polarity Switch event, check to see
08466        * if we should change the polarity state and
08467        * mark the channel as UP or if this is an indication
08468        * of remote end disconnect.
08469        */
08470       if (p->polarity == POLARITY_IDLE) {
08471          p->polarity = POLARITY_REV;
08472          if (p->answeronpolarityswitch &&
08473             ((ast->_state == AST_STATE_DIALING) ||
08474             (ast->_state == AST_STATE_RINGING))) {
08475             ast_debug(1, "Answering on polarity switch!\n");
08476             ast_setstate(p->owner, AST_STATE_UP);
08477             if (p->hanguponpolarityswitch) {
08478                p->polaritydelaytv = ast_tvnow();
08479             }
08480          } else
08481             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08482       }
08483       /* Removed else statement from here as it was preventing hangups from ever happening*/
08484       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08485       if (p->hanguponpolarityswitch &&
08486          (p->polarityonanswerdelay > 0) &&
08487          (p->polarity == POLARITY_REV) &&
08488          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08489          /* Added log_debug information below to provide a better indication of what is going on */
08490          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08491 
08492          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08493             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08494             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08495             p->polarity = POLARITY_IDLE;
08496          } else
08497             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
08498 
08499       } else {
08500          p->polarity = POLARITY_IDLE;
08501          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08502       }
08503       /* Added more log_debug information below to provide a better indication of what is going on */
08504       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08505       break;
08506    default:
08507       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08508    }
08509    return &p->subs[idx].f;
08510 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 6003 of file chan_dahdi.c.

References ast_channel::_state, analog_hangup(), analog_lib_handles(), ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_free(), ast_dsp_set_digitmode(), ast_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_verb, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cid_tag, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_ast_cause_to_r2_cause(), dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index, dahdi_r2_disconnect_call(), dahdi_set_hook(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), 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, analog_pvt::fxsoffhookstate, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2call, dahdi_pvt::mohsuggest, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, num_restart_pending, dahdi_pvt::oprmode, 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::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rdnis, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), revert_fax_buffers(), dahdi_pvt::ringt, S_OR, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, sig_pri_hangup(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_hangup(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and dahdi_pvt::waitingfordt.

06004 {
06005    int res = 0;
06006    int idx,x;
06007    int law;
06008    /*static int restore_gains(struct dahdi_pvt *p);*/
06009    struct dahdi_pvt *p = ast->tech_pvt;
06010    struct dahdi_params par;
06011 
06012    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06013    if (!ast->tech_pvt) {
06014       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06015       return 0;
06016    }
06017 
06018    ast_mutex_lock(&p->lock);
06019    p->exten[0] = '\0';
06020    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06021       dahdi_confmute(p, 0);
06022       restore_gains(p);
06023       p->ignoredtmf = 0;
06024       p->waitingfordt.tv_sec = 0;
06025 
06026       res = analog_hangup(p->sig_pvt, ast);
06027       revert_fax_buffers(p, ast);
06028 
06029       goto hangup_out;
06030    } else {
06031       p->cid_num[0] = '\0';
06032       p->cid_name[0] = '\0';
06033       p->cid_subaddr[0] = '\0';
06034    }
06035 
06036 #ifdef HAVE_PRI
06037    if (dahdi_sig_pri_lib_handles(p->sig)) {
06038       x = 1;
06039       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06040       dahdi_confmute(p, 0);
06041       p->muting = 0;
06042       restore_gains(p);
06043       if (p->dsp) {
06044          ast_dsp_free(p->dsp);
06045          p->dsp = NULL;
06046       }
06047       p->ignoredtmf = 0;
06048       revert_fax_buffers(p, ast);
06049       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06050       p->law = p->law_default;
06051       law = p->law_default;
06052       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06053       dahdi_disable_ec(p);
06054       update_conf(p);
06055       reset_conf(p);
06056       sig_pri_hangup(p->sig_pvt, ast);
06057       p->subs[SUB_REAL].owner = NULL;
06058       p->subs[SUB_REAL].needbusy = 0;
06059       p->owner = NULL;
06060       p->cid_tag[0] = '\0';
06061       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06062       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06063       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06064       p->outgoing = 0;
06065       p->digital = 0;
06066       p->faxhandled = 0;
06067       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06068       goto hangup_out;
06069    }
06070 #endif
06071 
06072 #if defined(HAVE_SS7)
06073    if (p->sig == SIG_SS7) {
06074       x = 1;
06075       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06076 
06077       dahdi_confmute(p, 0);
06078       p->muting = 0;
06079       restore_gains(p);
06080       if (p->dsp) {
06081          ast_dsp_free(p->dsp);
06082          p->dsp = NULL;
06083       }
06084       p->ignoredtmf = 0;
06085 
06086       /* Real channel, do some fixup */
06087       p->subs[SUB_REAL].owner = NULL;
06088       p->subs[SUB_REAL].needbusy = 0;
06089       p->polarity = POLARITY_IDLE;
06090       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06091 
06092       p->owner = NULL;
06093       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06094       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06095       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06096       p->outgoing = 0;
06097       p->digital = 0;
06098       p->faxhandled = 0;
06099       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06100 
06101       revert_fax_buffers(p, ast);
06102 
06103       p->law = p->law_default;
06104       law = p->law_default;
06105       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06106       if (res < 0)
06107          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06108 
06109       sig_ss7_hangup(p->sig_pvt, ast);
06110 
06111       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06112       dahdi_disable_ec(p);
06113       x = 0;
06114       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06115       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06116       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06117       update_conf(p);
06118       reset_conf(p);
06119 
06120       /* Restore data mode */
06121       x = 0;
06122       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06123 
06124       if (num_restart_pending == 0)
06125          restart_monitor();
06126 
06127       ast->tech_pvt = NULL;
06128       goto hangup_out;
06129    }
06130 #endif   /* defined(HAVE_SS7) */
06131 
06132    idx = dahdi_get_index(ast, p, 1);
06133 
06134    dahdi_confmute(p, 0);
06135    p->muting = 0;
06136    restore_gains(p);
06137    if (p->origcid_num) {
06138       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06139       ast_free(p->origcid_num);
06140       p->origcid_num = NULL;
06141    }
06142    if (p->origcid_name) {
06143       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06144       ast_free(p->origcid_name);
06145       p->origcid_name = NULL;
06146    }
06147    if (p->dsp)
06148       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06149 
06150    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06151       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06152    p->ignoredtmf = 0;
06153 
06154    if (idx > -1) {
06155       /* Real channel, do some fixup */
06156       p->subs[idx].owner = NULL;
06157       p->subs[idx].needanswer = 0;
06158       p->subs[idx].needflash = 0;
06159       p->subs[idx].needringing = 0;
06160       p->subs[idx].needbusy = 0;
06161       p->subs[idx].needcongestion = 0;
06162       p->subs[idx].linear = 0;
06163       p->polarity = POLARITY_IDLE;
06164       dahdi_setlinear(p->subs[idx].dfd, 0);
06165       if (idx == SUB_REAL) {
06166          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06167             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06168             if (p->subs[SUB_CALLWAIT].inthreeway) {
06169                /* We had flipped over to answer a callwait and now it's gone */
06170                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06171                /* Move to the call-wait, but un-own us until they flip back. */
06172                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06173                unalloc_sub(p, SUB_CALLWAIT);
06174                p->owner = NULL;
06175             } else {
06176                /* The three way hung up, but we still have a call wait */
06177                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06178                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06179                unalloc_sub(p, SUB_THREEWAY);
06180                if (p->subs[SUB_REAL].inthreeway) {
06181                   /* This was part of a three way call.  Immediately make way for
06182                      another call */
06183                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06184                   p->owner = p->subs[SUB_REAL].owner;
06185                } else {
06186                   /* This call hasn't been completed yet...  Set owner to NULL */
06187                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06188                   p->owner = NULL;
06189                }
06190                p->subs[SUB_REAL].inthreeway = 0;
06191             }
06192          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06193             /* Move to the call-wait and switch back to them. */
06194             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06195             unalloc_sub(p, SUB_CALLWAIT);
06196             p->owner = p->subs[SUB_REAL].owner;
06197             if (p->owner->_state != AST_STATE_UP)
06198                p->subs[SUB_REAL].needanswer = 1;
06199             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06200                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06201          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06202             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06203             unalloc_sub(p, SUB_THREEWAY);
06204             if (p->subs[SUB_REAL].inthreeway) {
06205                /* This was part of a three way call.  Immediately make way for
06206                   another call */
06207                ast_debug(1, "Call was complete, setting owner to former third call\n");
06208                p->owner = p->subs[SUB_REAL].owner;
06209             } else {
06210                /* This call hasn't been completed yet...  Set owner to NULL */
06211                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06212                p->owner = NULL;
06213             }
06214             p->subs[SUB_REAL].inthreeway = 0;
06215          }
06216       } else if (idx == SUB_CALLWAIT) {
06217          /* Ditch the holding callwait call, and immediately make it availabe */
06218          if (p->subs[SUB_CALLWAIT].inthreeway) {
06219             /* This is actually part of a three way, placed on hold.  Place the third part
06220                on music on hold now */
06221             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06222                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06223                   S_OR(p->mohsuggest, NULL),
06224                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06225             }
06226             p->subs[SUB_THREEWAY].inthreeway = 0;
06227             /* Make it the call wait now */
06228             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06229             unalloc_sub(p, SUB_THREEWAY);
06230          } else
06231             unalloc_sub(p, SUB_CALLWAIT);
06232       } else if (idx == SUB_THREEWAY) {
06233          if (p->subs[SUB_CALLWAIT].inthreeway) {
06234             /* The other party of the three way call is currently in a call-wait state.
06235                Start music on hold for them, and take the main guy out of the third call */
06236             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06237                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06238                   S_OR(p->mohsuggest, NULL),
06239                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06240             }
06241             p->subs[SUB_CALLWAIT].inthreeway = 0;
06242          }
06243          p->subs[SUB_REAL].inthreeway = 0;
06244          /* If this was part of a three way call index, let us make
06245             another three way call */
06246          unalloc_sub(p, SUB_THREEWAY);
06247       } else {
06248          /* This wasn't any sort of call, but how are we an index? */
06249          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06250       }
06251    }
06252 
06253    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06254       p->owner = NULL;
06255       p->ringt = 0;
06256       p->distinctivering = 0;
06257       p->confirmanswer = 0;
06258       p->outgoing = 0;
06259       p->digital = 0;
06260       p->faxhandled = 0;
06261       p->pulsedial = 0;
06262       if (p->dsp) {
06263          ast_dsp_free(p->dsp);
06264          p->dsp = NULL;
06265       }
06266 
06267       revert_fax_buffers(p, ast);
06268 
06269       p->law = p->law_default;
06270       law = p->law_default;
06271       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06272       if (res < 0)
06273          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06274       /* Perform low level hangup if no owner left */
06275 #ifdef HAVE_OPENR2
06276       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06277          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06278          /* If it's an incoming call, check the mfcr2_forced_release setting */
06279          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06280             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06281          } else {
06282             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06283             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06284             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06285                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06286             dahdi_r2_disconnect_call(p, r2cause);
06287          }
06288       } else if (p->mfcr2call) {
06289          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06290          /* since ast_request() was called but not ast_call() we have not yet dialed
06291          and the openr2 stack will not call on_call_end callback, we need to unset
06292          the mfcr2call flag and bump the monitor count so the monitor thread can take
06293          care of this channel events from now on */
06294          p->mfcr2call = 0;
06295       }
06296 #endif
06297       switch (p->sig) {
06298       case SIG_SS7:
06299       case SIG_MFCR2:
06300       case SIG_PRI_LIB_HANDLE_CASES:
06301       case 0:
06302          break;
06303       default:
06304          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06305          break;
06306       }
06307       if (res < 0) {
06308          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06309       }
06310       switch (p->sig) {
06311       case SIG_FXOGS:
06312       case SIG_FXOLS:
06313       case SIG_FXOKS:
06314          memset(&par, 0, sizeof(par));
06315          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06316          if (!res) {
06317             struct analog_pvt *analog_p = p->sig_pvt;
06318 #if 0
06319             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06320 #endif
06321             /* If they're off hook, try playing congestion */
06322             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06323                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06324             else
06325                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06326             analog_p->fxsoffhookstate = par.rxisoffhook;
06327          }
06328          break;
06329       case SIG_FXSGS:
06330       case SIG_FXSLS:
06331       case SIG_FXSKS:
06332          /* Make sure we're not made available for at least two seconds assuming
06333          we were actually used for an inbound or outbound call. */
06334          if (ast->_state != AST_STATE_RESERVED) {
06335             time(&p->guardtime);
06336             p->guardtime += 2;
06337          }
06338          break;
06339       default:
06340          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06341       }
06342       if (p->sig)
06343          dahdi_disable_ec(p);
06344       x = 0;
06345       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06346       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06347       p->didtdd = 0;
06348       p->callwaitcas = 0;
06349       p->callwaiting = p->permcallwaiting;
06350       p->hidecallerid = p->permhidecallerid;
06351       p->waitingfordt.tv_sec = 0;
06352       p->dialing = 0;
06353       p->rdnis[0] = '\0';
06354       update_conf(p);
06355       reset_conf(p);
06356       /* Restore data mode */
06357       switch (p->sig) {
06358       case SIG_PRI_LIB_HANDLE_CASES:
06359       case SIG_SS7:
06360          x = 0;
06361          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06362          break;
06363       default:
06364          break;
06365       }
06366       if (num_restart_pending == 0)
06367          restart_monitor();
06368    }
06369 
06370    p->callwaitingrepeat = 0;
06371    p->cidcwexpire = 0;
06372    p->cid_suppress_expire = 0;
06373    p->oprmode = 0;
06374    ast->tech_pvt = NULL;
06375 hangup_out:
06376    ast_free(p->cidspill);
06377    p->cidspill = NULL;
06378 
06379    ast_mutex_unlock(&p->lock);
06380    ast_module_unref(ast_module_info->self);
06381    ast_verb(3, "Hungup '%s'\n", ast->name);
06382 
06383    ast_mutex_lock(&iflock);
06384 
06385    if (p->restartpending) {
06386       num_restart_pending--;
06387    }
06388 
06389    if (p->destroy) {
06390       destroy_channel(p, 0);
06391    }
06392    ast_mutex_unlock(&iflock);
06393    return 0;
06394 }

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

Definition at line 5404 of file chan_dahdi.c.

References DAHDI_IFLIST_NONE, ifend, iflist, dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::which_iflist.

Referenced by destroy_dahdi_pvt().

05405 {
05406    /* Extract from the forward chain. */
05407    if (pvt->prev) {
05408       pvt->prev->next = pvt->next;
05409    } else if (iflist == pvt) {
05410       /* Node is at the head of the list. */
05411       iflist = pvt->next;
05412    }
05413 
05414    /* Extract from the reverse chain. */
05415    if (pvt->next) {
05416       pvt->next->prev = pvt->prev;
05417    } else if (ifend == pvt) {
05418       /* Node is at the end of the list. */
05419       ifend = pvt->prev;
05420    }
05421 
05422    /* Node is no longer in the list. */
05423    pvt->which_iflist = DAHDI_IFLIST_NONE;
05424    pvt->prev = NULL;
05425    pvt->next = NULL;
05426 }

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

Definition at line 5354 of file chan_dahdi.c.

References dahdi_pvt::channel, DAHDI_IFLIST_MAIN, iflist, dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::which_iflist.

Referenced by duplicate_pseudo().

05355 {
05356    struct dahdi_pvt *cur;
05357 
05358    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05359 
05360    /* Find place in middle of list for the new interface. */
05361    for (cur = iflist; cur; cur = cur->next) {
05362       if (pvt->channel < cur->channel) {
05363          /* New interface goes before the current interface. */
05364          pvt->prev = cur->prev;
05365          pvt->next = cur;
05366          if (cur->prev) {
05367             /* Insert into the middle of the list. */
05368             cur->prev->next = pvt;
05369          } else {
05370             /* Insert at head of list. */
05371             iflist = pvt;
05372          }
05373          cur->prev = pvt;
05374          return;
05375       }
05376    }
05377 
05378    /* New interface goes onto the end of the list */
05379    pvt->prev = ifend;
05380    pvt->next = NULL;
05381    if (ifend) {
05382       ifend->next = pvt;
05383    }
05384    ifend = pvt;
05385    if (!iflist) {
05386       /* List was empty */
05387       iflist = pvt;
05388    }
05389 }

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

Definition at line 9126 of file chan_dahdi.c.

References ast_channel::_state, AST_CAUSE_CONGESTION, 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_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_get_index, dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mohinterpret, ast_channel::name, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, sig_pri_indicate(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_indicate(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

09127 {
09128    struct dahdi_pvt *p = chan->tech_pvt;
09129    int res=-1;
09130    int idx;
09131    int func = DAHDI_FLASH;
09132 
09133    ast_mutex_lock(&p->lock);
09134    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09135    switch (p->sig) {
09136 #if defined(HAVE_PRI)
09137    case SIG_PRI_LIB_HANDLE_CASES:
09138       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09139       ast_mutex_unlock(&p->lock);
09140       return res;
09141 #endif   /* defined(HAVE_PRI) */
09142 #if defined(HAVE_SS7)
09143    case SIG_SS7:
09144       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09145       ast_mutex_unlock(&p->lock);
09146       return res;
09147 #endif   /* defined(HAVE_SS7) */
09148    default:
09149       break;
09150    }
09151 #ifdef HAVE_OPENR2
09152    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09153       ast_mutex_unlock(&p->lock);
09154       /* if this is an R2 call and the call is not yet accepted, we don't want the
09155          tone indications to mess up with the MF tones */
09156       return 0;
09157    }
09158 #endif
09159    idx = dahdi_get_index(chan, p, 0);
09160    if (idx == SUB_REAL) {
09161       switch (condition) {
09162       case AST_CONTROL_BUSY:
09163          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09164          break;
09165       case AST_CONTROL_RINGING:
09166          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09167 
09168          if (chan->_state != AST_STATE_UP) {
09169             if ((chan->_state != AST_STATE_RING) ||
09170                ((p->sig != SIG_FXSKS) &&
09171              (p->sig != SIG_FXSLS) &&
09172              (p->sig != SIG_FXSGS)))
09173             ast_setstate(chan, AST_STATE_RINGING);
09174          }
09175          break;
09176       case AST_CONTROL_PROCEEDING:
09177          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
09178          /* don't continue in ast_indicate */
09179          res = 0;
09180          break;
09181       case AST_CONTROL_PROGRESS:
09182          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
09183          /* don't continue in ast_indicate */
09184          res = 0;
09185          break;
09186       case AST_CONTROL_CONGESTION:
09187          chan->hangupcause = AST_CAUSE_CONGESTION;
09188          break;
09189       case AST_CONTROL_HOLD:
09190          ast_moh_start(chan, data, p->mohinterpret);
09191          break;
09192       case AST_CONTROL_UNHOLD:
09193          ast_moh_stop(chan);
09194          break;
09195       case AST_CONTROL_RADIO_KEY:
09196          if (p->radio)
09197             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09198          res = 0;
09199          break;
09200       case AST_CONTROL_RADIO_UNKEY:
09201          if (p->radio)
09202             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09203          res = 0;
09204          break;
09205       case AST_CONTROL_FLASH:
09206          /* flash hookswitch */
09207          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09208             /* Clear out the dial buffer */
09209             p->dop.dialstr[0] = '\0';
09210             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09211                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09212                   chan->name, strerror(errno));
09213             } else
09214                res = 0;
09215          } else
09216             res = 0;
09217          break;
09218       case AST_CONTROL_SRCUPDATE:
09219          res = 0;
09220          break;
09221       case -1:
09222          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09223          break;
09224       }
09225    } else {
09226       res = 0;
09227    }
09228    ast_mutex_unlock(&p->lock);
09229    return res;
09230 }

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

Definition at line 6974 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and dahdi_pvt::slaves.

Referenced by dahdi_bridge().

06974                                                                           {
06975    int x;
06976    if (!slave || !master) {
06977       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
06978       return;
06979    }
06980    for (x = 0; x < MAX_SLAVES; x++) {
06981       if (!master->slaves[x]) {
06982          master->slaves[x] = slave;
06983          break;
06984       }
06985    }
06986    if (x >= MAX_SLAVES) {
06987       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
06988       master->slaves[MAX_SLAVES - 1] = slave;
06989    }
06990    if (slave->master)
06991       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
06992    slave->master = master;
06993 
06994    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
06995 }

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

Definition at line 3634 of file chan_dahdi.c.

References ast_channel_trylock, dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by wakeup_sub().

03635 {
03636    for (;;) {
03637       if (!pvt->subs[sub_idx].owner) {
03638          /* No subchannel owner pointer */
03639          break;
03640       }
03641       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03642          /* Got subchannel owner lock */
03643          break;
03644       }
03645       /* We must unlock the private to avoid the possibility of a deadlock */
03646       DEADLOCK_AVOIDANCE(&pvt->lock);
03647    }
03648 }

static struct ast_channel * dahdi_new ( struct dahdi_pvt i,
int  state,
int  startpbx,
int  idx,
int  law,
const char *  linkedid 
) [static]

Definition at line 9280 of file chan_dahdi.c.

References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, dahdi_pvt::amaflags, analog_lib_handles(), ast_party_caller::ani, ast_party_caller::ani2, AST_ADSI_UNAVAILABLE, ast_cc_copy_config_params(), ast_channel_alloc, ast_channel_cc_params_init(), ast_channel_set_fd(), ast_copy_string(), ast_debug, ast_devstate_changed_literal(), 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_digitmode(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_free, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_state_chan2dev(), AST_STATE_RING, ast_str_buffer(), ast_strdup, ast_string_field_set, ast_strlen_zero(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, ast_channel::caller, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, CANBUSYDETECT, CANPROGRESSDETECT, sig_pri_span::cc_params, dahdi_pvt::cc_params, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, ast_channel::context, dahdi_pvt::context, create_channel_name(), dahdi_confmute(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), dahdi_tech, dahdi_subchannel::dfd, ast_channel::dialed, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_party_redirecting::from, global_jbconf, dahdi_pvt::hardwaredtmf, ast_party_caller::id, language, dahdi_pvt::language, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::mfcr2_recvd_category, dahdi_pvt::mfcr2call, dahdi_pvt::muting, ast_variable::name, ast_party_id::name, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, ast_party_dialed::number, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, parkinglot, dahdi_pvt::parkinglot, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, dahdi_pvt::pri, progzone, dahdi_pvt::radio, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::redirecting, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_PRI_LIB_HANDLE_CASES, SIG_SS7, dahdi_pvt::silencethreshold, ast_party_dialed::str, ast_party_number::str, SUB_REAL, subnames, dahdi_pvt::subs, ast_party_id::tag, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, ast_variable::value, dahdi_pvt::vars, dahdi_pvt::waitfordialtone, and ast_channel::writeformat.

Referenced by dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_offered(), dahdi_request(), handle_init_event(), mwi_thread(), my_new_analog_ast_channel(), my_new_pri_ast_channel(), my_new_ss7_ast_channel(), and register_translator().

09281 {
09282    struct ast_channel *tmp;
09283    format_t deflaw;
09284    int x;
09285    int features;
09286    struct ast_str *chan_name;
09287    struct ast_variable *v;
09288 
09289    if (i->subs[idx].owner) {
09290       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09291       return NULL;
09292    }
09293 
09294 #if defined(HAVE_PRI)
09295    /*
09296     * The dnid has been stuffed with the called-number[:subaddress]
09297     * by dahdi_request() for outgoing calls.
09298     */
09299    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09300 #else
09301    chan_name = create_channel_name(i);
09302 #endif   /* defined(HAVE_PRI) */
09303    if (!chan_name) {
09304       return NULL;
09305    }
09306 
09307    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
09308    ast_free(chan_name);
09309    if (!tmp)
09310       return NULL;
09311    tmp->tech = &dahdi_tech;
09312 #if defined(HAVE_PRI)
09313    if (i->pri) {
09314       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09315    }
09316 #endif   /* defined(HAVE_PRI) */
09317    ast_channel_cc_params_init(tmp, i->cc_params);
09318    if (law) {
09319       i->law = law;
09320       if (law == DAHDI_LAW_ALAW) {
09321          deflaw = AST_FORMAT_ALAW;
09322       } else {
09323          deflaw = AST_FORMAT_ULAW;
09324       }
09325    } else {
09326       switch (i->sig) {
09327       case SIG_PRI_LIB_HANDLE_CASES:
09328          /* Make sure companding law is known. */
09329          i->law = (i->law_default == DAHDI_LAW_ALAW)
09330             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09331          break;
09332       default:
09333          i->law = i->law_default;
09334          break;
09335       }
09336       if (i->law_default == DAHDI_LAW_ALAW) {
09337          deflaw = AST_FORMAT_ALAW;
09338       } else {
09339          deflaw = AST_FORMAT_ULAW;
09340       }
09341    }
09342    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09343    tmp->nativeformats = deflaw;
09344    /* Start out assuming ulaw since it's smaller :) */
09345    tmp->rawreadformat = deflaw;
09346    tmp->readformat = deflaw;
09347    tmp->rawwriteformat = deflaw;
09348    tmp->writeformat = deflaw;
09349    i->subs[idx].linear = 0;
09350    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09351    features = 0;
09352    if (idx == SUB_REAL) {
09353       if (i->busydetect && CANBUSYDETECT(i))
09354          features |= DSP_FEATURE_BUSY_DETECT;
09355       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09356          features |= DSP_FEATURE_CALL_PROGRESS;
09357       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09358          features |= DSP_FEATURE_WAITDIALTONE;
09359       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09360          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09361          features |= DSP_FEATURE_FAX_DETECT;
09362       }
09363       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09364       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09365          i->hardwaredtmf = 0;
09366          features |= DSP_FEATURE_DIGIT_DETECT;
09367       } else if (NEED_MFDETECT(i)) {
09368          i->hardwaredtmf = 1;
09369          features |= DSP_FEATURE_DIGIT_DETECT;
09370       }
09371    }
09372    if (features) {
09373       if (i->dsp) {
09374          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09375       } else {
09376          if (i->channel != CHAN_PSEUDO)
09377             i->dsp = ast_dsp_new();
09378          else
09379             i->dsp = NULL;
09380          if (i->dsp) {
09381             i->dsp_features = features;
09382 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09383             /* We cannot do progress detection until receive PROGRESS message */
09384             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09385                /* Remember requested DSP features, don't treat
09386                   talking as ANSWER */
09387                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09388                features = 0;
09389             }
09390 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09391             ast_dsp_set_features(i->dsp, features);
09392             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09393             if (!ast_strlen_zero(progzone))
09394                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09395             if (i->busydetect && CANBUSYDETECT(i)) {
09396                if(i->silencethreshold > 0)
09397                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09398                ast_dsp_set_busy_count(i->dsp, i->busycount);
09399                if(i->busytonelength > 0)
09400                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09401                if((i->busytonelength == i->busyquietlength) && i->busycompare)
09402                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09403             }
09404          }
09405       }
09406    }
09407 
09408    if (state == AST_STATE_RING)
09409       tmp->rings = 1;
09410    tmp->tech_pvt = i;
09411    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09412       /* Only FXO signalled stuff can be picked up */
09413       tmp->callgroup = i->callgroup;
09414       tmp->pickupgroup = i->pickupgroup;
09415    }
09416    if (!ast_strlen_zero(i->parkinglot))
09417       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09418    if (!ast_strlen_zero(i->language))
09419       ast_string_field_set(tmp, language, i->language);
09420    if (!i->owner)
09421       i->owner = tmp;
09422    if (!ast_strlen_zero(i->accountcode))
09423       ast_string_field_set(tmp, accountcode, i->accountcode);
09424    if (i->amaflags)
09425       tmp->amaflags = i->amaflags;
09426    i->subs[idx].owner = tmp;
09427    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09428    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09429       ast_string_field_set(tmp, call_forward, i->call_forward);
09430    }
09431    /* If we've been told "no ADSI" then enforce it */
09432    if (!i->adsi)
09433       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09434    if (!ast_strlen_zero(i->exten))
09435       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09436    if (!ast_strlen_zero(i->rdnis)) {
09437       tmp->redirecting.from.number.valid = 1;
09438       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09439    }
09440    if (!ast_strlen_zero(i->dnid)) {
09441       tmp->dialed.number.str = ast_strdup(i->dnid);
09442    }
09443 
09444    /* Don't use ast_set_callerid() here because it will
09445     * generate a needless NewCallerID event */
09446 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09447    if (!ast_strlen_zero(i->cid_ani)) {
09448       tmp->caller.ani.number.valid = 1;
09449       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09450    } else if (!ast_strlen_zero(i->cid_num)) {
09451       tmp->caller.ani.number.valid = 1;
09452       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09453    }
09454 #else
09455    if (!ast_strlen_zero(i->cid_num)) {
09456       tmp->caller.ani.number.valid = 1;
09457       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09458    }
09459 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09460    tmp->caller.id.name.presentation = i->callingpres;
09461    tmp->caller.id.number.presentation = i->callingpres;
09462    tmp->caller.id.number.plan = i->cid_ton;
09463    tmp->caller.ani2 = i->cid_ani2;
09464    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09465    /* clear the fake event in case we posted one before we had ast_channel */
09466    i->fake_event = 0;
09467    /* Assure there is no confmute on this channel */
09468    dahdi_confmute(i, 0);
09469    i->muting = 0;
09470    /* Configure the new channel jb */
09471    ast_jb_configure(tmp, &global_jbconf);
09472 
09473    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
09474 
09475    for (v = i->vars ; v ; v = v->next)
09476       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09477 
09478    ast_module_ref(ast_module_info->self);
09479 
09480    if (startpbx) {
09481 #ifdef HAVE_OPENR2
09482       if (i->mfcr2call) {
09483          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09484       }
09485 #endif
09486       if (ast_pbx_start(tmp)) {
09487          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09488          ast_hangup(tmp);
09489          return NULL;
09490       }
09491    }
09492    return tmp;
09493 }

static int dahdi_new_pri_nobch_channel ( struct sig_pri_span pri  )  [static]

Definition at line 12927 of file chan_dahdi.c.

References CHAN_PSEUDO, sig_pri_span::numchans, and sig_pri_span::pvts.

12928 {
12929    int pvt_idx;
12930    int res;
12931    unsigned idx;
12932    struct dahdi_pvt *pvt;
12933    struct sig_pri_chan *chan;
12934    struct dahdi_bufferinfo bi;
12935 
12936    static int nobch_channel = CHAN_PSEUDO;
12937 
12938    /* Find spot in the private pointer array for new interface. */
12939    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
12940       if (!pri->pvts[pvt_idx]) {
12941          break;
12942       }
12943    }
12944    if (pri->numchans == pvt_idx) {
12945       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
12946          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
12947          return -1;
12948       }
12949 
12950       /* Add new spot to the private pointer array. */
12951       pri->pvts[pvt_idx] = NULL;
12952       ++pri->numchans;
12953    }
12954 
12955    pvt = ast_calloc(1, sizeof(*pvt));
12956    if (!pvt) {
12957       return -1;
12958    }
12959    pvt->cc_params = ast_cc_config_params_init();
12960    if (!pvt->cc_params) {
12961       ast_free(pvt);
12962       return -1;
12963    }
12964    ast_mutex_init(&pvt->lock);
12965    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
12966       pvt->subs[idx].dfd = -1;
12967    }
12968    pvt->buf_no = dahdi_pseudo_parms.buf_no;
12969    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
12970    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
12971    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
12972 
12973    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
12974    if (!chan) {
12975       destroy_dahdi_pvt(pvt);
12976       return -1;
12977    }
12978    chan->no_b_channel = 1;
12979 
12980    /*
12981     * Pseudo channel companding law.
12982     * Needed for outgoing call waiting calls.
12983     * XXX May need to make this determined by switchtype or user option.
12984     */
12985    pvt->law_default = DAHDI_LAW_ALAW;
12986 
12987    pvt->sig = pri->sig;
12988    pvt->outsigmod = -1;
12989    pvt->pri = pri;
12990    pvt->sig_pvt = chan;
12991    pri->pvts[pvt_idx] = chan;
12992 
12993    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
12994    if (pvt->subs[SUB_REAL].dfd < 0) {
12995       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
12996          strerror(errno));
12997       destroy_dahdi_pvt(pvt);
12998       return -1;
12999    }
13000    memset(&bi, 0, sizeof(bi));
13001    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13002    if (!res) {
13003       pvt->bufsize = bi.bufsize;
13004       bi.txbufpolicy = pvt->buf_policy;
13005       bi.rxbufpolicy = pvt->buf_policy;
13006       bi.numbufs = pvt->buf_no;
13007       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13008       if (res < 0) {
13009          ast_log(LOG_WARNING,
13010             "Unable to set buffer policy on no B channel interface: %s\n",
13011             strerror(errno));
13012       }
13013    } else
13014       ast_log(LOG_WARNING,
13015          "Unable to check buffer policy on no B channel interface: %s\n",
13016          strerror(errno));
13017 
13018    --nobch_channel;
13019    if (CHAN_PSEUDO < nobch_channel) {
13020       nobch_channel = CHAN_PSEUDO - 1;
13021    }
13022    pvt->channel = nobch_channel;
13023    chan->channel = pvt->channel;
13024 
13025    dahdi_nobch_insert(pri, pvt);
13026 
13027    return pvt_idx;
13028 }

static void dahdi_nobch_extract ( struct sig_pri_span pri,
struct dahdi_pvt pvt 
) [static]

Definition at line 5498 of file chan_dahdi.c.

References DAHDI_IFLIST_NONE, dahdi_pvt::next, sig_pri_span::no_b_chan_end, sig_pri_span::no_b_chan_iflist, dahdi_pvt::prev, dahdi_pvt::pri, and dahdi_pvt::which_iflist.

Referenced by destroy_dahdi_pvt().

05499 {
05500    /* Extract from the forward chain. */
05501    if (pvt->prev) {
05502       pvt->prev->next = pvt->next;
05503    } else if (pri->no_b_chan_iflist == pvt) {
05504       /* Node is at the head of the list. */
05505       pri->no_b_chan_iflist = pvt->next;
05506    }
05507 
05508    /* Extract from the reverse chain. */
05509    if (pvt->next) {
05510       pvt->next->prev = pvt->prev;
05511    } else if (pri->no_b_chan_end == pvt) {
05512       /* Node is at the end of the list. */
05513       pri->no_b_chan_end = pvt->prev;
05514    }
05515 
05516    /* Node is no longer in the list. */
05517    pvt->which_iflist = DAHDI_IFLIST_NONE;
05518    pvt->prev = NULL;
05519    pvt->next = NULL;
05520 }

static void dahdi_nobch_insert ( struct sig_pri_span pri,
struct dahdi_pvt pvt 
) [static]

Definition at line 5445 of file chan_dahdi.c.

References dahdi_pvt::channel, DAHDI_IFLIST_NO_B_CHAN, dahdi_pvt::next, sig_pri_span::no_b_chan_end, sig_pri_span::no_b_chan_iflist, dahdi_pvt::prev, dahdi_pvt::pri, and dahdi_pvt::which_iflist.

05446 {
05447    struct dahdi_pvt *cur;
05448 
05449    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05450 
05451    /* Find place in middle of list for the new interface. */
05452    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05453       if (pvt->channel < cur->channel) {
05454          /* New interface goes before the current interface. */
05455          pvt->prev = cur->prev;
05456          pvt->next = cur;
05457          if (cur->prev) {
05458             /* Insert into the middle of the list. */
05459             cur->prev->next = pvt;
05460          } else {
05461             /* Insert at head of list. */
05462             pri->no_b_chan_iflist = pvt;
05463          }
05464          cur->prev = pvt;
05465          return;
05466       }
05467    }
05468 
05469    /* New interface goes onto the end of the list */
05470    pvt->prev = pri->no_b_chan_end;
05471    pvt->next = NULL;
05472    if (pri->no_b_chan_end) {
05473       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05474    }
05475    pri->no_b_chan_end = pvt;
05476    if (!pri->no_b_chan_iflist) {
05477       /* List was empty */
05478       pri->no_b_chan_iflist = pvt;
05479    }
05480 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4165 of file chan_dahdi.c.

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

Referenced by alloc_sub(), and duplicate_pseudo().

04166 {
04167    int fd;
04168    int isnum;
04169    int chan = 0;
04170    int bs;
04171    int x;
04172    isnum = 1;
04173    for (x = 0; x < strlen(fn); x++) {
04174       if (!isdigit(fn[x])) {
04175          isnum = 0;
04176          break;
04177       }
04178    }
04179    if (isnum) {
04180       chan = atoi(fn);
04181       if (chan < 1) {
04182          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04183          return -1;
04184       }
04185       fn = "/dev/dahdi/channel";
04186    }
04187    fd = open(fn, O_RDWR | O_NONBLOCK);
04188    if (fd < 0) {
04189       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04190       return -1;
04191    }
04192    if (chan) {
04193       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04194          x = errno;
04195          close(fd);
04196          errno = x;
04197          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04198          return -1;
04199       }
04200    }
04201    bs = READ_SIZE;
04202    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04203       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04204       x = errno;
04205       close(fd);
04206       errno = x;
04207       return -1;
04208    }
04209    return fd;
04210 }

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

Definition at line 13723 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, errno, pridebugfd, pridebugfdlock, and pris.

Referenced by load_module().

13724 {
13725    int x, y;
13726    int dchan = -1, span = -1;
13727    int dchancount = 0;
13728 
13729    if (pri) {
13730       for (x = 0; x < NUM_SPANS; x++) {
13731          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13732             if (pris[x].pri.dchans[y])
13733                dchancount++;
13734 
13735             if (pris[x].pri.dchans[y] == pri)
13736                dchan = y;
13737          }
13738          if (dchan >= 0) {
13739             span = x;
13740             break;
13741          }
13742          dchancount = 0;
13743       }
13744       if ((dchancount > 1) && (span > -1))
13745          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
13746       else if (span > -1)
13747          ast_log(LOG_ERROR, "%d %s", span+1, s);
13748       else
13749          ast_log(LOG_ERROR, "%s", s);
13750    } else
13751       ast_log(LOG_ERROR, "%s", s);
13752 
13753    ast_mutex_lock(&pridebugfdlock);
13754 
13755    if (pridebugfd >= 0) {
13756       if (write(pridebugfd, s, strlen(s)) < 0) {
13757          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13758       }
13759    }
13760 
13761    ast_mutex_unlock(&pridebugfdlock);
13762 }

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

Definition at line 13681 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose, errno, pridebugfd, pridebugfdlock, and pris.

Referenced by load_module().

13682 {
13683    int x, y;
13684    int dchan = -1, span = -1, dchancount = 0;
13685 
13686    if (pri) {
13687       for (x = 0; x < NUM_SPANS; x++) {
13688          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13689             if (pris[x].pri.dchans[y])
13690                dchancount++;
13691 
13692             if (pris[x].pri.dchans[y] == pri)
13693                dchan = y;
13694          }
13695          if (dchan >= 0) {
13696             span = x;
13697             break;
13698          }
13699          dchancount = 0;
13700       }
13701       if (dchancount > 1 && (span > -1))
13702          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
13703       else if (span > -1)
13704          ast_verbose("%d %s", span+1, s);
13705       else
13706          ast_verbose("%s", s);
13707    } else
13708       ast_verbose("%s", s);
13709 
13710    ast_mutex_lock(&pridebugfdlock);
13711 
13712    if (pridebugfd >= 0) {
13713       if (write(pridebugfd, s, strlen(s)) < 0) {
13714          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13715       }
13716    }
13717 
13718    ast_mutex_unlock(&pridebugfdlock);
13719 }

static void dahdi_pri_update_span_devstate ( struct sig_pri_span pri  )  [static]

Definition at line 3173 of file chan_dahdi.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_changed(), sig_pri_span::congestion_devstate, HAVE_PRI_SERVICE_MESSAGES, sig_pri_chan::inalarm, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_chan::owner, dahdi_pvt::pri, sig_pri_span::pvts, sig_pri_chan::service_status, and sig_pri_span::span.

03174 {
03175    unsigned idx;
03176    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03177    unsigned in_use;     /* Number of B channels in use on the span. */
03178    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03179    enum ast_device_state new_state;
03180 
03181    /* Count the number of B channels and the number of B channels in use. */
03182    num_b_chans = 0;
03183    in_use = 0;
03184    in_alarm = 1;
03185    for (idx = pri->numchans; idx--;) {
03186       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03187          /* This is a B channel interface. */
03188          ++num_b_chans;
03189          if (pri->pvts[idx]->owner
03190 #if defined(HAVE_PRI_SERVICE_MESSAGES)
03191             /* Out-of-service B channels are "in-use". */
03192             || pri->pvts[idx]->service_status
03193 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
03194             ) {
03195             ++in_use;
03196          }
03197          if (!pri->pvts[idx]->inalarm) {
03198             /* There is a channel that is not in alarm. */
03199             in_alarm = 0;
03200          }
03201       }
03202    }
03203 
03204    /* Update the span congestion device state and report any change. */
03205    if (in_alarm) {
03206       new_state = AST_DEVICE_UNAVAILABLE;
03207    } else {
03208       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03209    }
03210    if (pri->congestion_devstate != new_state) {
03211       pri->congestion_devstate = new_state;
03212       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03213    }
03214 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03215    /* Update the span threshold device state and report any change. */
03216    if (in_alarm) {
03217       new_state = AST_DEVICE_UNAVAILABLE;
03218    } else if (!in_use) {
03219       new_state = AST_DEVICE_NOT_INUSE;
03220    } else if (!pri->user_busy_threshold) {
03221       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03222    } else {
03223       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03224          : AST_DEVICE_BUSY;
03225    }
03226    if (pri->threshold_devstate != new_state) {
03227       pri->threshold_devstate = new_state;
03228       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03229    }
03230 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03231 }

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

Definition at line 6491 of file chan_dahdi.c.

References ast_copy_string(), ast_debug, AST_OPTION_CC_AGENT_TYPE, AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, dahdi_sig_pri_lib_handles(), DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, dahdi_pvt::ignoredtmf, ast_channel::name, dahdi_pvt::sig, and ast_channel::tech_pvt.

06492 {
06493    char *cp;
06494    struct dahdi_pvt *p = chan->tech_pvt;
06495 
06496    /* all supported options require data */
06497    if (!data || (*datalen < 1)) {
06498       errno = EINVAL;
06499       return -1;
06500    }
06501 
06502    switch (option) {
06503    case AST_OPTION_DIGIT_DETECT:
06504       cp = (char *) data;
06505       *cp = p->ignoredtmf ? 0 : 1;
06506       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06507       break;
06508    case AST_OPTION_FAX_DETECT:
06509       cp = (char *) data;
06510       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06511       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06512       break;
06513    case AST_OPTION_CC_AGENT_TYPE:
06514 #if defined(HAVE_PRI)
06515 #if defined(HAVE_PRI_CCSS)
06516       if (dahdi_sig_pri_lib_handles(p->sig)) {
06517          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06518          break;
06519       }
06520 #endif   /* defined(HAVE_PRI_CCSS) */
06521 #endif   /* defined(HAVE_PRI) */
06522       return -1;
06523    default:
06524       return -1;
06525    }
06526 
06527    errno = 0;
06528 
06529    return 0;
06530 }

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

Definition at line 3659 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, dahdi_pvt::lock, and dahdi_pvt::owner.

Referenced by action_dahdidialoffhook().

03660 {
03661    for (;;) {
03662       if (p->owner) {
03663          if (ast_channel_trylock(p->owner)) {
03664             DEADLOCK_AVOIDANCE(&p->lock);
03665          } else {
03666             ast_queue_frame(p->owner, f);
03667             ast_channel_unlock(p->owner);
03668             break;
03669          }
03670       } else
03671          break;
03672    }
03673 }

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

Definition at line 4120 of file chan_dahdi.c.

References AST_ALAW.

04121 {
04122    return AST_ALAW(sample);
04123 }

static int dahdi_r2_answer ( struct dahdi_pvt p  )  [static]

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

03690 {
03691    int res = 0;
03692    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03693    * and does not has support for openr2_chan_answer_call_with_mode
03694    *  */
03695 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03696    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03697    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03698    if (!double_answer) {
03699       /* this still can result in double answer if the channel context
03700       * was configured that way */
03701       res = openr2_chan_answer_call(p->r2chan);
03702    } else if (wants_double_answer) {
03703       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03704    } else {
03705       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03706    }
03707 #else
03708    res = openr2_chan_answer_call(p->r2chan);
03709 #endif
03710    return res;
03711 }

static int dahdi_r2_cause_to_ast_cause ( openr2_call_disconnect_cause_t  cause  )  [static]

Definition at line 3930 of file chan_dahdi.c.

References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NOTDEFINED, and AST_CAUSE_UNREGISTERED.

Referenced by dahdi_r2_on_call_disconnect().

03931 {
03932    switch (cause) {
03933    case OR2_CAUSE_BUSY_NUMBER:
03934       return AST_CAUSE_BUSY;
03935    case OR2_CAUSE_NETWORK_CONGESTION:
03936       return AST_CAUSE_CONGESTION;
03937    case OR2_CAUSE_OUT_OF_ORDER:
03938       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
03939    case OR2_CAUSE_UNALLOCATED_NUMBER:
03940       return AST_CAUSE_UNREGISTERED;
03941    case OR2_CAUSE_NO_ANSWER:
03942       return AST_CAUSE_NO_ANSWER;
03943    case OR2_CAUSE_NORMAL_CLEARING:
03944       return AST_CAUSE_NORMAL_CLEARING;
03945    case OR2_CAUSE_UNSPECIFIED:
03946    default:
03947       return AST_CAUSE_NOTDEFINED;
03948    }
03949 }

static void dahdi_r2_destroy_links ( void   )  [static]

Definition at line 11765 of file chan_dahdi.c.

References ast_free, AST_PTHREADT_NULL, r2links, and r2links_count.

Referenced by __unload_module(), and dahdi_restart().

11766 {
11767    int i = 0;
11768    if (!r2links) {
11769       return;
11770    }
11771    for (; i < r2links_count; i++) {
11772       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11773          pthread_cancel(r2links[i]->r2master);
11774          pthread_join(r2links[i]->r2master, NULL);
11775          openr2_context_delete(r2links[i]->protocol_context);
11776       }
11777       ast_free(r2links[i]);
11778    }
11779    ast_free(r2links);
11780    r2links = NULL;
11781    r2links_count = 0;
11782 }

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

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

03799 {
03800    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03801       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03802          p->channel, openr2_proto_get_disconnect_string(cause));
03803       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03804       openr2_chan_set_idle(p->r2chan);
03805       ast_mutex_lock(&p->lock);
03806       p->mfcr2call = 0;
03807       ast_mutex_unlock(&p->lock);
03808    }
03809 }

static openr2_calling_party_category_t dahdi_r2_get_channel_category ( struct ast_channel c  )  [static]

Definition at line 3716 of file chan_dahdi.c.

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

Referenced by dahdi_call().

03717 {
03718    openr2_calling_party_category_t cat;
03719    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03720    struct dahdi_pvt *p = c->tech_pvt;
03721    if (ast_strlen_zero(catstr)) {
03722       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03723             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03724       return p->mfcr2_category;
03725    }
03726    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03727       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03728             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03729       return p->mfcr2_category;
03730    }
03731    ast_debug(1, "Using category %s\n", catstr);
03732    return cat;
03733 }

static struct dahdi_mfcr2* dahdi_r2_get_link ( void   )  [static]

Definition at line 11785 of file chan_dahdi.c.

References ast_calloc, ast_free, ast_log(), AST_PTHREADT_NULL, ast_realloc, LOG_DEBUG, LOG_ERROR, dahdi_mfcr2::monitored_count, R2_LINK_CAPACITY, r2links, r2links_count, and dahdi_mfcr2::r2master.

11786 {
11787    struct dahdi_mfcr2 *new_r2link = NULL;
11788    struct dahdi_mfcr2 **new_r2links = NULL;
11789    /* this function is called just when starting up and no monitor threads have been launched,
11790       no need to lock monitored_count member */
11791    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
11792       new_r2link = ast_calloc(1, sizeof(**r2links));
11793       if (!new_r2link) {
11794          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11795          return NULL;
11796       }
11797       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
11798       if (!new_r2links) {
11799          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11800          ast_free(new_r2link);
11801          return NULL;
11802       }
11803       r2links = new_r2links;
11804       new_r2link->r2master = AST_PTHREADT_NULL;
11805       r2links[r2links_count] = new_r2link;
11806       r2links_count++;
11807       ast_log(LOG_DEBUG, "Created new R2 link!\n");
11808    }
11809    return r2links[r2links_count - 1];
11810 }

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

Definition at line 4125 of file chan_dahdi.c.

References AST_LIN2A.

04126 {
04127    return AST_LIN2A(sample);
04128 }

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

Definition at line 4084 of file chan_dahdi.c.

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

04085 {
04086    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04087    p->cid_num[p->mfcr2_ani_index] = digit;
04088    p->cid_name[p->mfcr2_ani_index] = digit;
04089    p->mfcr2_ani_index++;
04090    p->cid_num[p->mfcr2_ani_index] = 0;
04091    p->cid_name[p->mfcr2_ani_index] = 0;
04092 }

static void dahdi_r2_on_billing_pulse_received ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4094 of file chan_dahdi.c.

References ast_verbose.

04095 {
04096    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04097 }

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

Definition at line 3876 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_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.

03877 {
03878    struct dahdi_pvt *p = NULL;
03879    struct ast_channel *c = NULL;
03880    p = openr2_chan_get_client_data(r2chan);
03881    dahdi_enable_ec(p);
03882    p->mfcr2_call_accepted = 1;
03883    /* if it's an incoming call ... */
03884    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03885       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03886       /* If accept on offer is not set, it means at this point the PBX thread is already
03887          launched (was launched in the 'on call offered' handler) and therefore this callback
03888          is being executed already in the PBX thread rather than the monitor thread, don't launch
03889          any other thread, just disable the openr2 reading and answer the call if needed */
03890       if (!p->mfcr2_accept_on_offer) {
03891          openr2_chan_disable_read(r2chan);
03892          if (p->mfcr2_answer_pending) {
03893             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03894             dahdi_r2_answer(p);
03895          }
03896          return;
03897       }
03898       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03899       if (c) {
03900          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
03901             library to forget about it */
03902          openr2_chan_disable_read(r2chan);
03903          return;
03904       }
03905       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03906       /* failed to create the channel, bail out and report it as an out of order line */
03907       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03908       return;
03909    }
03910    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
03911    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03912    p->subs[SUB_REAL].needringing = 1;
03913    p->dialing = 0;
03914    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
03915    openr2_chan_disable_read(r2chan);
03916 }

static void dahdi_r2_on_call_answered ( openr2_chan_t *  r2chan  )  [static]

Definition at line 3918 of file chan_dahdi.c.

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

03919 {
03920    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03921    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03922    p->subs[SUB_REAL].needanswer = 1;
03923 }

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

Definition at line 3951 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, ast_mutex_lock, ast_mutex_unlock, ast_queue_hangup_with_cause(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_verbose, dahdi_r2_cause_to_ast_cause(), dahdi_r2_disconnect_call(), dahdi_pvt::lock, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_pvt::owner, SUB_REAL, and dahdi_pvt::subs.

03952 {
03953    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03954    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
03955    ast_mutex_lock(&p->lock);
03956    if (!p->owner) {
03957       ast_mutex_unlock(&p->lock);
03958       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
03959       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
03960       return;
03961    }
03962    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
03963       be done in dahdi_hangup */
03964    if (p->owner->_state == AST_STATE_UP) {
03965       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03966       ast_mutex_unlock(&p->lock);
03967    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
03968       /* being the forward side we must report what happened to the call to whoever requested it */
03969       switch (cause) {
03970       case OR2_CAUSE_BUSY_NUMBER:
03971          p->subs[SUB_REAL].needbusy = 1;
03972          break;
03973       case OR2_CAUSE_NETWORK_CONGESTION:
03974       case OR2_CAUSE_OUT_OF_ORDER:
03975       case OR2_CAUSE_UNALLOCATED_NUMBER:
03976       case OR2_CAUSE_NO_ANSWER:
03977       case OR2_CAUSE_UNSPECIFIED:
03978       case OR2_CAUSE_NORMAL_CLEARING:
03979          p->subs[SUB_REAL].needcongestion = 1;
03980          break;
03981       default:
03982          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03983       }
03984       ast_mutex_unlock(&p->lock);
03985    } else {
03986       ast_mutex_unlock(&p->lock);
03987       /* being the backward side and not UP yet, we only need to request hangup */
03988       /* TODO: what about doing this same thing when were AST_STATE_UP? */
03989       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
03990    }
03991 }

static void dahdi_r2_on_call_end ( openr2_chan_t *  r2chan  )  [static]

Definition at line 3866 of file chan_dahdi.c.

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

03867 {
03868    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03869    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03870    ast_mutex_lock(&p->lock);
03871    p->mfcr2call = 0;
03872    ast_mutex_unlock(&p->lock);
03873 }

static void dahdi_r2_on_call_init ( openr2_chan_t *  r2chan  )  [static]

Definition at line 3735 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::cid_subaddr, dahdi_pvt::exten, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, dahdi_pvt::mfcr2call, and dahdi_pvt::rdnis.

03736 {
03737    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03738    ast_mutex_lock(&p->lock);
03739    if (p->mfcr2call) {
03740       ast_mutex_unlock(&p->lock);
03741       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03742          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03743          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03744          the other end will see our seize as a forced release and drop the call, we will see an invalid
03745          pattern that will be seen and treated as protocol error. */
03746       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03747       return;
03748    }
03749    p->mfcr2call = 1;
03750    /* better safe than sorry ... */
03751    p->cid_name[0] = '\0';
03752    p->cid_num[0] = '\0';
03753    p->cid_subaddr[0] = '\0';
03754    p->rdnis[0] = '\0';
03755    p->exten[0] = '\0';
03756    p->mfcr2_ani_index = '\0';
03757    p->mfcr2_dnis_index = '\0';
03758    p->mfcr2_dnis_matched = 0;
03759    p->mfcr2_answer_pending = 0;
03760    p->mfcr2_call_accepted = 0;
03761    ast_mutex_unlock(&p->lock);
03762    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03763 }

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 3811 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_NOTICE, LOG_WARNING, 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.

03812 {
03813    struct dahdi_pvt *p;
03814    struct ast_channel *c;
03815    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03816          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03817          openr2_proto_get_category_string(category));
03818    p = openr2_chan_get_client_data(r2chan);
03819    /* if collect calls are not allowed and this is a collect call, reject it! */
03820    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03821       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03822       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03823       return;
03824    }
03825    ast_mutex_lock(&p->lock);
03826    p->mfcr2_recvd_category = category;
03827    /* if we're not supposed to use CID, clear whatever we have */
03828    if (!p->use_callerid) {
03829       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03830       p->cid_num[0] = 0;
03831       p->cid_name[0] = 0;
03832    }
03833    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03834    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03835       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03836       p->exten[0] = 's';
03837       p->exten[1] = 0;
03838    }
03839    ast_mutex_unlock(&p->lock);
03840    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03841       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03842             p->channel, p->exten, p->context);
03843       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03844       return;
03845    }
03846    if (!p->mfcr2_accept_on_offer) {
03847       /* The user wants us to start the PBX thread right away without accepting the call first */
03848       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03849       if (c) {
03850          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03851             the call or reject it and detect the tone off condition of the other end, all of this
03852             will be done in the PBX thread now */
03853          return;
03854       }
03855       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03856       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03857    } else if (p->mfcr2_charge_calls) {
03858       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03859       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03860    } else {
03861       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03862       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03863    }
03864 }

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

Definition at line 3925 of file chan_dahdi.c.

03926 {
03927    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
03928 }

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

References CHAN_TAG, and dahdi_r2_write_log().

04053 {
04054 #define CHAN_TAG "Chan "
04055    char logmsg[256];
04056    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04057    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04058    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04059    dahdi_r2_write_log(level, completemsg);
04060 }

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

References CONTEXT_TAG, and dahdi_r2_write_log().

04040 {
04041 #define CONTEXT_TAG "Context - "
04042    char logmsg[256];
04043    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04044    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04045    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04046    dahdi_r2_write_log(level, completemsg);
04047 #undef CONTEXT_TAG
04048 }

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

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

04063 {
04064    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04065    /* if 'immediate' is set, let's stop requesting DNIS */
04066    if (p->immediate) {
04067       return 0;
04068    }
04069    p->exten[p->mfcr2_dnis_index] = digit;
04070    p->rdnis[p->mfcr2_dnis_index] = digit;
04071    p->mfcr2_dnis_index++;
04072    p->exten[p->mfcr2_dnis_index] = 0;
04073    p->rdnis[p->mfcr2_dnis_index] = 0;
04074    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04075    if ((p->mfcr2_dnis_matched ||
04076        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04077        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04078       return 0;
04079    }
04080    /* otherwise keep going */
04081    return 1;
04082 }

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

Definition at line 3765 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, and dahdi_pvt::lock.

03766 {
03767    int res;
03768    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03769    ast_mutex_lock(&p->lock);
03770    p->inalarm = alarm ? 1 : 0;
03771    if (p->inalarm) {
03772       res = get_alarms(p);
03773       handle_alarms(p, res);
03774    } else {
03775       handle_clear_alarms(p);
03776    }
03777    ast_mutex_unlock(&p->lock);
03778 }

static void dahdi_r2_on_line_blocked ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4019 of file chan_dahdi.c.

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

04020 {
04021    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04022    ast_mutex_lock(&p->lock);
04023    p->remotelyblocked = 1;
04024    ast_mutex_unlock(&p->lock);
04025    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04026 }

static void dahdi_r2_on_line_idle ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4028 of file chan_dahdi.c.

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

04029 {
04030    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04031    ast_mutex_lock(&p->lock);
04032    p->remotelyblocked = 0;
04033    ast_mutex_unlock(&p->lock);
04034    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04035 }

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

Definition at line 3780 of file chan_dahdi.c.

References ast_log(), and LOG_ERROR.

03781 {
03782    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03783 }

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

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

03786 {
03787    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03788    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03789    if (p->owner) {
03790       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03791       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03792    }
03793    ast_mutex_lock(&p->lock);
03794    p->mfcr2call = 0;
03795    ast_mutex_unlock(&p->lock);
03796 }

static int dahdi_r2_set_context ( struct dahdi_mfcr2 r2_link,
const struct dahdi_chan_conf conf 
) [static]

Definition at line 11812 of file chan_dahdi.c.

References ast_config_AST_LOG_DIR, ast_log(), ast_strlen_zero(), dahdi_mfcr2_conf::double_answer, dahdi_mfcr2_conf::get_ani_first, dahdi_mfcr2_conf::immediate_accept, LOG_ERROR, dahdi_mfcr2_conf::logdir, dahdi_mfcr2_conf::loglevel, dahdi_mfcr2_conf::max_ani, dahdi_mfcr2_conf::max_dnis, dahdi_mfcr2_conf::metering_pulse_timeout, dahdi_mfcr2_conf::mfback_timeout, dahdi_chan_conf::mfcr2, dahdi_mfcr2::monitored_count, dahdi_mfcr2::protocol_context, dahdi_mfcr2_conf::r2proto_file, and dahdi_mfcr2_conf::variant.

11813 {
11814    char tmplogdir[] = "/tmp";
11815    char logdir[OR2_MAX_PATH];
11816    int threshold = 0;
11817    int snres = 0;
11818    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
11819          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
11820          conf->mfcr2.max_dnis);
11821    if (!r2_link->protocol_context) {
11822       return -1;
11823    }
11824    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
11825    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
11826 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
11827    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
11828 #endif
11829    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
11830    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
11831    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
11832    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
11833    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
11834    if (ast_strlen_zero(conf->mfcr2.logdir)) {
11835       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11836          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11837       }
11838    } else {
11839       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
11840       if (snres >= sizeof(logdir)) {
11841          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
11842          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11843             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11844          }
11845       } else {
11846          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
11847             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
11848          }
11849       }
11850    }
11851    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
11852       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
11853          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
11854       }
11855    }
11856    r2_link->monitored_count = 0;
11857    return 0;
11858 }

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

Definition at line 3993 of file chan_dahdi.c.

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

Referenced by dahdi_r2_on_chan_log(), and dahdi_r2_on_context_log().

03994 {
03995    switch (level) {
03996    case OR2_LOG_NOTICE:
03997       ast_verbose("%s", logmessage);
03998       break;
03999    case OR2_LOG_WARNING:
04000       ast_log(LOG_WARNING, "%s", logmessage);
04001       break;
04002    case OR2_LOG_ERROR:
04003       ast_log(LOG_ERROR, "%s", logmessage);
04004       break;
04005    case OR2_LOG_STACK_TRACE:
04006    case OR2_LOG_MF_TRACE:
04007    case OR2_LOG_CAS_TRACE:
04008    case OR2_LOG_DEBUG:
04009    case OR2_LOG_EX_DEBUG:
04010       ast_log(LOG_DEBUG, "%s", logmessage);
04011       break;
04012    default:
04013       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04014       ast_log(LOG_DEBUG, "%s", logmessage);
04015       break;
04016    }
04017 }

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

Definition at line 8640 of file chan_dahdi.c.

References __dahdi_exception(), ast_channel::_state, analog_exception(), analog_handle_dtmf(), analog_lib_handles(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_dsp_get_tcount(), ast_dsp_get_tstate(), ast_dsp_process(), ast_dsp_set_features(), ast_dsp_was_muted(), 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_log(), ast_mutex_trylock, ast_mutex_unlock, ast_null_frame, ast_queue_frame(), ast_set_flag, ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, CHECK_BLOCKING, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, ast_frame_subclass::codec, dahdi_callwait(), dahdi_confmute(), dahdi_get_index, dahdi_handle_dtmf(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), dahdi_sig_pri_lib_handles(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::dsp, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_RINGING, errno, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, ast_frame::mallocd, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_progress, mute, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::outgoing, sig_pri_span::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), dahdi_pvt::ringt, ast_frame::samples, send_callerid(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, dahdi_pvt::waitfordialtone, and dahdi_pvt::waitingfordt.

08641 {
08642    struct dahdi_pvt *p = ast->tech_pvt;
08643    int res;
08644    int idx;
08645    void *readbuf;
08646    struct ast_frame *f;
08647 
08648    while (ast_mutex_trylock(&p->lock)) {
08649       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08650    }
08651 
08652    idx = dahdi_get_index(ast, p, 0);
08653 
08654    /* Hang up if we don't really exist */
08655    if (idx < 0)   {
08656       ast_log(LOG_WARNING, "We don't exist?\n");
08657       ast_mutex_unlock(&p->lock);
08658       return NULL;
08659    }
08660 
08661    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08662       ast_mutex_unlock(&p->lock);
08663       return NULL;
08664    }
08665 
08666    p->subs[idx].f.frametype = AST_FRAME_NULL;
08667    p->subs[idx].f.datalen = 0;
08668    p->subs[idx].f.samples = 0;
08669    p->subs[idx].f.mallocd = 0;
08670    p->subs[idx].f.offset = 0;
08671    p->subs[idx].f.subclass.integer = 0;
08672    p->subs[idx].f.delivery = ast_tv(0,0);
08673    p->subs[idx].f.src = "dahdi_read";
08674    p->subs[idx].f.data.ptr = NULL;
08675 
08676    /* make sure it sends initial key state as first frame */
08677    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08678    {
08679       struct dahdi_params ps;
08680 
08681       memset(&ps, 0, sizeof(ps));
08682       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08683          ast_mutex_unlock(&p->lock);
08684          return NULL;
08685       }
08686       p->firstradio = 1;
08687       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08688       if (ps.rxisoffhook)
08689       {
08690          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08691       }
08692       else
08693       {
08694          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08695       }
08696       ast_mutex_unlock(&p->lock);
08697       return &p->subs[idx].f;
08698    }
08699    if (p->ringt > 0) {
08700       if (!(--p->ringt)) {
08701          ast_mutex_unlock(&p->lock);
08702          return NULL;
08703       }
08704    }
08705 
08706 #ifdef HAVE_OPENR2
08707    if (p->mfcr2) {
08708       openr2_chan_process_event(p->r2chan);
08709       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08710          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08711          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
08712           * now enqueue a progress frame to bridge the media up */
08713          if (p->mfcr2_call_accepted &&
08714              !p->mfcr2_progress && 
08715              ast->_state == AST_STATE_RINGING) {
08716             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08717             ast_queue_frame(p->owner, &f);
08718             p->mfcr2_progress = 1;
08719          }
08720       }
08721    }
08722 #endif
08723 
08724    if (p->subs[idx].needringing) {
08725       /* Send ringing frame if requested */
08726       p->subs[idx].needringing = 0;
08727       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08728       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08729       ast_setstate(ast, AST_STATE_RINGING);
08730       ast_mutex_unlock(&p->lock);
08731       return &p->subs[idx].f;
08732    }
08733 
08734    if (p->subs[idx].needbusy) {
08735       /* Send busy frame if requested */
08736       p->subs[idx].needbusy = 0;
08737       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08738       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08739       ast_mutex_unlock(&p->lock);
08740       return &p->subs[idx].f;
08741    }
08742 
08743    if (p->subs[idx].needcongestion) {
08744       /* Send congestion frame if requested */
08745       p->subs[idx].needcongestion = 0;
08746       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08747       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08748       ast_mutex_unlock(&p->lock);
08749       return &p->subs[idx].f;
08750    }
08751 
08752    if (p->subs[idx].needanswer) {
08753       /* Send answer frame if requested */
08754       p->subs[idx].needanswer = 0;
08755       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08756       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08757       ast_mutex_unlock(&p->lock);
08758       return &p->subs[idx].f;
08759    }
08760 #ifdef HAVE_OPENR2
08761    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08762       /* openr2 took care of reading and handling any event
08763         (needanswer, needbusy etc), if we continue we will read()
08764         twice, lets just return a null frame. This should only
08765         happen when openr2 is dialing out */
08766       ast_mutex_unlock(&p->lock);
08767       return &ast_null_frame;
08768    }
08769 #endif
08770 
08771    if (p->subs[idx].needflash) {
08772       /* Send answer frame if requested */
08773       p->subs[idx].needflash = 0;
08774       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08775       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08776       ast_mutex_unlock(&p->lock);
08777       return &p->subs[idx].f;
08778    }
08779 
08780    if (p->subs[idx].needhold) {
08781       /* Send answer frame if requested */
08782       p->subs[idx].needhold = 0;
08783       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08784       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08785       ast_mutex_unlock(&p->lock);
08786       ast_debug(1, "Sending hold on '%s'\n", ast->name);
08787       return &p->subs[idx].f;
08788    }
08789 
08790    if (p->subs[idx].needunhold) {
08791       /* Send answer frame if requested */
08792       p->subs[idx].needunhold = 0;
08793       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08794       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08795       ast_mutex_unlock(&p->lock);
08796       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08797       return &p->subs[idx].f;
08798    }
08799 
08800    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08801       if (!p->subs[idx].linear) {
08802          p->subs[idx].linear = 1;
08803          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08804          if (res)
08805             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08806       }
08807    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08808       (ast->rawreadformat == AST_FORMAT_ALAW)) {
08809       if (p->subs[idx].linear) {
08810          p->subs[idx].linear = 0;
08811          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08812          if (res)
08813             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08814       }
08815    } else {
08816       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08817       ast_mutex_unlock(&p->lock);
08818       return NULL;
08819    }
08820    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08821    CHECK_BLOCKING(ast);
08822    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08823    ast_clear_flag(ast, AST_FLAG_BLOCKING);
08824    /* Check for hangup */
08825    if (res < 0) {
08826       f = NULL;
08827       if (res == -1) {
08828          if (errno == EAGAIN) {
08829             /* Return "NULL" frame if there is nobody there */
08830             ast_mutex_unlock(&p->lock);
08831             return &p->subs[idx].f;
08832          } else if (errno == ELAST) {
08833             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08834                struct analog_pvt *analog_p = p->sig_pvt;
08835                f = analog_exception(analog_p, ast);
08836             } else {
08837                f = __dahdi_exception(ast);
08838             }
08839          } else
08840             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08841       }
08842       ast_mutex_unlock(&p->lock);
08843       return f;
08844    }
08845    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
08846       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08847       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08848          struct analog_pvt *analog_p = p->sig_pvt;
08849          f = analog_exception(analog_p, ast);
08850       } else {
08851          f = __dahdi_exception(ast);
08852       }
08853       ast_mutex_unlock(&p->lock);
08854       return f;
08855    }
08856    if (p->tdd) { /* if in TDD mode, see if we receive that */
08857       int c;
08858 
08859       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
08860       if (c < 0) {
08861          ast_debug(1,"tdd_feed failed\n");
08862          ast_mutex_unlock(&p->lock);
08863          return NULL;
08864       }
08865       if (c) { /* if a char to return */
08866          p->subs[idx].f.subclass.integer = 0;
08867          p->subs[idx].f.frametype = AST_FRAME_TEXT;
08868          p->subs[idx].f.mallocd = 0;
08869          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08870          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
08871          p->subs[idx].f.datalen = 1;
08872          *((char *) p->subs[idx].f.data.ptr) = c;
08873          ast_mutex_unlock(&p->lock);
08874          return &p->subs[idx].f;
08875       }
08876    }
08877    if (idx == SUB_REAL) {
08878       /* Ensure the CW timers decrement only on a single subchannel */
08879       if (p->cidcwexpire) {
08880          if (!--p->cidcwexpire) {
08881             /* Expired CID/CW */
08882             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
08883             restore_conference(p);
08884          }
08885       }
08886       if (p->cid_suppress_expire) {
08887          --p->cid_suppress_expire;
08888       }
08889       if (p->callwaitingrepeat) {
08890          if (!--p->callwaitingrepeat) {
08891             /* Expired, Repeat callwaiting tone */
08892             ++p->callwaitrings;
08893             dahdi_callwait(ast);
08894          }
08895       }
08896    }
08897    if (p->subs[idx].linear) {
08898       p->subs[idx].f.datalen = READ_SIZE * 2;
08899    } else
08900       p->subs[idx].f.datalen = READ_SIZE;
08901 
08902    /* Handle CallerID Transmission */
08903    if ((p->owner == ast) && p->cidspill) {
08904       send_callerid(p);
08905    }
08906 
08907    p->subs[idx].f.frametype = AST_FRAME_VOICE;
08908    p->subs[idx].f.subclass.codec = ast->rawreadformat;
08909    p->subs[idx].f.samples = READ_SIZE;
08910    p->subs[idx].f.mallocd = 0;
08911    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08912    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
08913 #if 0
08914    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
08915 #endif
08916    if (p->dialing ||  p->radio || /* Transmitting something */
08917       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
08918       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
08919       ) {
08920       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
08921          don't send anything */
08922       p->subs[idx].f.frametype = AST_FRAME_NULL;
08923       p->subs[idx].f.subclass.integer = 0;
08924       p->subs[idx].f.samples = 0;
08925       p->subs[idx].f.mallocd = 0;
08926       p->subs[idx].f.offset = 0;
08927       p->subs[idx].f.data.ptr = NULL;
08928       p->subs[idx].f.datalen= 0;
08929    }
08930    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
08931       /* Perform busy detection etc on the dahdi line */
08932       int mute;
08933 
08934       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
08935 
08936       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
08937       mute = ast_dsp_was_muted(p->dsp);
08938       if (p->muting != mute) {
08939          p->muting = mute;
08940          dahdi_confmute(p, mute);
08941       }
08942 
08943       if (f) {
08944          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
08945             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
08946                /* Treat this as a "hangup" instead of a "busy" on the assumption that
08947                   a busy */
08948                f = NULL;
08949             }
08950          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
08951             || f->frametype == AST_FRAME_DTMF_END) {
08952 #ifdef HAVE_PRI
08953             if (dahdi_sig_pri_lib_handles(p->sig)
08954                && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
08955                && p->pri
08956                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
08957                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
08958                /* Don't accept in-band DTMF when in overlap dial mode */
08959                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
08960                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
08961                   f->subclass.integer, f->subclass.integer, ast->name);
08962 
08963                f->frametype = AST_FRAME_NULL;
08964                f->subclass.integer = 0;
08965             }
08966 #endif
08967             /* DSP clears us of being pulse */
08968             p->pulsedial = 0;
08969          } else if (p->waitingfordt.tv_sec) {
08970             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
08971                p->waitingfordt.tv_sec = 0;
08972                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
08973                f=NULL;
08974             } else if (f->frametype == AST_FRAME_VOICE) {
08975                f->frametype = AST_FRAME_NULL;
08976                f->subclass.integer = 0;
08977                if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
08978                   p->waitingfordt.tv_sec = 0;
08979                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
08980                   ast_dsp_set_features(p->dsp, p->dsp_features);
08981                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
08982                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
08983                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08984                      if (res < 0) {
08985                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
08986                         p->dop.dialstr[0] = '\0';
08987                         ast_mutex_unlock(&p->lock);
08988                         return NULL;
08989                      } else {
08990                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
08991                         p->dialing = 1;
08992                         p->dop.dialstr[0] = '\0';
08993                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
08994                         ast_setstate(ast, AST_STATE_DIALING);
08995                      }
08996                   }
08997                }
08998             }
08999          }
09000       }
09001    } else
09002       f = &p->subs[idx].f;
09003 
09004    if (f) {
09005       switch (f->frametype) {
09006       case AST_FRAME_DTMF_BEGIN:
09007       case AST_FRAME_DTMF_END:
09008          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09009             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09010          } else {
09011             dahdi_handle_dtmf(ast, idx, &f);
09012          }
09013          break;
09014       case AST_FRAME_VOICE:
09015          if (p->cidspill || p->cid_suppress_expire) {
09016             /* We are/were sending a caller id spill.  Suppress any echo. */
09017             p->subs[idx].f.frametype = AST_FRAME_NULL;
09018             p->subs[idx].f.subclass.integer = 0;
09019             p->subs[idx].f.samples = 0;
09020             p->subs[idx].f.mallocd = 0;
09021             p->subs[idx].f.offset = 0;
09022             p->subs[idx].f.data.ptr = NULL;
09023             p->subs[idx].f.datalen= 0;
09024          }
09025          break;
09026       default:
09027          break;
09028       }
09029    }
09030 
09031    /* If we have a fake_event, trigger exception to handle it */
09032    if (p->fake_event)
09033       ast_set_flag(ast, AST_FLAG_EXCEPTION);
09034 
09035    ast_mutex_unlock(&p->lock);
09036    return f;
09037 }

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

Definition at line 13261 of file chan_dahdi.c.

References analog_lib_handles(), analog_request(), ast_atomic_fetchadd_int(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, AST_TRANS_CAP_DIGITAL, available(), dahdi_starting_point::backwards, dahdi_starting_point::cadance, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_starting_point::channelmatch, dahdi_pvt::confirmanswer, dahdi_new(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_pvt::dialstring, dahdi_pvt::distinctivering, dahdi_pvt::dnid, duplicate_pseudo(), dahdi_starting_point::groupmatch, ifend, iflist, iflock, is_group_or_channel_match(), ast_channel::linkedid, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2call, dahdi_pvt::next, dahdi_pvt::oprmode, dahdi_starting_point::opt, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_pvt::radio, restart_monitor(), round_robin, dahdi_starting_point::roundrobin, dahdi_starting_point::rr_starting_point, dahdi_pvt::sig, SIG_PRI_DEFLAW, sig_pri_extract_called_num_subaddr(), SIG_PRI_LIB_HANDLE_CASES, sig_pri_request(), dahdi_pvt::sig_pvt, SIG_SS7, SIG_SS7_DEFLAW, sig_ss7_request(), dahdi_starting_point::span, SUB_CALLWAIT, and SUB_REAL.

13262 {
13263    int callwait = 0;
13264    struct dahdi_pvt *p;
13265    struct ast_channel *tmp = NULL;
13266    struct dahdi_pvt *exitpvt;
13267    int channelmatched = 0;
13268    int groupmatched = 0;
13269    int transcapdigital = 0;
13270    struct dahdi_starting_point start;
13271 
13272    ast_mutex_lock(&iflock);
13273    p = determine_starting_point(data, &start);
13274    if (!p) {
13275       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13276       ast_mutex_unlock(&iflock);
13277       return NULL;
13278    }
13279 
13280    /* Search for an unowned channel */
13281    exitpvt = p;
13282    while (p && !tmp) {
13283       if (start.roundrobin)
13284          round_robin[start.rr_starting_point] = p;
13285 
13286       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13287          && available(&p, channelmatched)) {
13288          ast_debug(1, "Using channel %d\n", p->channel);
13289 
13290          callwait = (p->owner != NULL);
13291 #ifdef HAVE_OPENR2
13292          if (p->mfcr2) {
13293             ast_mutex_lock(&p->lock);
13294             if (p->mfcr2call) {
13295                ast_mutex_unlock(&p->lock);
13296                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13297                goto next;
13298             }
13299             p->mfcr2call = 1;
13300             ast_mutex_unlock(&p->lock);
13301          }
13302 #endif
13303          if (p->channel == CHAN_PSEUDO) {
13304             p = duplicate_pseudo(p);
13305             if (!p) {
13306                break;
13307             }
13308          }
13309 
13310          /* Make special notes */
13311          switch (start.opt) {
13312          case '\0':
13313             /* No option present. */
13314             break;
13315          case 'c':
13316             /* Confirm answer */
13317             p->confirmanswer = 1;
13318             break;
13319          case 'r':
13320             /* Distinctive ring */
13321             p->distinctivering = start.cadance;
13322             break;
13323          case 'd':
13324             /* If this is an ISDN call, make it digital */
13325             transcapdigital = AST_TRANS_CAP_DIGITAL;
13326             break;
13327          default:
13328             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13329             break;
13330          }
13331 
13332          p->outgoing = 1;
13333          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13334             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13335 #ifdef HAVE_PRI
13336          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13337             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13338                sizeof(p->dnid));
13339             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13340 #endif
13341 #if defined(HAVE_SS7)
13342          } else if (p->sig == SIG_SS7) {
13343             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13344 #endif   /* defined(HAVE_SS7) */
13345          } else {
13346             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13347          }
13348          if (!tmp) {
13349             p->outgoing = 0;
13350 #if defined(HAVE_PRI)
13351 #if defined(HAVE_PRI_CALL_WAITING)
13352             switch (p->sig) {
13353             case SIG_PRI_LIB_HANDLE_CASES:
13354                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13355                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13356                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13357                }
13358                break;
13359             default:
13360                break;
13361             }
13362 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13363 #endif   /* defined(HAVE_PRI) */
13364          } else {
13365             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13366          }
13367          break;
13368       }
13369 #ifdef HAVE_OPENR2
13370 next:
13371 #endif
13372       if (start.backwards) {
13373          p = p->prev;
13374          if (!p)
13375             p = ifend;
13376       } else {
13377          p = p->next;
13378          if (!p)
13379             p = iflist;
13380       }
13381       /* stop when you roll to the one that we started from */
13382       if (p == exitpvt)
13383          break;
13384    }
13385    ast_mutex_unlock(&iflock);
13386    restart_monitor();
13387    if (cause && !tmp) {
13388       if (callwait || channelmatched) {
13389          *cause = AST_CAUSE_BUSY;
13390       } else if (groupmatched) {
13391          *cause = AST_CAUSE_CONGESTION;
13392       } else {
13393          /*
13394           * We did not match any channel requested.
13395           * Dialplan error requesting non-existant channel?
13396           */
13397       }
13398    }
13399 
13400    return tmp;
13401 }

static int dahdi_restart ( void   )  [static]

Definition at line 14626 of file chan_dahdi.c.

References ast_debug, ast_mutex_lock, AST_PTHREADT_NULL, ast_verb, dahdi_r2_destroy_links(), dahdi_softhangup_all(), sig_pri_span::master, dahdi_pri::pri, dahdi_pvt::pri, pris, and restart_lock.

Referenced by action_dahdirestart(), and dahdi_restart_cmd().

14627 {
14628 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14629    int i, j;
14630 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14631    int cancel_code;
14632    struct dahdi_pvt *p;
14633 
14634    ast_mutex_lock(&restart_lock);
14635    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14636    dahdi_softhangup_all();
14637    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14638 #ifdef HAVE_OPENR2
14639    dahdi_r2_destroy_links();
14640 #endif
14641 
14642 #if defined(HAVE_PRI)
14643    for (i = 0; i < NUM_SPANS; i++) {
14644       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14645          cancel_code = pthread_cancel(pris[i].pri.master);
14646          pthread_kill(pris[i].pri.master, SIGURG);
14647          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].pri.master, cancel_code);
14648          pthread_join(pris[i].pri.master, NULL);
14649          ast_debug(4, "Joined thread of span %d\n", i);
14650       }
14651    }
14652 #endif
14653 
14654 #if defined(HAVE_SS7)
14655    for (i = 0; i < NUM_SPANS; i++) {
14656       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14657          cancel_code = pthread_cancel(linksets[i].ss7.master);
14658          pthread_kill(linksets[i].ss7.master, SIGURG);
14659          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].ss7.master, cancel_code);
14660          pthread_join(linksets[i].ss7.master, NULL);
14661          ast_debug(4, "Joined thread of span %d\n", i);
14662       }
14663    }
14664 #endif   /* defined(HAVE_SS7) */
14665 
14666    ast_mutex_lock(&monlock);
14667    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14668       cancel_code = pthread_cancel(monitor_thread);
14669       pthread_kill(monitor_thread, SIGURG);
14670       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14671       pthread_join(monitor_thread, NULL);
14672       ast_debug(4, "Joined monitor thread\n");
14673    }
14674    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
14675 
14676    ast_mutex_lock(&ss_thread_lock);
14677    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
14678       int x = DAHDI_FLASH;
14679       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14680 
14681       ast_mutex_lock(&iflock);
14682       for (p = iflist; p; p = p->next) {
14683          if (p->owner) {
14684             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
14685             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14686          }
14687       }
14688       ast_mutex_unlock(&iflock);
14689       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14690    }
14691 
14692    /* ensure any created channels before monitor threads were stopped are hungup */
14693    dahdi_softhangup_all();
14694    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14695    destroy_all_channels();
14696    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14697 
14698    ast_mutex_unlock(&monlock);
14699 
14700 #ifdef HAVE_PRI
14701    for (i = 0; i < NUM_SPANS; i++) {
14702       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14703          dahdi_close_pri_fd(&(pris[i]), j);
14704    }
14705 
14706    memset(pris, 0, sizeof(pris));
14707    for (i = 0; i < NUM_SPANS; i++) {
14708       sig_pri_init_pri(&pris[i].pri);
14709    }
14710    pri_set_error(dahdi_pri_error);
14711    pri_set_message(dahdi_pri_message);
14712 #endif
14713 #if defined(HAVE_SS7)
14714    for (i = 0; i < NUM_SPANS; i++) {
14715       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
14716          dahdi_close_ss7_fd(&(linksets[i]), j);
14717    }
14718 
14719    memset(linksets, 0, sizeof(linksets));
14720    for (i = 0; i < NUM_SPANS; i++) {
14721       sig_ss7_init_linkset(&linksets[i].ss7);
14722    }
14723    ss7_set_error(dahdi_ss7_error);
14724    ss7_set_message(dahdi_ss7_message);
14725 #endif   /* defined(HAVE_SS7) */
14726 
14727    if (setup_dahdi(2) != 0) {
14728       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14729       ast_mutex_unlock(&ss_thread_lock);
14730       return 1;
14731    }
14732    ast_mutex_unlock(&ss_thread_lock);
14733    ast_mutex_unlock(&restart_lock);
14734    return 0;
14735 }

static char* dahdi_restart_cmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14737 of file chan_dahdi.c.

References ast_cli_args::argc, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_restart(), and ast_cli_entry::usage.

14738 {
14739    switch (cmd) {
14740    case CLI_INIT:
14741       e->command = "dahdi restart";
14742       e->usage =
14743          "Usage: dahdi restart\n"
14744          "  Restarts the DAHDI channels: destroys them all and then\n"
14745          "  re-reads them from chan_dahdi.conf.\n"
14746          "  Note that this will STOP any running CALL on DAHDI channels.\n"
14747          "";
14748       return NULL;
14749    case CLI_GENERATE:
14750       return NULL;
14751    }
14752    if (a->argc != 2)
14753       return CLI_SHOWUSAGE;
14754 
14755    if (dahdi_restart() != 0)
14756       return CLI_FAILURE;
14757    return CLI_SUCCESS;
14758 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 7388 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), dahdi_handle_event(), and my_ring().

07389 {
07390    int x;
07391    int res;
07392    /* Make sure our transmit state is on hook */
07393    x = 0;
07394    x = DAHDI_ONHOOK;
07395    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07396    do {
07397       x = DAHDI_RING;
07398       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07399       if (res) {
07400          switch (errno) {
07401          case EBUSY:
07402          case EINTR:
07403             /* Wait just in case */
07404             usleep(10000);
07405             continue;
07406          case EINPROGRESS:
07407             res = 0;
07408             break;
07409          default:
07410             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07411             res = 0;
07412          }
07413       }
07414    } while (res);
07415    return res;
07416 }

static int dahdi_send_callrerouting_facility_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 5778 of file chan_dahdi.c.

References ast_channel::_state, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), dahdi_tech, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::name, parse(), pri_send_callrerouting_facility_exec(), dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, ast_channel::tech, and ast_channel::tech_pvt.

Referenced by load_module().

05779 {
05780    /* Data will be our digit string */
05781    struct dahdi_pvt *pvt;
05782    char *parse;
05783    int res = -1;
05784    AST_DECLARE_APP_ARGS(args,
05785       AST_APP_ARG(destination);
05786       AST_APP_ARG(original);
05787       AST_APP_ARG(reason);
05788    );
05789 
05790    if (ast_strlen_zero(data)) {
05791       ast_log(LOG_DEBUG, "No data sent to application!\n");
05792       return -1;
05793    }
05794    if (chan->tech != &dahdi_tech) {
05795       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05796       return -1;
05797    }
05798    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05799    if (!pvt) {
05800       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05801       return -1;
05802    }
05803    switch (pvt->sig) {
05804    case SIG_PRI_LIB_HANDLE_CASES:
05805       break;
05806    default:
05807       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05808          chan->name);
05809       return -1;
05810    }
05811 
05812    parse = ast_strdupa(data);
05813    AST_STANDARD_APP_ARGS(args, parse);
05814 
05815    if (ast_strlen_zero(args.destination)) {
05816       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05817       return -1;
05818    }
05819 
05820    if (ast_strlen_zero(args.original)) {
05821       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05822       args.original = NULL;
05823    }
05824 
05825    if (ast_strlen_zero(args.reason)) {
05826       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05827       args.reason = NULL;
05828    }
05829 
05830    pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05831       args.original, args.reason);
05832 
05833    return res;
05834 }

static int dahdi_send_keypad_facility_exec ( struct ast_channel chan,
const char *  digits 
) [static]

Definition at line 5751 of file chan_dahdi.c.

References ast_debug, ast_strlen_zero(), pri_send_keypad_facility_exec(), dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.

Referenced by load_module().

05752 {
05753    /* Data will be our digit string */
05754    struct dahdi_pvt *p;
05755 
05756    if (ast_strlen_zero(digits)) {
05757       ast_debug(1, "No digit string sent to application!\n");
05758       return -1;
05759    }
05760 
05761    p = (struct dahdi_pvt *)chan->tech_pvt;
05762 
05763    if (!p) {
05764       ast_debug(1, "Unable to find technology private\n");
05765       return -1;
05766    }
05767 
05768    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05769 
05770    return 0;
05771 }

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

Definition at line 18051 of file chan_dahdi.c.

References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index, dahdi_subchannel::dfd, END_SILENCE_LEN, errno, HEADER_LEN, HEADER_MS, len(), dahdi_pvt::mate, 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.

18052 {
18053 #define  END_SILENCE_LEN 400
18054 #define  HEADER_MS 50
18055 #define  TRAILER_MS 5
18056 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18057 #define  ASCII_BYTES_PER_CHAR 80
18058 
18059    unsigned char *buf,*mybuf;
18060    struct dahdi_pvt *p = c->tech_pvt;
18061    struct pollfd fds[1];
18062    int size,res,fd,len,x;
18063    int bytes=0;
18064    /* Initial carrier (imaginary) */
18065    float cr = 1.0;
18066    float ci = 0.0;
18067    float scont = 0.0;
18068    int idx;
18069 
18070    idx = dahdi_get_index(c, p, 0);
18071    if (idx < 0) {
18072       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18073       return -1;
18074    }
18075    if (!text[0]) return(0); /* if nothing to send, don't */
18076    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18077    if (p->mate)
18078       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18079    else
18080       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18081    if (!buf)
18082       return -1;
18083    mybuf = buf;
18084    if (p->mate) {
18085       int codec = AST_LAW(p);
18086       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18087          PUT_CLID_MARKMS;
18088       }
18089       /* Put actual message */
18090       for (x = 0; text[x]; x++) {
18091          PUT_CLID(text[x]);
18092       }
18093       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18094          PUT_CLID_MARKMS;
18095       }
18096       len = bytes;
18097       buf = mybuf;
18098    } else {
18099       len = tdd_generate(p->tdd, buf, text);
18100       if (len < 1) {
18101          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18102          ast_free(mybuf);
18103          return -1;
18104       }
18105    }
18106    memset(buf + len, 0x7f, END_SILENCE_LEN);
18107    len += END_SILENCE_LEN;
18108    fd = p->subs[idx].dfd;
18109    while (len) {
18110       if (ast_check_hangup(c)) {
18111          ast_free(mybuf);
18112          return -1;
18113       }
18114       size = len;
18115       if (size > READ_SIZE)
18116          size = READ_SIZE;
18117       fds[0].fd = fd;
18118       fds[0].events = POLLOUT | POLLPRI;
18119       fds[0].revents = 0;
18120       res = poll(fds, 1, -1);
18121       if (!res) {
18122          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18123          continue;
18124       }
18125       /* if got exception */
18126       if (fds[0].revents & POLLPRI) {
18127          ast_free(mybuf);
18128          return -1;
18129       }
18130       if (!(fds[0].revents & POLLOUT)) {
18131          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18132          continue;
18133       }
18134       res = write(fd, buf, size);
18135       if (res != size) {
18136          if (res == -1) {
18137             ast_free(mybuf);
18138             return -1;
18139          }
18140          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18141          break;
18142       }
18143       len -= size;
18144       buf += size;
18145    }
18146    ast_free(mybuf);
18147    return(0);
18148 }

static char* dahdi_set_dnd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15349 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_false(), ast_mutex_lock, ast_mutex_unlock, ast_true(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_dnd(), ast_cli_args::fd, iflist, dahdi_pvt::next, and ast_cli_entry::usage.

15350 {
15351    int channel;
15352    int on;
15353    struct dahdi_pvt *dahdi_chan = NULL;
15354 
15355    switch (cmd) {
15356    case CLI_INIT:
15357       e->command = "dahdi set dnd";
15358       e->usage =
15359          "Usage: dahdi set dnd <chan#> <on|off>\n"
15360          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15361          "  Changes take effect immediately.\n"
15362          "  <chan num> is the channel number\n"
15363          "  <on|off> Enable or disable DND mode?\n"
15364          ;
15365       return NULL;
15366    case CLI_GENERATE:
15367       return NULL;
15368    }
15369 
15370    if (a->argc != 5)
15371       return CLI_SHOWUSAGE;
15372 
15373    if ((channel = atoi(a->argv[3])) <= 0) {
15374       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15375       return CLI_SHOWUSAGE;
15376    }
15377 
15378    if (ast_true(a->argv[4]))
15379       on = 1;
15380    else if (ast_false(a->argv[4]))
15381       on = 0;
15382    else {
15383       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15384       return CLI_SHOWUSAGE;
15385    }
15386 
15387    ast_mutex_lock(&iflock);
15388    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15389       if (dahdi_chan->channel != channel)
15390          continue;
15391 
15392       /* Found the channel. Actually set it */
15393       dahdi_dnd(dahdi_chan, on);
15394       break;
15395    }
15396    ast_mutex_unlock(&iflock);
15397 
15398    if (!dahdi_chan) {
15399       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15400       return CLI_FAILURE;
15401    }
15402 
15403    return CLI_SUCCESS;
15404 }

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

Definition at line 5011 of file chan_dahdi.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), mwi_send_process_buffer(), mwi_send_process_event(), my_off_hook(), and my_on_hook().

05012 {
05013    int x, res;
05014 
05015    x = hs;
05016    res = ioctl(fd, DAHDI_HOOK, &x);
05017 
05018    if (res < 0) {
05019       if (errno == EINPROGRESS)
05020          return 0;
05021       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05022       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05023    }
05024 
05025    return res;
05026 }

static char* dahdi_set_hwgain ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15209 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, errno, ast_cli_args::fd, iflist, dahdi_pvt::next, SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.

15210 {
15211    int channel;
15212    int gain;
15213    int tx;
15214    struct dahdi_hwgain hwgain;
15215    struct dahdi_pvt *tmp = NULL;
15216 
15217    switch (cmd) {
15218    case CLI_INIT:
15219       e->command = "dahdi set hwgain";
15220       e->usage =
15221          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15222          "  Sets the hardware gain on a a given channel, overriding the\n"
15223          "   value provided at module loadtime, whether the channel is in\n"
15224          "   use or not.  Changes take effect immediately.\n"
15225          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15226          "   <chan num> is the channel number relative to the device\n"
15227          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15228       return NULL;
15229    case CLI_GENERATE:
15230       return NULL;
15231    }
15232 
15233    if (a->argc != 6)
15234       return CLI_SHOWUSAGE;
15235 
15236    if (!strcasecmp("rx", a->argv[3]))
15237       tx = 0; /* rx */
15238    else if (!strcasecmp("tx", a->argv[3]))
15239       tx = 1; /* tx */
15240    else
15241       return CLI_SHOWUSAGE;
15242 
15243    channel = atoi(a->argv[4]);
15244    gain = atof(a->argv[5])*10.0;
15245 
15246    ast_mutex_lock(&iflock);
15247 
15248    for (tmp = iflist; tmp; tmp = tmp->next) {
15249 
15250       if (tmp->channel != channel)
15251          continue;
15252 
15253       if (tmp->subs[SUB_REAL].dfd == -1)
15254          break;
15255 
15256       hwgain.newgain = gain;
15257       hwgain.tx = tx;
15258       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15259          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15260          ast_mutex_unlock(&iflock);
15261          return CLI_FAILURE;
15262       }
15263       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15264          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15265       break;
15266    }
15267 
15268    ast_mutex_unlock(&iflock);
15269 
15270    if (tmp)
15271       return CLI_SUCCESS;
15272 
15273    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15274    return CLI_FAILURE;
15275 
15276 }

static char* dahdi_set_swgain ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15278 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iflist, dahdi_pvt::law, dahdi_pvt::next, dahdi_pvt::rxdrc, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, and ast_cli_entry::usage.

15279 {
15280    int channel;
15281    float gain;
15282    int tx;
15283    int res;
15284    struct dahdi_pvt *tmp = NULL;
15285 
15286    switch (cmd) {
15287    case CLI_INIT:
15288       e->command = "dahdi set swgain";
15289       e->usage =
15290          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15291          "  Sets the software gain on a a given channel, overriding the\n"
15292          "   value provided at module loadtime, whether the channel is in\n"
15293          "   use or not.  Changes take effect immediately.\n"
15294          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15295          "   <chan num> is the channel number relative to the device\n"
15296          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15297       return NULL;
15298    case CLI_GENERATE:
15299       return NULL;
15300    }
15301 
15302    if (a->argc != 6)
15303       return CLI_SHOWUSAGE;
15304 
15305    if (!strcasecmp("rx", a->argv[3]))
15306       tx = 0; /* rx */
15307    else if (!strcasecmp("tx", a->argv[3]))
15308       tx = 1; /* tx */
15309    else
15310       return CLI_SHOWUSAGE;
15311 
15312    channel = atoi(a->argv[4]);
15313    gain = atof(a->argv[5]);
15314 
15315    ast_mutex_lock(&iflock);
15316    for (tmp = iflist; tmp; tmp = tmp->next) {
15317 
15318       if (tmp->channel != channel)
15319          continue;
15320 
15321       if (tmp->subs[SUB_REAL].dfd == -1)
15322          break;
15323 
15324       if (tx)
15325          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15326       else
15327          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15328 
15329       if (res) {
15330          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15331          ast_mutex_unlock(&iflock);
15332          return CLI_FAILURE;
15333       }
15334 
15335       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15336          tx ? "tx" : "rx", gain, channel);
15337       break;
15338    }
15339    ast_mutex_unlock(&iflock);
15340 
15341    if (tmp)
15342       return CLI_SUCCESS;
15343 
15344    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15345    return CLI_FAILURE;
15346 
15347 }

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

Definition at line 2485 of file chan_dahdi.c.

Referenced by my_new_pri_ast_channel(), my_new_ss7_ast_channel(), and my_pri_open_media().

02486 {
02487    int res;
02488    res = ioctl(dfd, DAHDI_SETLAW, &law);
02489    if (res)
02490       return res;
02491    return 0;
02492 }

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

Definition at line 4240 of file chan_dahdi.c.

Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), my_all_subchannels_hungup(), my_set_linear_mode(), my_start_cid_detect(), my_stop_cid_detect(), and send_callerid().

04241 {
04242    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04243 }

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

Definition at line 6532 of file chan_dahdi.c.

References ast_check_hangup(), ast_debug, ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_DIGIT_DETECT, AST_OPTION_ECHOCAN, AST_OPTION_FAX_DETECT, 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_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, disable_dtmf_detect(), dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::dtmfrelax, enable_dtmf_detect(), errno, dahdi_pvt::law, len(), LOG_NOTICE, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, pp, READ_SIZE, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_channel_tech::type.

06533 {
06534    char *cp;
06535    signed char *scp;
06536    int x;
06537    int idx;
06538    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06539    struct oprmode *oprmode;
06540 
06541 
06542    /* all supported options require data */
06543    if (!data || (datalen < 1)) {
06544       errno = EINVAL;
06545       return -1;
06546    }
06547 
06548    switch (option) {
06549    case AST_OPTION_TXGAIN:
06550       scp = (signed char *) data;
06551       idx = dahdi_get_index(chan, p, 0);
06552       if (idx < 0) {
06553          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06554          return -1;
06555       }
06556       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06557       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06558    case AST_OPTION_RXGAIN:
06559       scp = (signed char *) data;
06560       idx = dahdi_get_index(chan, p, 0);
06561       if (idx < 0) {
06562          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06563          return -1;
06564       }
06565       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06566       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06567    case AST_OPTION_TONE_VERIFY:
06568       if (!p->dsp)
06569          break;
06570       cp = (char *) data;
06571       switch (*cp) {
06572       case 1:
06573          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06574          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06575          break;
06576       case 2:
06577          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06578          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06579          break;
06580       default:
06581          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06582          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06583          break;
06584       }
06585       break;
06586    case AST_OPTION_TDD:
06587       /* turn on or off TDD */
06588       cp = (char *) data;
06589       p->mate = 0;
06590       if (!*cp) { /* turn it off */
06591          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06592          if (p->tdd)
06593             tdd_free(p->tdd);
06594          p->tdd = 0;
06595          break;
06596       }
06597       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06598          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06599       dahdi_disable_ec(p);
06600       /* otherwise, turn it on */
06601       if (!p->didtdd) { /* if havent done it yet */
06602          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06603          unsigned char *buf;
06604          int size, res, fd, len;
06605          struct pollfd fds[1];
06606 
06607          buf = mybuf;
06608          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06609          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06610          len = 40000;
06611          idx = dahdi_get_index(chan, p, 0);
06612          if (idx < 0) {
06613             ast_log(LOG_WARNING, "No index in TDD?\n");
06614             return -1;
06615          }
06616          fd = p->subs[idx].dfd;
06617          while (len) {
06618             if (ast_check_hangup(chan))
06619                return -1;
06620             size = len;
06621             if (size > READ_SIZE)
06622                size = READ_SIZE;
06623             fds[0].fd = fd;
06624             fds[0].events = POLLPRI | POLLOUT;
06625             fds[0].revents = 0;
06626             res = poll(fds, 1, -1);
06627             if (!res) {
06628                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06629                continue;
06630             }
06631             /* if got exception */
06632             if (fds[0].revents & POLLPRI)
06633                return -1;
06634             if (!(fds[0].revents & POLLOUT)) {
06635                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06636                continue;
06637             }
06638             res = write(fd, buf, size);
06639             if (res != size) {
06640                if (res == -1) return -1;
06641                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06642                break;
06643             }
06644             len -= size;
06645             buf += size;
06646          }
06647          p->didtdd = 1; /* set to have done it now */
06648       }
06649       if (*cp == 2) { /* Mate mode */
06650          if (p->tdd)
06651             tdd_free(p->tdd);
06652          p->tdd = 0;
06653          p->mate = 1;
06654          break;
06655       }
06656       if (!p->tdd) { /* if we don't have one yet */
06657          p->tdd = tdd_new(); /* allocate one */
06658       }
06659       break;
06660    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06661       if (!p->dsp)
06662          break;
06663       cp = (char *) data;
06664       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06665          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06666       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06667       break;
06668    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06669 #if defined(HAVE_PRI)
06670       if (dahdi_sig_pri_lib_handles(p->sig)
06671          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06672          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06673          break;
06674       }
06675 #endif   /* defined(HAVE_PRI) */
06676 
06677       cp = (char *) data;
06678       if (!*cp) {
06679          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06680          x = 0;
06681          dahdi_disable_ec(p);
06682       } else {
06683          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06684          x = 1;
06685       }
06686       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06687          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06688       break;
06689    case AST_OPTION_OPRMODE:  /* Operator services mode */
06690       oprmode = (struct oprmode *) data;
06691       /* We don't support operator mode across technologies */
06692       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06693          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06694                chan->tech->type, oprmode->peer->tech->type);
06695          errno = EINVAL;
06696          return -1;
06697       }
06698       pp = oprmode->peer->tech_pvt;
06699       p->oprmode = pp->oprmode = 0;
06700       /* setup peers */
06701       p->oprpeer = pp;
06702       pp->oprpeer = p;
06703       /* setup modes, if any */
06704       if (oprmode->mode)
06705       {
06706          pp->oprmode = oprmode->mode;
06707          p->oprmode = -oprmode->mode;
06708       }
06709       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06710          oprmode->mode, chan->name,oprmode->peer->name);
06711       break;
06712    case AST_OPTION_ECHOCAN:
06713       cp = (char *) data;
06714       if (*cp) {
06715          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06716          dahdi_enable_ec(p);
06717       } else {
06718          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06719          dahdi_disable_ec(p);
06720       }
06721       break;
06722    case AST_OPTION_DIGIT_DETECT:
06723       cp = (char *) data;
06724       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06725       if (*cp) {
06726          enable_dtmf_detect(p);
06727       } else {
06728          disable_dtmf_detect(p);
06729       }
06730       break;
06731    case AST_OPTION_FAX_DETECT:
06732       cp = (char *) data;
06733       if (p->dsp) {
06734          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06735          if (*cp) {
06736             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06737          } else {
06738             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06739          }
06740          ast_dsp_set_features(p->dsp, p->dsp_features);
06741       }
06742       break;
06743    default:
06744       return -1;
06745    }
06746    errno = 0;
06747 
06748    return 0;
06749 }

static char* dahdi_show_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14856 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_ton, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::destroy, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, dahdi_pvt::exten, dahdi_pvt::faxhandled, ast_cli_args::fd, HAVE_PRI_SUBADDR, dahdi_pvt::head, iflist, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::mailbox, dahdi_pvt::master, 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, ast_channel::name, ast_variable::name, ast_variable::next, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, S_OR, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_cli_entry::usage, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

14857 {
14858    int channel;
14859    struct dahdi_pvt *tmp = NULL;
14860    struct dahdi_confinfo ci;
14861    struct dahdi_params ps;
14862    int x;
14863 
14864    switch (cmd) {
14865    case CLI_INIT:
14866       e->command = "dahdi show channel";
14867       e->usage =
14868          "Usage: dahdi show channel <chan num>\n"
14869          "  Detailed information about a given channel\n";
14870       return NULL;
14871    case CLI_GENERATE:
14872       return NULL;
14873    }
14874 
14875    if (a->argc != 4)
14876       return CLI_SHOWUSAGE;
14877 
14878    channel = atoi(a->argv[3]);
14879 
14880    ast_mutex_lock(&iflock);
14881    for (tmp = iflist; tmp; tmp = tmp->next) {
14882       if (tmp->channel == channel) {
14883          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14884          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14885          ast_cli(a->fd, "Span: %d\n", tmp->span);
14886          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14887          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14888          ast_cli(a->fd, "Context: %s\n", tmp->context);
14889          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14890          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14891 #if defined(HAVE_PRI)
14892 #if defined(HAVE_PRI_SUBADDR)
14893          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
14894 #endif   /* defined(HAVE_PRI_SUBADDR) */
14895 #endif   /* defined(HAVE_PRI) */
14896          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14897          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14898          if (tmp->vars) {
14899             struct ast_variable *v;
14900             ast_cli(a->fd, "Variables:\n");
14901             for (v = tmp->vars ; v ; v = v->next)
14902                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
14903          }
14904          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14905          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14906          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14907          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14908          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14909          ast_cli(a->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)" : "");
14910          ast_cli(a->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)" : "");
14911          ast_cli(a->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)" : "");
14912          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14913          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14914          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14915          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14916          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14917          if (tmp->busydetect) {
14918 #if defined(BUSYDETECT_TONEONLY)
14919             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14920 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14921             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14922 #endif
14923 #ifdef BUSYDETECT_DEBUG
14924             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
14925 #endif
14926             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
14927             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
14928          }
14929          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14930          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14931          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14932          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14933          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14934          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14935          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
14936          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
14937          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
14938          ast_cli(a->fd, "Echo Cancellation:\n");
14939 
14940          if (tmp->echocancel.head.tap_length) {
14941             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14942             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14943                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14944             }
14945             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14946          } else {
14947             ast_cli(a->fd, "\tnone\n");
14948          }
14949          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14950          if (tmp->master)
14951             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14952          for (x = 0; x < MAX_SLAVES; x++) {
14953             if (tmp->slaves[x])
14954                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14955          }
14956 #ifdef HAVE_OPENR2
14957          if (tmp->mfcr2) {
14958             char calldir[OR2_MAX_PATH];
14959             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14960             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14961             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14962             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14963             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14964             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14965             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14966             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14967             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14968             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14969             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14970 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14971             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14972 #endif
14973             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14974             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14975             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14976             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14977             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14978             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14979             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14980             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14981             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14982             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14983             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14984             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14985          }
14986 #endif
14987 #if defined(HAVE_SS7)
14988          if (tmp->ss7) {
14989             struct sig_ss7_chan *chan = tmp->sig_pvt;
14990 
14991             ast_cli(a->fd, "CIC: %d\n", chan->cic);
14992          }
14993 #endif   /* defined(HAVE_SS7) */
14994 #ifdef HAVE_PRI
14995          if (tmp->pri) {
14996             struct sig_pri_chan *chan = tmp->sig_pvt;
14997 
14998             ast_cli(a->fd, "PRI Flags: ");
14999             if (chan->resetting)
15000                ast_cli(a->fd, "Resetting ");
15001             if (chan->call)
15002                ast_cli(a->fd, "Call ");
15003             ast_cli(a->fd, "\n");
15004             if (tmp->logicalspan)
15005                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15006             else
15007                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15008          }
15009 #endif
15010          memset(&ci, 0, sizeof(ci));
15011          ps.channo = tmp->channel;
15012          if (tmp->subs[SUB_REAL].dfd > -1) {
15013             memset(&ci, 0, sizeof(ci));
15014             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15015                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15016             }
15017             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15018                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15019             }
15020             memset(&ps, 0, sizeof(ps));
15021             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15022                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15023             } else {
15024                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15025             }
15026          }
15027          if (ISTRUNK(tmp)) {
15028             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
15029             if (!ast_strlen_zero(progzone))
15030                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15031             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
15032             if(tmp->busydetect) {
15033                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15034                if(tmp->busytonelength > 0) {
15035                   ast_cli(a->fd, "Busy Pattern:\n");
15036                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15037                   if (tmp->busyquietlength > 0) 
15038                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15039                   else 
15040                      ast_cli(a->fd, " -- Detect Tone Only\n");
15041                   if(tmp->busyfuzziness > 0)
15042                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15043                }
15044             }
15045          }
15046          ast_mutex_unlock(&iflock);
15047          return CLI_SUCCESS;
15048       }
15049    }
15050    ast_mutex_unlock(&iflock);
15051 
15052    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15053    return CLI_FAILURE;
15054 }

static char* dahdi_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14770 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::context, ast_cli_args::fd, FORMAT2, dahdi_pvt::group, iflist, dahdi_pvt::next, and ast_cli_entry::usage.

14771 {
14772 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14773 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14774    unsigned int targetnum = 0;
14775    int filtertype = 0;
14776    struct dahdi_pvt *tmp = NULL;
14777    char tmps[20] = "";
14778    char statestr[20] = "";
14779    char blockstr[20] = "";
14780 
14781    switch (cmd) {
14782    case CLI_INIT:
14783       e->command = "dahdi show channels [group|context]";
14784       e->usage =
14785          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
14786          "  Shows a list of available channels with optional filtering\n"
14787          "  <group> must be a number between 0 and 63\n";
14788       return NULL;
14789    case CLI_GENERATE:
14790       return NULL;
14791    }
14792 
14793    /* syntax: dahdi show channels [ group <group> | context <context> ] */
14794 
14795    if (!((a->argc == 3) || (a->argc == 5)))
14796       return CLI_SHOWUSAGE;
14797 
14798    if (a->argc == 5) {
14799       if (!strcasecmp(a->argv[3], "group")) {
14800          targetnum = atoi(a->argv[4]);
14801          if ((targetnum < 0) || (targetnum > 63))
14802             return CLI_SHOWUSAGE;
14803          targetnum = 1 << targetnum;
14804          filtertype = 1;
14805       } else if (!strcasecmp(a->argv[3], "context")) {
14806          filtertype = 2;
14807       }
14808    }
14809 
14810    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14811    ast_mutex_lock(&iflock);
14812    for (tmp = iflist; tmp; tmp = tmp->next) {
14813       if (filtertype) {
14814          switch(filtertype) {
14815          case 1: /* dahdi show channels group <group> */
14816             if (!(tmp->group & targetnum)) {
14817                continue;
14818             }
14819             break;
14820          case 2: /* dahdi show channels context <context> */
14821             if (strcasecmp(tmp->context, a->argv[4])) {
14822                continue;
14823             }
14824             break;
14825          default:
14826             ;
14827          }
14828       }
14829       if (tmp->channel > 0) {
14830          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14831       } else
14832          ast_copy_string(tmps, "pseudo", sizeof(tmps));
14833 
14834       if (tmp->locallyblocked)
14835          blockstr[0] = 'L';
14836       else
14837          blockstr[0] = ' ';
14838 
14839       if (tmp->remotelyblocked)
14840          blockstr[1] = 'R';
14841       else
14842          blockstr[1] = ' ';
14843 
14844       blockstr[2] = '\0';
14845 
14846       snprintf(statestr, sizeof(statestr), "%s", "In Service");
14847 
14848       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14849    }
14850    ast_mutex_unlock(&iflock);
14851    return CLI_SUCCESS;
14852 #undef FORMAT
14853 #undef FORMAT2
14854 }

static char* dahdi_show_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15093 of file chan_dahdi.c.

References ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, errno, ast_cli_args::fd, FORMAT, FORMAT2, lbostr, and ast_cli_entry::usage.

15094 {
15095    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15096    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15097    int span;
15098    int res;
15099    char alarmstr[50];
15100 
15101    int ctl;
15102    struct dahdi_spaninfo s;
15103 
15104    switch (cmd) {
15105    case CLI_INIT:
15106       e->command = "dahdi show status";
15107       e->usage =
15108          "Usage: dahdi show status\n"
15109          "       Shows a list of DAHDI cards with status\n";
15110       return NULL;
15111    case CLI_GENERATE:
15112       return NULL;
15113    }
15114    ctl = open("/dev/dahdi/ctl", O_RDWR);
15115    if (ctl < 0) {
15116       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15117       return CLI_FAILURE;
15118    }
15119    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15120 
15121    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15122       s.spanno = span;
15123       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15124       if (res) {
15125          continue;
15126       }
15127       alarmstr[0] = '\0';
15128       if (s.alarms > 0) {
15129          if (s.alarms & DAHDI_ALARM_BLUE)
15130             strcat(alarmstr, "BLU/");
15131          if (s.alarms & DAHDI_ALARM_YELLOW)
15132             strcat(alarmstr, "YEL/");
15133          if (s.alarms & DAHDI_ALARM_RED)
15134             strcat(alarmstr, "RED/");
15135          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15136             strcat(alarmstr, "LB/");
15137          if (s.alarms & DAHDI_ALARM_RECOVER)
15138             strcat(alarmstr, "REC/");
15139          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15140             strcat(alarmstr, "NOP/");
15141          if (!strlen(alarmstr))
15142             strcat(alarmstr, "UUU/");
15143          if (strlen(alarmstr)) {
15144             /* Strip trailing / */
15145             alarmstr[strlen(alarmstr) - 1] = '\0';
15146          }
15147       } else {
15148          if (s.numchans)
15149             strcpy(alarmstr, "OK");
15150          else
15151             strcpy(alarmstr, "UNCONFIGURED");
15152       }
15153 
15154       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15155          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15156          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15157          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15158          "CAS",
15159          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15160          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15161          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15162          "Unk",
15163          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15164             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15165             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15166          lbostr[s.lbo]
15167          );
15168    }
15169    close(ctl);
15170 
15171    return CLI_SUCCESS;
15172 #undef FORMAT
15173 #undef FORMAT2
15174 }

static char* dahdi_show_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15176 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, ast_cli_args::fd, and ast_cli_entry::usage.

15177 {
15178    int pseudo_fd = -1;
15179    struct dahdi_versioninfo vi;
15180 
15181    switch (cmd) {
15182    case CLI_INIT:
15183       e->command = "dahdi show version";
15184       e->usage =
15185          "Usage: dahdi show version\n"
15186          "       Shows the DAHDI version in use\n";
15187       return NULL;
15188    case CLI_GENERATE:
15189       return NULL;
15190    }
15191    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15192       ast_cli(a->fd, "Failed to open control file to get version.\n");
15193       return CLI_SUCCESS;
15194    }
15195 
15196    strcpy(vi.version, "Unknown");
15197    strcpy(vi.echo_canceller, "Unknown");
15198 
15199    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15200       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15201    else
15202       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15203 
15204    close(pseudo_fd);
15205 
15206    return CLI_SUCCESS;
15207 }

static char* dahdi_sig2str ( int  sig  )  [static]

Definition at line 4461 of file chan_dahdi.c.

References SIG_BRI, SIG_BRI_PTMP, 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, and SIG_SS7.

04462 {
04463    static char buf[256];
04464    switch (sig) {
04465    case SIG_EM:
04466       return "E & M Immediate";
04467    case SIG_EMWINK:
04468       return "E & M Wink";
04469    case SIG_EM_E1:
04470       return "E & M E1";
04471    case SIG_FEATD:
04472       return "Feature Group D (DTMF)";
04473    case SIG_FEATDMF:
04474       return "Feature Group D (MF)";
04475    case SIG_FEATDMF_TA:
04476       return "Feature Groud D (MF) Tandem Access";
04477    case SIG_FEATB:
04478       return "Feature Group B (MF)";
04479    case SIG_E911:
04480       return "E911 (MF)";
04481    case SIG_FGC_CAMA:
04482       return "FGC/CAMA (Dialpulse)";
04483    case SIG_FGC_CAMAMF:
04484       return "FGC/CAMA (MF)";
04485    case SIG_FXSLS:
04486       return "FXS Loopstart";
04487    case SIG_FXSGS:
04488       return "FXS Groundstart";
04489    case SIG_FXSKS:
04490       return "FXS Kewlstart";
04491    case SIG_FXOLS:
04492       return "FXO Loopstart";
04493    case SIG_FXOGS:
04494       return "FXO Groundstart";
04495    case SIG_FXOKS:
04496       return "FXO Kewlstart";
04497    case SIG_PRI:
04498       return "ISDN PRI";
04499    case SIG_BRI:
04500       return "ISDN BRI Point to Point";
04501    case SIG_BRI_PTMP:
04502       return "ISDN BRI Point to MultiPoint";
04503    case SIG_SS7:
04504       return "SS7";
04505    case SIG_MFCR2:
04506       return "MFC/R2";
04507    case SIG_SF:
04508       return "SF (Tone) Immediate";
04509    case SIG_SFWINK:
04510       return "SF (Tone) Wink";
04511    case SIG_SF_FEATD:
04512       return "SF (Tone) with Feature Group D (DTMF)";
04513    case SIG_SF_FEATDMF:
04514       return "SF (Tone) with Feature Group D (MF)";
04515    case SIG_SF_FEATB:
04516       return "SF (Tone) with Feature Group B (MF)";
04517    case 0:
04518       return "Pseudo";
04519    default:
04520       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04521       return buf;
04522    }
04523 }

static int dahdi_sig_pri_lib_handles ( int  signaling  )  [inline, static]

Definition at line 1533 of file chan_dahdi.c.

References SIG_PRI_LIB_HANDLE_CASES.

Referenced by dahdi_bridge(), dahdi_call(), dahdi_cc_callback(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_queryoption(), dahdi_read(), dahdi_request(), and dahdi_setoption().

01534 {
01535    int handles;
01536 
01537    switch (signaling) {
01538    case SIG_PRI_LIB_HANDLE_CASES:
01539       handles = 1;
01540       break;
01541    default:
01542       handles = 0;
01543       break;
01544    }
01545 
01546    return handles;
01547 }

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 14597 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, dahdi_pvt::lock, ast_channel::name, dahdi_pvt::next, num_restart_pending, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

14598 {
14599    struct dahdi_pvt *p;
14600 retry:
14601    ast_mutex_lock(&iflock);
14602    for (p = iflist; p; p = p->next) {
14603       ast_mutex_lock(&p->lock);
14604       if (p->owner && !p->restartpending) {
14605          if (ast_channel_trylock(p->owner)) {
14606             if (option_debug > 2)
14607                ast_verbose("Avoiding deadlock\n");
14608             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14609             ast_mutex_unlock(&p->lock);
14610             ast_mutex_unlock(&iflock);
14611             goto retry;
14612          }
14613          if (option_debug > 2)
14614             ast_verbose("Softhanging up on %s\n", p->owner->name);
14615          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14616          p->restartpending = 1;
14617          num_restart_pending++;
14618          ast_channel_unlock(p->owner);
14619       }
14620       ast_mutex_unlock(&p->lock);
14621    }
14622    ast_mutex_unlock(&iflock);
14623 }

static void dahdi_ss7_error ( struct ss7 *  ss7,
char *  s 
) [static]

Definition at line 13583 of file chan_dahdi.c.

References ast_log(), linksets, and dahdi_ss7::ss7.

Referenced by load_module().

13584 {
13585    int i;
13586 
13587    if (ss7) {
13588       for (i = 0; i < NUM_SPANS; i++) {
13589          if (linksets[i].ss7.ss7 == ss7) {
13590             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13591             return;
13592          }
13593       }
13594    }
13595    ast_log(LOG_ERROR, "%s", s);
13596 }

static void dahdi_ss7_message ( struct ss7 *  ss7,
char *  s 
) [static]

Definition at line 13566 of file chan_dahdi.c.

References ast_verbose, linksets, and dahdi_ss7::ss7.

Referenced by load_module().

13567 {
13568    int i;
13569 
13570    if (ss7) {
13571       for (i = 0; i < NUM_SPANS; i++) {
13572          if (linksets[i].ss7.ss7 == ss7) {
13573             ast_verbose("[%d] %s", i + 1, s);
13574             return;
13575          }
13576       }
13577    }
13578    ast_verbose("%s", s);
13579 }

static int dahdi_status_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 17820 of file chan_dahdi.c.

References ast_data_add_bool(), ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_log(), errno, and lbostr.

17822 {
17823    int ctl, res, span;
17824    struct ast_data *data_span, *data_alarms;
17825    struct dahdi_spaninfo s;
17826 
17827    ctl = open("/dev/dahdi/ctl", O_RDWR);
17828    if (ctl < 0) {
17829       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
17830       return -1;
17831    }
17832    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17833       s.spanno = span;
17834       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
17835       if (res) {
17836          continue;
17837       }
17838 
17839       data_span = ast_data_add_node(data_root, "span");
17840       if (!data_span) {
17841          continue;
17842       }
17843       ast_data_add_str(data_span, "description", s.desc);
17844 
17845       /* insert the alarms status */
17846       data_alarms = ast_data_add_node(data_span, "alarms");
17847       if (!data_alarms) {
17848          continue;
17849       }
17850 
17851       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
17852       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
17853       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
17854       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
17855       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
17856       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
17857 
17858       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
17859       ast_data_add_int(data_span, "bpviol", s.bpvcount);
17860       ast_data_add_int(data_span, "crc4", s.crc4count);
17861       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17862                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17863                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17864                      "CAS");
17865       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17866                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17867                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17868                      "Unknown");
17869       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
17870                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17871                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
17872       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
17873 
17874       /* if this span doesn't match remove it. */
17875       if (!ast_data_search_match(search, data_span)) {
17876          ast_data_remove_node(data_root, data_span);
17877       }
17878    }
17879    close(ctl);
17880 
17881    return 0;
17882 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4803 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::echocanon, dahdi_pvt::echotraining, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), and my_train_echocanceller().

04804 {
04805    int x;
04806    int res;
04807 
04808    if (p && p->echocanon && p->echotraining) {
04809       x = p->echotraining;
04810       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04811       if (res)
04812          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04813       else
04814          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04815    } else {
04816       ast_debug(1, "No echo training requested\n");
04817    }
04818 }

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

Definition at line 6918 of file chan_dahdi.c.

References ast_debug, ast_mutex_lock, ast_mutex_trylock, dahdi_pvt::channel, conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pvt::master, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_bridge(), and dahdi_fixup().

06919 {
06920    /* Unlink a specific slave or all slaves/masters from a given master */
06921    int x;
06922    int hasslaves;
06923    if (!master)
06924       return;
06925    if (needlock) {
06926       ast_mutex_lock(&master->lock);
06927       if (slave) {
06928          while (ast_mutex_trylock(&slave->lock)) {
06929             DEADLOCK_AVOIDANCE(&master->lock);
06930          }
06931       }
06932    }
06933    hasslaves = 0;
06934    for (x = 0; x < MAX_SLAVES; x++) {
06935       if (master->slaves[x]) {
06936          if (!slave || (master->slaves[x] == slave)) {
06937             /* Take slave out of the conference */
06938             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
06939             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
06940             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
06941             master->slaves[x]->master = NULL;
06942             master->slaves[x] = NULL;
06943          } else
06944             hasslaves = 1;
06945       }
06946       if (!hasslaves)
06947          master->inconference = 0;
06948    }
06949    if (!slave) {
06950       if (master->master) {
06951          /* Take master out of the conference */
06952          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
06953          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
06954          hasslaves = 0;
06955          for (x = 0; x < MAX_SLAVES; x++) {
06956             if (master->master->slaves[x] == master)
06957                master->master->slaves[x] = NULL;
06958             else if (master->master->slaves[x])
06959                hasslaves = 1;
06960          }
06961          if (!hasslaves)
06962             master->master->inconference = 0;
06963       }
06964       master->master = NULL;
06965    }
06966    update_conf(master);
06967    if (needlock) {
06968       if (slave)
06969          ast_mutex_unlock(&slave->lock);
06970       ast_mutex_unlock(&master->lock);
06971    }
06972 }

static void dahdi_unlink_pri_pvt ( struct dahdi_pvt pvt  )  [static]

Definition at line 5533 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::pri, sig_pri_span::pri, and dahdi_pvt::sig_pvt.

Referenced by destroy_dahdi_pvt().

05534 {
05535    unsigned idx;
05536    struct sig_pri_span *pri;
05537 
05538    pri = pvt->pri;
05539    if (!pri) {
05540       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05541       return;
05542    }
05543    ast_mutex_lock(&pri->lock);
05544    for (idx = 0; idx < pri->numchans; ++idx) {
05545       if (pri->pvts[idx] == pvt->sig_pvt) {
05546          pri->pvts[idx] = NULL;
05547          ast_mutex_unlock(&pri->lock);
05548          return;
05549       }
05550    }
05551    ast_mutex_unlock(&pri->lock);
05552 }

static void dahdi_unlink_ss7_pvt ( struct dahdi_pvt pvt  )  [static]

Definition at line 5565 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::sig_pvt, dahdi_pvt::ss7, and sig_ss7_linkset::ss7.

Referenced by destroy_dahdi_pvt().

05566 {
05567    unsigned idx;
05568    struct sig_ss7_linkset *ss7;
05569 
05570    ss7 = pvt->ss7;
05571    if (!ss7) {
05572       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05573       return;
05574    }
05575    ast_mutex_lock(&ss7->lock);
05576    for (idx = 0; idx < ss7->numchans; ++idx) {
05577       if (ss7->pvts[idx] == pvt->sig_pvt) {
05578          ss7->pvts[idx] = NULL;
05579          ast_mutex_unlock(&ss7->lock);
05580          return;
05581       }
05582    }
05583    ast_mutex_unlock(&ss7->lock);
05584 }

static int dahdi_version_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 17923 of file chan_dahdi.c.

References ast_data_add_str(), ast_log(), and errno.

17925 {
17926    int pseudo_fd = -1;
17927    struct dahdi_versioninfo vi = {
17928       .version = "Unknown",
17929       .echo_canceller = "Unknown"
17930    };
17931 
17932    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
17933       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
17934       return -1;
17935    }
17936 
17937    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
17938       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
17939    }
17940 
17941    close(pseudo_fd);
17942 
17943    ast_data_add_str(data_root, "value", vi.version);
17944    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
17945 
17946    return 0;
17947 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 478 of file chan_dahdi.c.

00479 {
00480    int i, j = 0;
00481    i = DAHDI_IOMUX_SIGEVENT;
00482    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00483       return -1;
00484    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00485       return -1;
00486    return j;
00487 }

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

Definition at line 9515 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), and my_wink().

09516 {
09517    int j;
09518    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09519    for (;;)
09520    {
09521       /* set bits of interest */
09522       j = DAHDI_IOMUX_SIGEVENT;
09523       /* wait for some happening */
09524       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09525       /* exit loop if we have it */
09526       if (j & DAHDI_IOMUX_SIGEVENT) break;
09527    }
09528    /* get the event info */
09529    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09530    return 0;
09531 }

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

Definition at line 9061 of file chan_dahdi.c.

References ast_debug, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_log(), dahdi_pvt::channel, dahdi_pvt::cidspill, ast_frame_subclass::codec, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, errno, ast_frame::frametype, dahdi_subchannel::linear, my_dahdi_write(), ast_channel::name, dahdi_pvt::owner, ast_frame::ptr, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

09062 {
09063    struct dahdi_pvt *p = ast->tech_pvt;
09064    int res;
09065    int idx;
09066    idx = dahdi_get_index(ast, p, 0);
09067    if (idx < 0) {
09068       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09069       return -1;
09070    }
09071 
09072    /* Write a frame of (presumably voice) data */
09073    if (frame->frametype != AST_FRAME_VOICE) {
09074       if (frame->frametype != AST_FRAME_IMAGE)
09075          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09076       return 0;
09077    }
09078    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09079       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09080       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09081       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09082       return -1;
09083    }
09084    if (p->dialing) {
09085       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09086       return 0;
09087    }
09088    if (!p->owner) {
09089       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09090       return 0;
09091    }
09092    if (p->cidspill) {
09093       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09094          ast->name);
09095       return 0;
09096    }
09097    /* Return if it's not valid data */
09098    if (!frame->data.ptr || !frame->datalen)
09099       return 0;
09100 
09101    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09102       if (!p->subs[idx].linear) {
09103          p->subs[idx].linear = 1;
09104          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09105          if (res)
09106             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09107       }
09108       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09109    } else {
09110       /* x-law already */
09111       if (p->subs[idx].linear) {
09112          p->subs[idx].linear = 0;
09113          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09114          if (res)
09115             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09116       }
09117       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09118    }
09119    if (res < 0) {
09120       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09121       return -1;
09122    }
09123    return 0;
09124 }

static enum analog_event dahdievent_to_analogevent ( int  event  )  [static]

Definition at line 2630 of file chan_dahdi.c.

References ANALOG_EVENT_ALARM, ANALOG_EVENT_DIALCOMPLETE, ANALOG_EVENT_DTMFDOWN, ANALOG_EVENT_DTMFUP, ANALOG_EVENT_EC_DISABLED, ANALOG_EVENT_EC_NLP_DISABLED, ANALOG_EVENT_EC_NLP_ENABLED, ANALOG_EVENT_ERROR, ANALOG_EVENT_HOOKCOMPLETE, ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ANALOG_EVENT_NOALARM, ANALOG_EVENT_ONHOOK, ANALOG_EVENT_POLARITY, ANALOG_EVENT_PULSE_START, ANALOG_EVENT_PULSEDIGIT, ANALOG_EVENT_REMOVED, ANALOG_EVENT_RINGBEGIN, ANALOG_EVENT_RINGEROFF, ANALOG_EVENT_RINGERON, ANALOG_EVENT_RINGOFFHOOK, ANALOG_EVENT_RX_CED_DETECTED, ANALOG_EVENT_TX_CED_DETECTED, and ANALOG_EVENT_WINKFLASH.

Referenced by my_get_callerid(), and my_get_event().

02631 {
02632    enum analog_event res;
02633 
02634    switch (event) {
02635    case DAHDI_EVENT_ONHOOK:
02636       res = ANALOG_EVENT_ONHOOK;
02637       break;
02638    case DAHDI_EVENT_RINGOFFHOOK:
02639       res = ANALOG_EVENT_RINGOFFHOOK;
02640       break;
02641    case DAHDI_EVENT_WINKFLASH:
02642       res = ANALOG_EVENT_WINKFLASH;
02643       break;
02644    case DAHDI_EVENT_ALARM:
02645       res = ANALOG_EVENT_ALARM;
02646       break;
02647    case DAHDI_EVENT_NOALARM:
02648       res = ANALOG_EVENT_NOALARM;
02649       break;
02650    case DAHDI_EVENT_DIALCOMPLETE:
02651       res = ANALOG_EVENT_DIALCOMPLETE;
02652       break;
02653    case DAHDI_EVENT_RINGERON:
02654       res = ANALOG_EVENT_RINGERON;
02655       break;
02656    case DAHDI_EVENT_RINGEROFF:
02657       res = ANALOG_EVENT_RINGEROFF;
02658       break;
02659    case DAHDI_EVENT_HOOKCOMPLETE:
02660       res = ANALOG_EVENT_HOOKCOMPLETE;
02661       break;
02662    case DAHDI_EVENT_PULSE_START:
02663       res = ANALOG_EVENT_PULSE_START;
02664       break;
02665    case DAHDI_EVENT_POLARITY:
02666       res = ANALOG_EVENT_POLARITY;
02667       break;
02668    case DAHDI_EVENT_RINGBEGIN:
02669       res = ANALOG_EVENT_RINGBEGIN;
02670       break;
02671    case DAHDI_EVENT_EC_DISABLED:
02672       res = ANALOG_EVENT_EC_DISABLED;
02673       break;
02674    case DAHDI_EVENT_REMOVED:
02675       res = ANALOG_EVENT_REMOVED;
02676       break;
02677    case DAHDI_EVENT_NEONMWI_ACTIVE:
02678       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02679       break;
02680    case DAHDI_EVENT_NEONMWI_INACTIVE:
02681       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02682       break;
02683 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02684    case DAHDI_EVENT_TX_CED_DETECTED:
02685       res = ANALOG_EVENT_TX_CED_DETECTED;
02686       break;
02687    case DAHDI_EVENT_RX_CED_DETECTED:
02688       res = ANALOG_EVENT_RX_CED_DETECTED;
02689       break;
02690    case DAHDI_EVENT_EC_NLP_DISABLED:
02691       res = ANALOG_EVENT_EC_NLP_DISABLED;
02692       break;
02693    case DAHDI_EVENT_EC_NLP_ENABLED:
02694       res = ANALOG_EVENT_EC_NLP_ENABLED;
02695       break;
02696 #endif
02697    case DAHDI_EVENT_PULSEDIGIT:
02698       res = ANALOG_EVENT_PULSEDIGIT;
02699       break;
02700    case DAHDI_EVENT_DTMFDOWN:
02701       res = ANALOG_EVENT_DTMFDOWN;
02702       break;
02703    case DAHDI_EVENT_DTMFUP:
02704       res = ANALOG_EVENT_DTMFUP;
02705       break;
02706    default:
02707       switch(event & 0xFFFF0000) {
02708       case DAHDI_EVENT_PULSEDIGIT:
02709       case DAHDI_EVENT_DTMFDOWN:
02710       case DAHDI_EVENT_DTMFUP:
02711          /* The event includes a digit number in the low word.
02712           * Converting it to a 'enum analog_event' would remove
02713           * that information. Thus it is returned as-is.
02714           */
02715          return event;
02716       }
02717 
02718       res = ANALOG_EVENT_ERROR;
02719       break;
02720    }
02721 
02722    return res;
02723 }

static enum analog_sigtype dahdisig_to_analogsig ( int  sig  )  [static]

Definition at line 1549 of file chan_dahdi.c.

References ANALOG_SIG_EM, ANALOG_SIG_EM_E1, ANALOG_SIG_EMWINK, ANALOG_SIG_FEATB, ANALOG_SIG_FEATD, ANALOG_SIG_FEATDMF, ANALOG_SIG_FEATDMF_TA, ANALOG_SIG_FGC_CAMA, ANALOG_SIG_FGC_CAMAMF, ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, ANALOG_SIG_SF, ANALOG_SIG_SF_FEATD, ANALOG_SIG_SF_FEATDMF, ANALOG_SIG_SFWINK, 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_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

01550 {
01551    switch (sig) {
01552    case SIG_FXOLS:
01553       return ANALOG_SIG_FXOLS;
01554    case SIG_FXOGS:
01555       return ANALOG_SIG_FXOGS;
01556    case SIG_FXOKS:
01557       return ANALOG_SIG_FXOKS;
01558    case SIG_FXSLS:
01559       return ANALOG_SIG_FXSLS;
01560    case SIG_FXSGS:
01561       return ANALOG_SIG_FXSGS;
01562    case SIG_FXSKS:
01563       return ANALOG_SIG_FXSKS;
01564    case SIG_EMWINK:
01565       return ANALOG_SIG_EMWINK;
01566    case SIG_EM:
01567       return ANALOG_SIG_EM;
01568    case SIG_EM_E1:
01569       return ANALOG_SIG_EM_E1;
01570    case SIG_FEATD:
01571       return ANALOG_SIG_FEATD;
01572    case SIG_FEATDMF:
01573       return ANALOG_SIG_FEATDMF;
01574    case SIG_E911:
01575       return SIG_E911;
01576    case SIG_FGC_CAMA:
01577       return ANALOG_SIG_FGC_CAMA;
01578    case SIG_FGC_CAMAMF:
01579       return ANALOG_SIG_FGC_CAMAMF;
01580    case SIG_FEATB:
01581       return ANALOG_SIG_FEATB;
01582    case SIG_SFWINK:
01583       return ANALOG_SIG_SFWINK;
01584    case SIG_SF:
01585       return ANALOG_SIG_SF;
01586    case SIG_SF_FEATD:
01587       return ANALOG_SIG_SF_FEATD;
01588    case SIG_SF_FEATDMF:
01589       return ANALOG_SIG_SF_FEATDMF;
01590    case SIG_FEATDMF_TA:
01591       return ANALOG_SIG_FEATDMF_TA;
01592    case SIG_SF_FEATB:
01593       return ANALOG_SIG_FEATB;
01594    default:
01595       return -1;
01596    }
01597 }

static void deep_copy_dahdi_chan_conf ( struct dahdi_chan_conf dest,
const struct dahdi_chan_conf src 
) [static]

Definition at line 17534 of file chan_dahdi.c.

References ast_cc_copy_config_params(), dahdi_pvt::cc_params, and dahdi_chan_conf::chan.

Referenced by setup_dahdi_int().

17535 {
17536    struct ast_cc_config_params *cc_params;
17537 
17538    cc_params = dest->chan.cc_params;
17539    *dest = *src;
17540    dest->chan.cc_params = cc_params;
17541    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17542 }

static void destroy_all_channels ( void   )  [static]

Definition at line 5686 of file chan_dahdi.c.

References ast_db_del(), ast_db_get(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::channel, dahdi_db, destroy_dahdi_pvt(), ifcount, iflist, iflock, sig_pri_span::lock, sig_pri_span::no_b_chan_iflist, num_restart_pending, NUM_SPANS, dahdi_pri::pri, dahdi_pvt::pri, sig_pri_span::pri, pris, dahdi_pvt::span, and SRVST_DBKEY.

Referenced by __unload_module().

05687 {
05688    int chan;
05689 #if defined(HAVE_PRI)
05690    unsigned span;
05691    struct sig_pri_span *pri;
05692 #endif   /* defined(HAVE_PRI) */
05693    struct dahdi_pvt *p;
05694 
05695    while (num_restart_pending) {
05696       usleep(1);
05697    }
05698 
05699    ast_mutex_lock(&iflock);
05700    /* Destroy all the interfaces and free their memory */
05701    while (iflist) {
05702       p = iflist;
05703 
05704       chan = p->channel;
05705 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05706       {
05707          char db_chan_name[20];
05708          char db_answer[5];
05709          char state;
05710          int why = -1;
05711 
05712          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05713          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05714             sscanf(db_answer, "%1c:%30d", &state, &why);
05715          }
05716          if (!why) {
05717             /* SRVST persistence is not required */
05718             ast_db_del(db_chan_name, SRVST_DBKEY);
05719          }
05720       }
05721 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05722       /* Free associated memory */
05723       destroy_dahdi_pvt(p);
05724       ast_verb(3, "Unregistered channel %d\n", chan);
05725    }
05726    ifcount = 0;
05727    ast_mutex_unlock(&iflock);
05728 
05729 #if defined(HAVE_PRI)
05730    /* Destroy all of the no B channel interface lists */
05731    for (span = 0; span < NUM_SPANS; ++span) {
05732       if (!pris[span].dchannels[0]) {
05733          break;
05734       }
05735       pri = &pris[span].pri;
05736       ast_mutex_lock(&pri->lock);
05737       while (pri->no_b_chan_iflist) {
05738          p = pri->no_b_chan_iflist;
05739 
05740          /* Free associated memory */
05741          destroy_dahdi_pvt(p);
05742       }
05743       ast_mutex_unlock(&pri->lock);
05744    }
05745 #endif   /* defined(HAVE_PRI) */
05746 }

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

Definition at line 5668 of file chan_dahdi.c.

References dahdi_subchannel::owner, dahdi_pvt::owner, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().

05669 {
05670    int i;
05671 
05672    if (!now) {
05673       /* Do not destroy the channel now if it is owned by someone. */
05674       if (cur->owner) {
05675          return;
05676       }
05677       for (i = 0; i < 3; i++) {
05678          if (cur->subs[i].owner) {
05679             return;
05680          }
05681       }
05682    }
05683    destroy_dahdi_pvt(cur);
05684 }

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

Definition at line 5598 of file chan_dahdi.c.

References analog_delete(), analog_lib_handles(), ast_cc_config_params_destroy(), ast_event_unsubscribe(), ast_free, ast_mutex_destroy, ast_smdi_interface_unref(), ast_variables_destroy(), dahdi_pvt::cc_params, dahdi_pvt::cidspill, dahdi_close_sub(), dahdi_iflist_extract(), DAHDI_IFLIST_MAIN, DAHDI_IFLIST_NO_B_CHAN, DAHDI_IFLIST_NONE, dahdi_nobch_extract(), dahdi_unlink_pri_pvt(), dahdi_unlink_ss7_pvt(), find_next_iface_in_span(), dahdi_pvt::lock, dahdi_pvt::manages_span_alarms, dahdi_pvt::mwi_event_sub, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::sig, sig_pri_chan_delete(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_chan_delete(), dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, dahdi_pvt::use_smdi, dahdi_pvt::vars, and dahdi_pvt::which_iflist.

Referenced by destroy_all_channels(), and duplicate_pseudo().

05599 {
05600    struct dahdi_pvt *p = pvt;
05601 
05602    if (p->manages_span_alarms) {
05603       struct dahdi_pvt *next = find_next_iface_in_span(p);
05604       if (next) {
05605          next->manages_span_alarms = 1;
05606       }
05607    }
05608 
05609    /* Remove channel from the list */
05610 #if defined(HAVE_PRI)
05611    dahdi_unlink_pri_pvt(p);
05612 #endif   /* defined(HAVE_PRI) */
05613 #if defined(HAVE_SS7)
05614    dahdi_unlink_ss7_pvt(p);
05615 #endif   /* defined(HAVE_SS7) */
05616    switch (pvt->which_iflist) {
05617    case DAHDI_IFLIST_NONE:
05618       break;
05619    case DAHDI_IFLIST_MAIN:
05620       dahdi_iflist_extract(p);
05621       break;
05622 #if defined(HAVE_PRI)
05623    case DAHDI_IFLIST_NO_B_CHAN:
05624       if (p->pri) {
05625          dahdi_nobch_extract(p->pri, p);
05626       }
05627       break;
05628 #endif   /* defined(HAVE_PRI) */
05629    }
05630 
05631    if (p->sig_pvt) {
05632       if (analog_lib_handles(p->sig, 0, 0)) {
05633          analog_delete(p->sig_pvt);
05634       }
05635       switch (p->sig) {
05636 #if defined(HAVE_PRI)
05637       case SIG_PRI_LIB_HANDLE_CASES:
05638          sig_pri_chan_delete(p->sig_pvt);
05639          break;
05640 #endif   /* defined(HAVE_PRI) */
05641 #if defined(HAVE_SS7)
05642       case SIG_SS7:
05643          sig_ss7_chan_delete(p->sig_pvt);
05644          break;
05645 #endif   /* defined(HAVE_SS7) */
05646       default:
05647          break;
05648       }
05649    }
05650    ast_free(p->cidspill);
05651    if (p->use_smdi)
05652       ast_smdi_interface_unref(p->smdi_iface);
05653    if (p->mwi_event_sub)
05654       ast_event_unsubscribe(p->mwi_event_sub);
05655    if (p->vars) {
05656       ast_variables_destroy(p->vars);
05657    }
05658    if (p->cc_params) {
05659       ast_cc_config_params_destroy(p->cc_params);
05660    }
05661    ast_mutex_destroy(&p->lock);
05662    dahdi_close_sub(p, SUB_REAL);
05663    if (p->owner)
05664       p->owner->tech_pvt = NULL;
05665    ast_free(p);
05666 }

static struct dahdi_pvt* determine_starting_point ( const char *  data,
struct dahdi_starting_point param 
) [static]

Definition at line 13100 of file chan_dahdi.c.

References args, ARRAY_LEN, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), CHAN_PSEUDO, errno, ifend, iflist, dahdi_pvt::next, dahdi_pvt::prev, and round_robin.

Referenced by dahdi_cc_callback(), and dahdi_request().

13101 {
13102    char *dest;
13103    char *s;
13104    int x;
13105    int res = 0;
13106    struct dahdi_pvt *p;
13107    char *subdir = NULL;
13108    AST_DECLARE_APP_ARGS(args,
13109       AST_APP_ARG(group);  /* channel/group token */
13110       //AST_APP_ARG(ext);  /* extension token */
13111       //AST_APP_ARG(opts); /* options token */
13112       AST_APP_ARG(other);  /* Any remining unused arguments */
13113    );
13114 
13115    /*
13116     * data is ---v
13117     * Dial(DAHDI/pseudo[/extension[/options]])
13118     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13119     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13120     * Dial(DAHDI/i<span>[/extension[/options]])
13121     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13122     *
13123     * i - ISDN span channel restriction.
13124     *     Used by CC to ensure that the CC recall goes out the same span.
13125     *     Also to make ISDN channel names dialable when the sequence number
13126     *     is stripped off.  (Used by DTMF attended transfer feature.)
13127     *
13128     * g - channel group allocation search forward
13129     * G - channel group allocation search backward
13130     * r - channel group allocation round robin search forward
13131     * R - channel group allocation round robin search backward
13132     *
13133     * c - Wait for DTMF digit to confirm answer
13134     * r<cadance#> - Set distintive ring cadance number
13135     * d - Force bearer capability for ISDN/SS7 call to digital.
13136     */
13137 
13138    if (data) {
13139       dest = ast_strdupa(data);
13140    } else {
13141       ast_log(LOG_WARNING, "Channel requested with no data\n");
13142       return NULL;
13143    }
13144    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13145    if (!args.argc || ast_strlen_zero(args.group)) {
13146       ast_log(LOG_WARNING, "No channel/group specified\n");
13147       return NULL;
13148    }
13149 
13150    /* Initialize the output parameters */
13151    memset(param, 0, sizeof(*param));
13152    param->channelmatch = -1;
13153 
13154    if (strchr(args.group, '!') != NULL) {
13155       char *prev = args.group;
13156       while ((s = strchr(prev, '!')) != NULL) {
13157          *s++ = '/';
13158          prev = s;
13159       }
13160       *(prev - 1) = '\0';
13161       subdir = args.group;
13162       args.group = prev;
13163    } else if (args.group[0] == 'i') {
13164       /* Extract the ISDN span channel restriction specifier. */
13165       res = sscanf(args.group + 1, "%30d", &x);
13166       if (res < 1) {
13167          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13168          return NULL;
13169       }
13170       param->span = x;
13171 
13172       /* Remove the ISDN span channel restriction specifier. */
13173       s = strchr(args.group, '-');
13174       if (!s) {
13175          /* Search all groups since we are ISDN span restricted. */
13176          return iflist;
13177       }
13178       args.group = s + 1;
13179       res = 0;
13180    }
13181    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13182       /* Retrieve the group number */
13183       s = args.group + 1;
13184       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13185       if (res < 1) {
13186          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13187          return NULL;
13188       }
13189       param->groupmatch = ((ast_group_t) 1 << x);
13190 
13191       if (toupper(args.group[0]) == 'G') {
13192          if (args.group[0] == 'G') {
13193             param->backwards = 1;
13194             p = ifend;
13195          } else
13196             p = iflist;
13197       } else {
13198          if (ARRAY_LEN(round_robin) <= x) {
13199             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13200                x, data);
13201             return NULL;
13202          }
13203          if (args.group[0] == 'R') {
13204             param->backwards = 1;
13205             p = round_robin[x] ? round_robin[x]->prev : ifend;
13206             if (!p)
13207                p = ifend;
13208          } else {
13209             p = round_robin[x] ? round_robin[x]->next : iflist;
13210             if (!p)
13211                p = iflist;
13212          }
13213          param->roundrobin = 1;
13214          param->rr_starting_point = x;
13215       }
13216    } else {
13217       s = args.group;
13218       if (!strcasecmp(s, "pseudo")) {
13219          /* Special case for pseudo */
13220          x = CHAN_PSEUDO;
13221          param->channelmatch = x;
13222       } else {
13223          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13224          if (res < 1) {
13225             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13226             return NULL;
13227          } else {
13228             param->channelmatch = x;
13229          }
13230       }
13231       if (subdir) {
13232          char path[PATH_MAX];
13233          struct stat stbuf;
13234 
13235          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13236                subdir, param->channelmatch);
13237          if (stat(path, &stbuf) < 0) {
13238             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13239                   path, strerror(errno));
13240             return NULL;
13241          }
13242          if (!S_ISCHR(stbuf.st_mode)) {
13243             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13244                   path);
13245             return NULL;
13246          }
13247          param->channelmatch = minor(stbuf.st_rdev);
13248       }
13249 
13250       p = iflist;
13251    }
13252 
13253    if (param->opt == 'r' && res < 3) {
13254       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13255       param->opt = '\0';
13256    }
13257 
13258    return p;
13259 }

static int device2chan ( const char *  subdir,
int  channel,
char *  path,
int  pathlen 
) [static]

Definition at line 11883 of file chan_dahdi.c.

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

Referenced by build_channels().

11884 {
11885    struct stat stbuf;
11886    int      num;
11887 
11888    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
11889    if (stat(path, &stbuf) < 0) {
11890       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
11891       return -errno;
11892    }
11893    if (!S_ISCHR(stbuf.st_mode)) {
11894       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
11895       return -EINVAL;
11896    }
11897    num = minor(stbuf.st_rdev);
11898    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
11899    return num;
11900 
11901 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 4300 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

04301 {
04302    if (isdigit(digit))
04303       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04304    else if (digit >= 'A' && digit <= 'D')
04305       return DAHDI_TONE_DTMF_A + (digit - 'A');
04306    else if (digit >= 'a' && digit <= 'd')
04307       return DAHDI_TONE_DTMF_A + (digit - 'a');
04308    else if (digit == '*')
04309       return DAHDI_TONE_DTMF_s;
04310    else if (digit == '#')
04311       return DAHDI_TONE_DTMF_p;
04312    else
04313       return -1;
04314 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 6460 of file chan_dahdi.c.

References ast_dsp_set_features(), dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_bridge(), and dahdi_setoption().

06461 {
06462    int val = 0;
06463 
06464    p->ignoredtmf = 1;
06465 
06466    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06467 
06468    if (!p->hardwaredtmf && p->dsp) {
06469       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06470       ast_dsp_set_features(p->dsp, p->dsp_features);
06471    }
06472 }

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

Definition at line 11308 of file chan_dahdi.c.

References analog_lib_handles(), ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, ifcount, iflist, iflock, last, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

11309 {
11310    int count, res, res2, spoint, pollres=0;
11311    struct dahdi_pvt *i;
11312    struct dahdi_pvt *last = NULL;
11313    struct dahdi_pvt *doomed;
11314    time_t thispass = 0, lastpass = 0;
11315    int found;
11316    char buf[1024];
11317    struct pollfd *pfds=NULL;
11318    int lastalloc = -1;
11319    /* This thread monitors all the frame relay interfaces which are not yet in use
11320       (and thus do not have a separate thread) indefinitely */
11321    /* From here on out, we die whenever asked */
11322 #if 0
11323    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11324       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11325       return NULL;
11326    }
11327    ast_debug(1, "Monitor starting...\n");
11328 #endif
11329    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11330 
11331    for (;;) {
11332       /* Lock the interface list */
11333       ast_mutex_lock(&iflock);
11334       if (!pfds || (lastalloc != ifcount)) {
11335          if (pfds) {
11336             ast_free(pfds);
11337             pfds = NULL;
11338          }
11339          if (ifcount) {
11340             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11341                ast_mutex_unlock(&iflock);
11342                return NULL;
11343             }
11344          }
11345          lastalloc = ifcount;
11346       }
11347       /* Build the stuff we're going to poll on, that is the socket of every
11348          dahdi_pvt that does not have an associated owner channel */
11349       count = 0;
11350       for (i = iflist; i; i = i->next) {
11351          ast_mutex_lock(&i->lock);
11352          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11353             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11354                struct analog_pvt *p = i->sig_pvt;
11355 
11356                if (!p)
11357                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11358 
11359                if (!p->owner && !p->subs[SUB_REAL].owner) {
11360                   /* This needs to be watched, as it lacks an owner */
11361                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11362                   pfds[count].events = POLLPRI;
11363                   pfds[count].revents = 0;
11364                   /* Message waiting or r2 channels also get watched for reading */
11365                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11366                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11367                      pfds[count].events |= POLLIN;
11368                   }
11369                   count++;
11370                }
11371             } else {
11372                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11373                   /* This needs to be watched, as it lacks an owner */
11374                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11375                   pfds[count].events = POLLPRI;
11376                   pfds[count].revents = 0;
11377                   /* If we are monitoring for VMWI or sending CID, we need to
11378                      read from the channel as well */
11379                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11380                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11381                      pfds[count].events |= POLLIN;
11382                   }
11383                   count++;
11384                }
11385             }
11386          }
11387          ast_mutex_unlock(&i->lock);
11388       }
11389       /* Okay, now that we know what to do, release the interface lock */
11390       ast_mutex_unlock(&iflock);
11391 
11392       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11393       pthread_testcancel();
11394       /* Wait at least a second for something to happen */
11395       res = poll(pfds, count, 1000);
11396       pthread_testcancel();
11397       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11398 
11399       /* Okay, poll has finished.  Let's see what happened.  */
11400       if (res < 0) {
11401          if ((errno != EAGAIN) && (errno != EINTR))
11402             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11403          continue;
11404       }
11405       /* Alright, lock the interface list again, and let's look and see what has
11406          happened */
11407       ast_mutex_lock(&iflock);
11408       found = 0;
11409       spoint = 0;
11410       lastpass = thispass;
11411       thispass = time(NULL);
11412       doomed = NULL;
11413       for (i = iflist;; i = i->next) {
11414          if (doomed) {
11415             int res;
11416             res = dahdi_destroy_channel_bynum(doomed->channel);
11417             if (res != RESULT_SUCCESS) {
11418                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11419             }
11420             doomed = NULL;
11421          }
11422          if (!i) {
11423             break;
11424          }
11425 
11426          if (thispass != lastpass) {
11427             if (!found && ((i == last) || ((i == iflist) && !last))) {
11428                last = i;
11429                if (last) {
11430                   struct analog_pvt *analog_p = last->sig_pvt;
11431                   /* Only allow MWI to be initiated on a quiescent fxs port */
11432                   if (analog_p
11433                      && !last->mwisendactive
11434                      && (last->sig & __DAHDI_SIG_FXO)
11435                      && !analog_p->fxsoffhookstate
11436                      && !last->owner
11437                      && !ast_strlen_zero(last->mailbox)
11438                      && (thispass - analog_p->onhooktime > 3)) {
11439                      res = has_voicemail(last);
11440                      if (analog_p->msgstate != res) {
11441                         /* Set driver resources for signalling VMWI */
11442                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11443                         if (res2) {
11444                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11445                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11446                         }
11447                         /* If enabled for FSK spill then initiate it */
11448                         if (mwi_send_init(last)) {
11449                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11450                         }
11451                         analog_p->msgstate = res;
11452                         found ++;
11453                      }
11454                   }
11455                   last = last->next;
11456                }
11457             }
11458          }
11459          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11460             if (i->radio && !i->owner)
11461             {
11462                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11463                if (res)
11464                {
11465                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11466                   /* Don't hold iflock while handling init events */
11467                   ast_mutex_unlock(&iflock);
11468                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11469                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11470                   else
11471                      doomed = handle_init_event(i, res);
11472                   ast_mutex_lock(&iflock);
11473                }
11474                continue;
11475             }
11476             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11477             if (pollres & POLLIN) {
11478                if (i->owner || i->subs[SUB_REAL].owner) {
11479 #ifdef HAVE_PRI
11480                   if (!i->pri)
11481 #endif
11482                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11483                   continue;
11484                }
11485                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11486                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11487                   continue;
11488                }
11489                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11490                if (res > 0) {
11491                   if (i->mwimonitor_fsk) {
11492                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11493                         pthread_attr_t attr;
11494                         pthread_t threadid;
11495                         struct mwi_thread_data *mtd;
11496 
11497                         pthread_attr_init(&attr);
11498                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11499 
11500                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11501                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11502                            mtd->pvt = i;
11503                            memcpy(mtd->buf, buf, res);
11504                            mtd->len = res;
11505                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11506                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11507                               ast_free(mtd);
11508                            }
11509                            i->mwimonitoractive = 1;
11510                         }
11511                      }
11512                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11513                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11514                      int energy;
11515                      struct timeval now;
11516                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11517                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11518                      */
11519                      if (1 == i->dtmfcid_holdoff_state) {
11520                         gettimeofday(&i->dtmfcid_delay, NULL);
11521                         i->dtmfcid_holdoff_state = 2;
11522                      } else if (2 == i->dtmfcid_holdoff_state) {
11523                         gettimeofday(&now, NULL);
11524                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11525                            i->dtmfcid_holdoff_state = 0;
11526                         }
11527                      } else {
11528                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11529                         if (!i->mwisendactive && energy > dtmfcid_level) {
11530                            pthread_t threadid;
11531                            struct ast_channel *chan;
11532                            ast_mutex_unlock(&iflock);
11533                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11534                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11535                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11536                               i->dtmfcid_holdoff_state = 1;
11537                            } else {
11538                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11539                               if (!chan) {
11540                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11541                               } else {
11542                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11543                                  if (res) {
11544                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11545                                  } else {
11546                                     i->dtmfcid_holdoff_state = 1;
11547                                  }
11548                               }
11549                            }
11550                            ast_mutex_lock(&iflock);
11551                         }
11552                      }
11553                   }
11554                   if (i->mwisendactive) {
11555                      mwi_send_process_buffer(i, res);
11556                   }
11557                } else {
11558                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11559                }
11560             }
11561             if (pollres & POLLPRI) {
11562                if (i->owner || i->subs[SUB_REAL].owner) {
11563 #ifdef HAVE_PRI
11564                   if (!i->pri)
11565 #endif
11566                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11567                   continue;
11568                }
11569                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11570                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11571                /* Don't hold iflock while handling init events */
11572                ast_mutex_unlock(&iflock);
11573                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11574                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11575                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11576                   else
11577                      doomed = handle_init_event(i, res);
11578                }
11579                ast_mutex_lock(&iflock);
11580             }
11581          }
11582       }
11583       ast_mutex_unlock(&iflock);
11584    }
11585    /* Never reached */
11586    return NULL;
11587 
11588 }

static int drc_sample ( int  sample,
float  drc 
) [static]

Definition at line 4839 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

04840 {
04841    float neg;
04842    float shallow, steep;
04843    float max = SHRT_MAX;
04844    
04845    neg = (sample < 0 ? -1 : 1);
04846    steep = drc*sample;
04847    shallow = neg*(max-max/drc)+(float)sample/drc;
04848    if (abs(steep) < abs(shallow)) {
04849       sample = steep;
04850    }
04851    else {
04852       sample = shallow;
04853    }
04854 
04855    return sample;
04856 }

static struct dahdi_pvt* duplicate_pseudo ( struct dahdi_pvt src  )  [static]

Definition at line 13036 of file chan_dahdi.c.

References ast_cc_config_params_init, ast_cc_copy_config_params(), ast_free, ast_log(), ast_malloc, ast_mutex_init, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::cc_params, dahdi_iflist_insert(), DAHDI_IFLIST_NONE, dahdi_open(), destroy_dahdi_pvt(), errno, and SUB_REAL.

Referenced by dahdi_request().

13037 {
13038    struct dahdi_pvt *p;
13039    struct dahdi_bufferinfo bi;
13040    int res;
13041 
13042    p = ast_malloc(sizeof(*p));
13043    if (!p) {
13044       return NULL;
13045    }
13046    *p = *src;
13047 
13048    /* Must deep copy the cc_params. */
13049    p->cc_params = ast_cc_config_params_init();
13050    if (!p->cc_params) {
13051       ast_free(p);
13052       return NULL;
13053    }
13054    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13055 
13056    p->which_iflist = DAHDI_IFLIST_NONE;
13057    p->next = NULL;
13058    p->prev = NULL;
13059    ast_mutex_init(&p->lock);
13060    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13061    if (p->subs[SUB_REAL].dfd < 0) {
13062       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13063       destroy_dahdi_pvt(p);
13064       return NULL;
13065    }
13066    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13067    if (!res) {
13068       bi.txbufpolicy = src->buf_policy;
13069       bi.rxbufpolicy = src->buf_policy;
13070       bi.numbufs = src->buf_no;
13071       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13072       if (res < 0) {
13073          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13074       }
13075    } else
13076       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13077    p->destroy = 1;
13078    dahdi_iflist_insert(p);
13079    return p;
13080 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 6474 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_setoption().

06475 {
06476    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06477 
06478    if (p->channel == CHAN_PSEUDO)
06479       return;
06480 
06481    p->ignoredtmf = 0;
06482 
06483    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06484 
06485    if (!p->hardwaredtmf && p->dsp) {
06486       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06487       ast_dsp_set_features(p->dsp, p->dsp_features);
06488    }
06489 }

static const char * event2str ( int  event  )  [static]

Definition at line 4452 of file chan_dahdi.c.

References ARRAY_LEN.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), mwi_thread(), my_distinctive_ring(), my_handle_dchan_exception(), and my_handle_link_exception().

04453 {
04454    static char buf[256];
04455    if ((event < (ARRAY_LEN(events))) && (event > -1))
04456       return events[event];
04457    sprintf(buf, "Event %d", event); /* safe */
04458    return buf;
04459 }

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

Definition at line 4903 of file chan_dahdi.c.

References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().

Referenced by set_actual_rxgain().

04904 {
04905    int j;
04906    int k;
04907    float linear_gain = pow(10.0, gain / 20.0);
04908 
04909    switch (law) {
04910    case DAHDI_LAW_ALAW:
04911       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04912          if (gain || drc) {
04913             k = AST_ALAW(j);
04914             if (drc) {
04915                k = drc_sample(k, drc);
04916             }
04917             k = (float)k*linear_gain;
04918             if (k > 32767) k = 32767;
04919             if (k < -32767) k = -32767;
04920             g->rxgain[j] = AST_LIN2A(k);
04921          } else {
04922             g->rxgain[j] = j;
04923          }
04924       }
04925       break;
04926    case DAHDI_LAW_MULAW:
04927       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04928          if (gain || drc) {
04929             k = AST_MULAW(j);
04930             if (drc) {
04931                k = drc_sample(k, drc);
04932             }
04933             k = (float)k*linear_gain;
04934             if (k > 32767) k = 32767;
04935             if (k < -32767) k = -32767;
04936             g->rxgain[j] = AST_LIN2MU(k);
04937          } else {
04938             g->rxgain[j] = j;
04939          }
04940       }
04941       break;
04942    }
04943 }

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

Definition at line 4859 of file chan_dahdi.c.

References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().

Referenced by set_actual_txgain().

04860 {
04861    int j;
04862    int k;
04863 
04864    float linear_gain = pow(10.0, gain / 20.0);
04865 
04866    switch (law) {
04867    case DAHDI_LAW_ALAW:
04868       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04869          if (gain || drc) {
04870             k = AST_ALAW(j);
04871             if (drc) {
04872                k = drc_sample(k, drc);
04873             }
04874             k = (float)k*linear_gain;
04875             if (k > 32767) k = 32767;
04876             if (k < -32767) k = -32767;
04877             g->txgain[j] = AST_LIN2A(k);
04878          } else {
04879             g->txgain[j] = j;
04880          }
04881       }
04882       break;
04883    case DAHDI_LAW_MULAW:
04884       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04885          if (gain || drc) {
04886             k = AST_MULAW(j);
04887             if (drc) {
04888                k = drc_sample(k, drc);
04889             }
04890             k = (float)k*linear_gain;
04891             if (k > 32767) k = 32767;
04892             if (k < -32767) k = -32767;
04893             g->txgain[j] = AST_LIN2MU(k);
04894 
04895          } else {
04896             g->txgain[j] = j;
04897          }
04898       }
04899       break;
04900    }
04901 }

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

Definition at line 15438 of file chan_dahdi.c.

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

Referenced by action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_transfer(), and action_transferhangup().

15439 {
15440    struct dahdi_pvt *p;
15441 
15442    ast_mutex_lock(&iflock);
15443    for (p = iflist; p; p = p->next) {
15444       if (p->channel == channel) {
15445          break;
15446       }
15447    }
15448    ast_mutex_unlock(&iflock);
15449    return p;
15450 }

static struct dahdi_pvt* find_next_iface_in_span ( struct dahdi_pvt cur  )  [static]

Definition at line 5587 of file chan_dahdi.c.

References dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::span.

Referenced by destroy_dahdi_pvt().

05588 {
05589    if (cur->next && cur->next->span == cur->span) {
05590       return cur->next;
05591    } else if (cur->prev && cur->prev->span == cur->span) {
05592       return cur->prev;
05593    }
05594 
05595    return NULL;
05596 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

Checks channel for alarms

Parameters:
p a channel to check for alarms.
Returns:
the alarms on the span to which the channel belongs, or alarms on the channel if no span alarms.

Definition at line 7498 of file chan_dahdi.c.

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

Referenced by action_dahdishowchannels(), dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), handle_init_event(), mwi_thread(), and my_get_and_handle_alarms().

07499 {
07500    int res;
07501    struct dahdi_spaninfo zi;
07502    struct dahdi_params params;
07503 
07504    memset(&zi, 0, sizeof(zi));
07505    zi.spanno = p->span;
07506 
07507    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07508       if (zi.alarms != DAHDI_ALARM_NONE)
07509          return zi.alarms;
07510    } else {
07511       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07512       return 0;
07513    }
07514 
07515    /* No alarms on the span. Check for channel alarms. */
07516    memset(&params, 0, sizeof(params));
07517    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07518       return params.chan_alarms;
07519 
07520    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07521 
07522    return DAHDI_ALARM_NONE;
07523 }

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

Definition at line 7623 of file chan_dahdi.c.

References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event, dahdi_pvt::manages_span_alarms, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, and dahdi_pvt::span.

Referenced by dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), handle_init_event(), mwi_thread(), and my_get_and_handle_alarms().

07624 {
07625    const char *alarm_str = alarm2str(alms);
07626 
07627    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07628       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07629       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07630                  "Alarm: %s\r\n"
07631                  "Channel: %d\r\n",
07632                  alarm_str, p->channel);
07633    }
07634 
07635    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07636       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07637       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07638                  "Alarm: %s\r\n"
07639                  "Span: %d\r\n",
07640                  alarm_str, p->span);
07641    }
07642 }

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3675 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, LOG_NOTICE, manager_event, dahdi_pvt::manages_span_alarms, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, and dahdi_pvt::span.

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

03676 {
03677    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03678       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03679       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03680    }
03681    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03682       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03683       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03684    }
03685 }

static char* handle_dahdi_show_cadences ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15056 of file chan_dahdi.c.

References ast_cli(), cadences, cidrings, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, ast_cli_args::fd, num_cadence, term_color(), and ast_cli_entry::usage.

15057 {
15058    int i, j;
15059    switch (cmd) {
15060    case CLI_INIT:
15061       e->command = "dahdi show cadences";
15062       e->usage =
15063          "Usage: dahdi show cadences\n"
15064          "       Shows all cadences currently defined\n";
15065       return NULL;
15066    case CLI_GENERATE:
15067       return NULL;
15068    }
15069    for (i = 0; i < num_cadence; i++) {
15070       char output[1024];
15071       char tmp[16], tmp2[64];
15072       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15073       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15074 
15075       for (j = 0; j < 16; j++) {
15076          if (cadences[i].ringcadence[j] == 0)
15077             break;
15078          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15079          if (cidrings[i] * 2 - 1 == j)
15080             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15081          else
15082             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15083          if (j != 0)
15084             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15085          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15086       }
15087       ast_cli(a->fd,"%s\n",output);
15088    }
15089    return CLI_SUCCESS;
15090 }

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

Definition at line 11066 of file chan_dahdi.c.

References analog_ss_thread(), ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, 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_pri_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), SUB_REAL, and dahdi_pvt::subs.

11067 {
11068    int res;
11069    pthread_t threadid;
11070    struct ast_channel *chan;
11071 
11072    /* Handle an event on a given channel for the monitor thread. */
11073 
11074    switch (event) {
11075    case DAHDI_EVENT_NONE:
11076    case DAHDI_EVENT_BITSCHANGED:
11077       break;
11078    case DAHDI_EVENT_WINKFLASH:
11079    case DAHDI_EVENT_RINGOFFHOOK:
11080       if (i->inalarm) break;
11081       if (i->radio) break;
11082       /* Got a ring/answer.  What kind of channel are we? */
11083       switch (i->sig) {
11084       case SIG_FXOLS:
11085       case SIG_FXOGS:
11086       case SIG_FXOKS:
11087          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11088          if (res && (errno == EBUSY))
11089             break;
11090 
11091          /* Cancel VMWI spill */
11092          ast_free(i->cidspill);
11093          i->cidspill = NULL;
11094          restore_conference(i);
11095 
11096          if (i->immediate) {
11097             dahdi_enable_ec(i);
11098             /* The channel is immediately up.  Start right away */
11099             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11100             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11101             if (!chan) {
11102                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11103                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11104                if (res < 0)
11105                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11106             }
11107          } else {
11108             /* Check for callerid, digits, etc */
11109             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11110             if (chan) {
11111                if (has_voicemail(i))
11112                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11113                else
11114                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11115                if (res < 0)
11116                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11117                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11118                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11119                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11120                   if (res < 0)
11121                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11122                   ast_hangup(chan);
11123                }
11124             } else
11125                ast_log(LOG_WARNING, "Unable to create channel\n");
11126          }
11127          break;
11128       case SIG_FXSLS:
11129       case SIG_FXSGS:
11130       case SIG_FXSKS:
11131             i->ringt = i->ringt_base;
11132             /* Fall through */
11133       case SIG_EMWINK:
11134       case SIG_FEATD:
11135       case SIG_FEATDMF:
11136       case SIG_FEATDMF_TA:
11137       case SIG_E911:
11138       case SIG_FGC_CAMA:
11139       case SIG_FGC_CAMAMF:
11140       case SIG_FEATB:
11141       case SIG_EM:
11142       case SIG_EM_E1:
11143       case SIG_SFWINK:
11144       case SIG_SF_FEATD:
11145       case SIG_SF_FEATDMF:
11146       case SIG_SF_FEATB:
11147       case SIG_SF:
11148          /* Check for callerid, digits, etc */
11149          if (i->cid_start == CID_START_POLARITY_IN) {
11150             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11151          } else {
11152             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11153          }
11154 
11155          if (!chan) {
11156             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11157          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11158             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11159             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11160             if (res < 0) {
11161                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11162             }
11163             ast_hangup(chan);
11164          }
11165          break;
11166       default:
11167          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11168          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11169          if (res < 0)
11170             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11171          return NULL;
11172       }
11173       break;
11174    case DAHDI_EVENT_NOALARM:
11175       switch (i->sig) {
11176 #if defined(HAVE_PRI)
11177       case SIG_PRI_LIB_HANDLE_CASES:
11178          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11179          break;
11180 #endif   /* defined(HAVE_PRI) */
11181 #if defined(HAVE_SS7)
11182       case SIG_SS7:
11183          sig_ss7_set_alarm(i->sig_pvt, 0);
11184          break;
11185 #endif   /* defined(HAVE_SS7) */
11186       default:
11187          i->inalarm = 0;
11188          break;
11189       }
11190       handle_clear_alarms(i);
11191       break;
11192    case DAHDI_EVENT_ALARM:
11193       switch (i->sig) {
11194 #if defined(HAVE_PRI)
11195       case SIG_PRI_LIB_HANDLE_CASES:
11196          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11197          break;
11198 #endif   /* defined(HAVE_PRI) */
11199 #if defined(HAVE_SS7)
11200       case SIG_SS7:
11201          sig_ss7_set_alarm(i->sig_pvt, 1);
11202          break;
11203 #endif   /* defined(HAVE_SS7) */
11204       default:
11205          i->inalarm = 1;
11206          break;
11207       }
11208       res = get_alarms(i);
11209       handle_alarms(i, res);
11210       /* fall thru intentionally */
11211    case DAHDI_EVENT_ONHOOK:
11212       if (i->radio)
11213          break;
11214       /* Back on hook.  Hang up. */
11215       switch (i->sig) {
11216       case SIG_FXOLS:
11217       case SIG_FXOGS:
11218       case SIG_FEATD:
11219       case SIG_FEATDMF:
11220       case SIG_FEATDMF_TA:
11221       case SIG_E911:
11222       case SIG_FGC_CAMA:
11223       case SIG_FGC_CAMAMF:
11224       case SIG_FEATB:
11225       case SIG_EM:
11226       case SIG_EM_E1:
11227       case SIG_EMWINK:
11228       case SIG_SF_FEATD:
11229       case SIG_SF_FEATDMF:
11230       case SIG_SF_FEATB:
11231       case SIG_SF:
11232       case SIG_SFWINK:
11233       case SIG_FXSLS:
11234       case SIG_FXSGS:
11235       case SIG_FXSKS:
11236       case SIG_FXOKS:
11237          dahdi_disable_ec(i);
11238          /* Diddle the battery for the zhone */
11239 #ifdef ZHONE_HACK
11240          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11241          usleep(1);
11242 #endif
11243          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11244          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11245          break;
11246       case SIG_SS7:
11247       case SIG_PRI_LIB_HANDLE_CASES:
11248          dahdi_disable_ec(i);
11249          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11250          break;
11251       default:
11252          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11253          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11254          return NULL;
11255       }
11256       break;
11257    case DAHDI_EVENT_POLARITY:
11258       switch (i->sig) {
11259       case SIG_FXSLS:
11260       case SIG_FXSKS:
11261       case SIG_FXSGS:
11262          /* We have already got a PR before the channel was
11263             created, but it wasn't handled. We need polarity
11264             to be REV for remote hangup detection to work.
11265             At least in Spain */
11266          if (i->hanguponpolarityswitch)
11267             i->polarity = POLARITY_REV;
11268          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11269             i->polarity = POLARITY_REV;
11270             ast_verb(2, "Starting post polarity "
11271                "CID detection on channel %d\n",
11272                i->channel);
11273             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11274             if (!chan) {
11275                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11276             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11277                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11278             }
11279          }
11280          break;
11281       default:
11282          ast_log(LOG_WARNING, "handle_init_event detected "
11283             "polarity reversal on non-FXO (SIG_FXS) "
11284             "interface %d\n", i->channel);
11285       }
11286       break;
11287    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11288       ast_log(LOG_NOTICE,
11289             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11290             i->channel);
11291       return i;
11292    case DAHDI_EVENT_NEONMWI_ACTIVE:
11293       if (i->mwimonitor_neon) {
11294          notify_message(i->mailbox, 1);
11295          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11296       }
11297       break;
11298    case DAHDI_EVENT_NEONMWI_INACTIVE:
11299       if (i->mwimonitor_neon) {
11300          notify_message(i->mailbox, 0);
11301          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11302       }
11303       break;
11304    }
11305    return NULL;
11306 }

static char* handle_mfcr2_call_files ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14427 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14428 {
14429    struct dahdi_pvt *p = NULL;
14430    int channo = 0;
14431    switch (cmd) {
14432    case CLI_INIT:
14433       e->command = "mfcr2 call files [on|off]";
14434       e->usage =
14435          "Usage: mfcr2 call files [on|off] <channel>\n"
14436          "       Enable call files creation on the specified channel.\n"
14437          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14438       return NULL;
14439    case CLI_GENERATE:
14440       return NULL;
14441    }
14442    if (a->argc < 4) {
14443       return CLI_SHOWUSAGE;
14444    }
14445    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14446    ast_mutex_lock(&iflock);
14447    for (p = iflist; p; p = p->next) {
14448       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14449          continue;
14450       }
14451       if ((channo != -1) && (p->channel != channo )) {
14452          continue;
14453       }
14454       if (ast_true(a->argv[3])) {
14455          openr2_chan_enable_call_files(p->r2chan);
14456       } else {
14457          openr2_chan_disable_call_files(p->r2chan);
14458       }
14459       if (channo != -1) {
14460          if (ast_true(a->argv[3])) {
14461             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14462          } else {
14463             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14464          }
14465          break;
14466       }
14467    }
14468    if ((channo != -1) && !p) {
14469       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14470    }
14471    if (channo == -1) {
14472       if (ast_true(a->argv[3])) {
14473          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14474       } else {
14475          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14476       }
14477    }
14478    ast_mutex_unlock(&iflock);
14479    return CLI_SUCCESS;
14480 }

static char* handle_mfcr2_set_blocked ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14523 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14524 {
14525    struct dahdi_pvt *p = NULL;
14526    int channo = 0;
14527    switch (cmd) {
14528    case CLI_INIT:
14529       e->command = "mfcr2 set blocked";
14530       e->usage =
14531          "Usage: mfcr2 set blocked <channel>\n"
14532          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14533          "       Force the given channel into BLOCKED state.\n"
14534          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14535       return NULL;
14536    case CLI_GENERATE:
14537       return NULL;
14538    }
14539    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14540    ast_mutex_lock(&iflock);
14541    for (p = iflist; p; p = p->next) {
14542       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14543          continue;
14544       }
14545       if ((channo != -1) && (p->channel != channo )) {
14546          continue;
14547       }
14548       openr2_chan_set_blocked(p->r2chan);
14549       ast_mutex_lock(&p->lock);
14550       p->locallyblocked = 1;
14551       ast_mutex_unlock(&p->lock);
14552       if (channo != -1) {
14553          break;
14554       }
14555    }
14556    if ((channo != -1) && !p) {
14557       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14558    }
14559    ast_mutex_unlock(&iflock);
14560    return CLI_SUCCESS;
14561 }

static char* handle_mfcr2_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14362 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_strdupa, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14363 {
14364    struct dahdi_pvt *p = NULL;
14365    int channo = 0;
14366    char *toklevel = NULL;
14367    char *saveptr = NULL;
14368    char *logval = NULL;
14369    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14370    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14371    switch (cmd) {
14372    case CLI_INIT:
14373       e->command = "mfcr2 set debug";
14374       e->usage =
14375          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14376          "       Set a new logging level for the specified channel.\n"
14377          "       If no channel is specified the logging level will be applied to all channels.\n";
14378       return NULL;
14379    case CLI_GENERATE:
14380       return NULL;
14381    }
14382    if (a->argc < 4) {
14383       return CLI_SHOWUSAGE;
14384    }
14385    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14386    logval = ast_strdupa(a->argv[3]);
14387    toklevel = strtok_r(logval, ",", &saveptr);
14388    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14389       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14390       return CLI_FAILURE;
14391    } else if (OR2_LOG_NOTHING == tmplevel) {
14392       loglevel = tmplevel;
14393    } else {
14394       loglevel |= tmplevel;
14395       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14396          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14397             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14398             continue;
14399          }
14400          loglevel |= tmplevel;
14401       }
14402    }
14403    ast_mutex_lock(&iflock);
14404    for (p = iflist; p; p = p->next) {
14405       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14406          continue;
14407       }
14408       if ((channo != -1) && (p->channel != channo )) {
14409          continue;
14410       }
14411       openr2_chan_set_log_level(p->r2chan, loglevel);
14412       if (channo != -1) {
14413          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14414          break;
14415       }
14416    }
14417    if ((channo != -1) && !p) {
14418       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14419    }
14420    if (channo == -1) {
14421       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14422    }
14423    ast_mutex_unlock(&iflock);
14424    return CLI_SUCCESS;
14425 }

static char* handle_mfcr2_set_idle ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14482 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14483 {
14484    struct dahdi_pvt *p = NULL;
14485    int channo = 0;
14486    switch (cmd) {
14487    case CLI_INIT:
14488       e->command = "mfcr2 set idle";
14489       e->usage =
14490          "Usage: mfcr2 set idle <channel>\n"
14491          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14492          "       Force the given channel into IDLE state.\n"
14493          "       If no channel is specified, all channels will be set to IDLE.\n";
14494       return NULL;
14495    case CLI_GENERATE:
14496       return NULL;
14497    }
14498    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14499    ast_mutex_lock(&iflock);
14500    for (p = iflist; p; p = p->next) {
14501       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14502          continue;
14503       }
14504       if ((channo != -1) && (p->channel != channo )) {
14505          continue;
14506       }
14507       openr2_chan_set_idle(p->r2chan);
14508       ast_mutex_lock(&p->lock);
14509       p->locallyblocked = 0;
14510       p->mfcr2call = 0;
14511       ast_mutex_unlock(&p->lock);
14512       if (channo != -1) {
14513          break;
14514       }
14515    }
14516    if ((channo != -1) && !p) {
14517       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14518    }
14519    ast_mutex_unlock(&iflock);
14520    return CLI_SUCCESS;
14521 }

static char* handle_mfcr2_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14288 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::context, ast_cli_args::fd, FORMAT, dahdi_pvt::group, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14289 {
14290 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14291    int filtertype = 0;
14292    int targetnum = 0;
14293    char channo[5];
14294    char anino[5];
14295    char dnisno[5];
14296    struct dahdi_pvt *p;
14297    openr2_context_t *r2context;
14298    openr2_variant_t r2variant;
14299    switch (cmd) {
14300    case CLI_INIT:
14301       e->command = "mfcr2 show channels [group|context]";
14302       e->usage =
14303          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14304          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14305       return NULL;
14306    case CLI_GENERATE:
14307       return NULL;
14308    }
14309    if (!((a->argc == 3) || (a->argc == 5))) {
14310       return CLI_SHOWUSAGE;
14311    }
14312    if (a->argc == 5) {
14313       if (!strcasecmp(a->argv[3], "group")) {
14314          targetnum = atoi(a->argv[4]);
14315          if ((targetnum < 0) || (targetnum > 63))
14316             return CLI_SHOWUSAGE;
14317          targetnum = 1 << targetnum;
14318          filtertype = 1;
14319       } else if (!strcasecmp(a->argv[3], "context")) {
14320          filtertype = 2;
14321       } else {
14322          return CLI_SHOWUSAGE;
14323       }
14324    }
14325    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14326    ast_mutex_lock(&iflock);
14327    for (p = iflist; p; p = p->next) {
14328       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14329          continue;
14330       }
14331       if (filtertype) {
14332          switch(filtertype) {
14333          case 1: /* mfcr2 show channels group <group> */
14334             if (p->group != targetnum) {
14335                continue;
14336             }
14337             break;
14338          case 2: /* mfcr2 show channels context <context> */
14339             if (strcasecmp(p->context, a->argv[4])) {
14340                continue;
14341             }
14342             break;
14343          default:
14344             ;
14345          }
14346       }
14347       r2context = openr2_chan_get_context(p->r2chan);
14348       r2variant = openr2_context_get_variant(r2context);
14349       snprintf(channo, sizeof(channo), "%d", p->channel);
14350       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14351       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14352       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14353             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14354             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14355             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14356    }
14357    ast_mutex_unlock(&iflock);
14358    return CLI_SUCCESS;
14359 #undef FORMAT
14360 }

static char* handle_mfcr2_show_variants ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14260 of file chan_dahdi.c.

References ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, and ast_cli_entry::usage.

14261 {
14262 #define FORMAT "%4s %40s\n"
14263    int i = 0;
14264    int numvariants = 0;
14265    const openr2_variant_entry_t *variants;
14266    switch (cmd) {
14267    case CLI_INIT:
14268       e->command = "mfcr2 show variants";
14269       e->usage =
14270          "Usage: mfcr2 show variants\n"
14271          "       Shows the list of MFC/R2 variants supported.\n";
14272       return NULL;
14273    case CLI_GENERATE:
14274       return NULL;
14275    }
14276    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14277       ast_cli(a->fd, "Failed to get list of variants.\n");
14278       return CLI_FAILURE;
14279    }
14280    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14281    for (i = 0; i < numvariants; i++) {
14282       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14283    }
14284    return CLI_SUCCESS;
14285 #undef FORMAT
14286 }

static char* handle_mfcr2_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14244 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

14245 {
14246    switch (cmd) {
14247    case CLI_INIT:
14248       e->command = "mfcr2 show version";
14249       e->usage =
14250          "Usage: mfcr2 show version\n"
14251          "       Shows the version of the OpenR2 library being used.\n";
14252       return NULL;
14253    case CLI_GENERATE:
14254       return NULL;
14255    }
14256    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14257    return CLI_SUCCESS;
14258 }

static char* handle_pri_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 13890 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, dahdi_pri::pri, pris, SIG_PRI_DEBUG_INTENSE, SIG_PRI_DEBUG_NORMAL, ast_cli_entry::usage, and ast_cli_args::word.

13891 {
13892    int span;
13893    int x;
13894    int level = 0;
13895    switch (cmd) {
13896    case CLI_INIT:
13897       e->command = "pri set debug {on|off|0|1|2} span";
13898       e->usage =
13899          "Usage: pri set debug {<level>|on|off} span <span>\n"
13900          "       Enables debugging on a given PRI span\n";
13901       return NULL;
13902    case CLI_GENERATE:
13903       return complete_span_4(a->line, a->word, a->pos, a->n);
13904    }
13905    if (a->argc < 6) {
13906       return CLI_SHOWUSAGE;
13907    }
13908 
13909    if (!strcasecmp(a->argv[3], "on")) {
13910       level = 1;
13911    } else if (!strcasecmp(a->argv[3], "off")) {
13912       level = 0;
13913    } else {
13914       level = atoi(a->argv[3]);
13915    }
13916    span = atoi(a->argv[5]);
13917    if ((span < 1) || (span > NUM_SPANS)) {
13918       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13919       return CLI_SUCCESS;
13920    }
13921    if (!pris[span-1].pri.pri) {
13922       ast_cli(a->fd, "No PRI running on span %d\n", span);
13923       return CLI_SUCCESS;
13924    }
13925 
13926    /* Set debug level in libpri */
13927    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
13928       if (pris[span - 1].pri.dchans[x]) {
13929          switch (level) {
13930          case 0:
13931             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
13932             break;
13933          case 1:
13934             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
13935             break;
13936          default:
13937             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
13938             break;
13939          }
13940       }
13941    }
13942    if (level == 0) {
13943       /* Close the debugging file if it's set */
13944       ast_mutex_lock(&pridebugfdlock);
13945       if (0 <= pridebugfd) {
13946          close(pridebugfd);
13947          pridebugfd = -1;
13948          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
13949             pridebugfilename);
13950       }
13951       ast_mutex_unlock(&pridebugfdlock);
13952    }
13953    pris[span - 1].pri.debug = (level) ? 1 : 0;
13954    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
13955    return CLI_SUCCESS;
13956 }

static char* handle_pri_service_disable_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14085 of file chan_dahdi.c.

References CLI_GENERATE, CLI_INIT, ast_cli_entry::command, handle_pri_service_generic(), and ast_cli_entry::usage.

14086 {
14087    switch (cmd) {
14088    case CLI_INIT:
14089       e->command = "pri service disable channel";
14090       e->usage =
14091          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14092          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14093          "  to remove a channel from service, with optional interface id\n"
14094          "  as agreed upon with remote switch operator\n";
14095       return NULL;
14096    case CLI_GENERATE:
14097       return NULL;
14098    }
14099    return handle_pri_service_generic(e, cmd, a, 2);
14100 }

static char* handle_pri_service_enable_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14068 of file chan_dahdi.c.

References CLI_GENERATE, CLI_INIT, ast_cli_entry::command, handle_pri_service_generic(), and ast_cli_entry::usage.

14069 {
14070    switch (cmd) {
14071    case CLI_INIT:
14072       e->command = "pri service enable channel";
14073       e->usage =
14074          "Usage: pri service enable channel <channel> [<interface id>]\n"
14075          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14076          "  to restore a channel to service, with optional interface id\n"
14077          "  as agreed upon with remote switch operator\n";
14078       return NULL;
14079    case CLI_GENERATE:
14080       return NULL;
14081    }
14082    return handle_pri_service_generic(e, cmd, a, 0);
14083 }

static char* handle_pri_service_generic ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a,
int  changestatus 
) [static]

Definition at line 13960 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_FAILURE, CLI_SHOWUSAGE, ast_cli_args::fd, dahdi_pri::pri, pris, and sig_pri_span::trunkgroup.

Referenced by handle_pri_service_disable_channel(), and handle_pri_service_enable_channel().

13961 {
13962    unsigned *why;
13963    int channel;
13964    int trunkgroup;
13965    int x, y, fd = a->fd;
13966    int interfaceid = 0;
13967    char *c;
13968    char db_chan_name[20], db_answer[5];
13969    struct dahdi_pvt *tmp;
13970    struct dahdi_pri *pri;
13971 
13972    if (a->argc < 5 || a->argc > 6)
13973       return CLI_SHOWUSAGE;
13974    if ((c = strchr(a->argv[4], ':'))) {
13975       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
13976          return CLI_SHOWUSAGE;
13977       if ((trunkgroup < 1) || (channel < 1))
13978          return CLI_SHOWUSAGE;
13979       pri = NULL;
13980       for (x=0;x<NUM_SPANS;x++) {
13981          if (pris[x].pri.trunkgroup == trunkgroup) {
13982             pri = pris + x;
13983             break;
13984          }
13985       }
13986       if (!pri) {
13987          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13988          return CLI_FAILURE;
13989       }
13990    } else
13991       channel = atoi(a->argv[4]);
13992 
13993    if (a->argc == 6)
13994       interfaceid = atoi(a->argv[5]);
13995 
13996    /* either servicing a D-Channel */
13997    for (x = 0; x < NUM_SPANS; x++) {
13998       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13999          if (pris[x].dchannels[y] == channel) {
14000             pri = pris + x;
14001             if (pri->pri.enable_service_message_support) {
14002                ast_mutex_lock(&pri->pri.lock);
14003                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14004                ast_mutex_unlock(&pri->pri.lock);
14005             } else {
14006                ast_cli(fd,
14007                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14008                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14009             }
14010             return CLI_SUCCESS;
14011          }
14012       }
14013    }
14014 
14015    /* or servicing a B-Channel */
14016    ast_mutex_lock(&iflock);
14017    for (tmp = iflist; tmp; tmp = tmp->next) {
14018       if (tmp->pri && tmp->channel == channel) {
14019          ast_mutex_unlock(&iflock);
14020          ast_mutex_lock(&tmp->pri->lock);
14021          if (!tmp->pri->enable_service_message_support) {
14022             ast_mutex_unlock(&tmp->pri->lock);
14023             ast_cli(fd,
14024                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14025                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14026             return CLI_SUCCESS;
14027          }
14028          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14029          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14030          switch(changestatus) {
14031          case 0: /* enable */
14032             /* Near end wants to be in service now. */
14033             ast_db_del(db_chan_name, SRVST_DBKEY);
14034             *why &= ~SRVST_NEAREND;
14035             if (*why) {
14036                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14037                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14038             } else {
14039                dahdi_pri_update_span_devstate(tmp->pri);
14040             }
14041             break;
14042          /* case 1:  -- loop */
14043          case 2: /* disable */
14044             /* Near end wants to be out-of-service now. */
14045             ast_db_del(db_chan_name, SRVST_DBKEY);
14046             *why |= SRVST_NEAREND;
14047             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14048             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14049             dahdi_pri_update_span_devstate(tmp->pri);
14050             break;
14051          /* case 3:  -- continuity */
14052          /* case 4:  -- shutdown */
14053          default:
14054             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14055             break;
14056          }
14057          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14058          ast_mutex_unlock(&tmp->pri->lock);
14059          return CLI_SUCCESS;
14060       }
14061    }
14062    ast_mutex_unlock(&iflock);
14063 
14064    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14065    return CLI_FAILURE;
14066 }

static char* handle_pri_set_debug_file ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 13852 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), AST_FILE_MODE, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfd, pridebugfdlock, pridebugfilename, and ast_cli_entry::usage.

13853 {
13854    int myfd;
13855    switch (cmd) {
13856    case CLI_INIT:
13857       e->command = "pri set debug file";
13858       e->usage = "Usage: pri set debug file [output-file]\n"
13859          "       Sends PRI debug output to the specified output file\n";
13860       return NULL;
13861    case CLI_GENERATE:
13862       return NULL;
13863    }
13864    if (a->argc < 5)
13865       return CLI_SHOWUSAGE;
13866 
13867    if (ast_strlen_zero(a->argv[4]))
13868       return CLI_SHOWUSAGE;
13869 
13870    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13871    if (myfd < 0) {
13872       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13873       return CLI_SUCCESS;
13874    }
13875 
13876    ast_mutex_lock(&pridebugfdlock);
13877 
13878    if (pridebugfd >= 0)
13879       close(pridebugfd);
13880 
13881    pridebugfd = myfd;
13882    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13883    ast_mutex_unlock(&pridebugfdlock);
13884    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13885    return CLI_SUCCESS;
13886 }

static char* handle_pri_show_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14166 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, sig_pri_span::dchans, debug, ast_cli_args::fd, sig_pri_span::pri, sig_pri_chan::pri, pris, and ast_cli_entry::usage.

14167 {
14168    int x;
14169    int span;
14170    int count=0;
14171    int debug;
14172 
14173    switch (cmd) {
14174    case CLI_INIT:
14175       e->command = "pri show debug";
14176       e->usage =
14177          "Usage: pri show debug\n"
14178          "  Show the debug state of pri spans\n";
14179       return NULL;
14180    case CLI_GENERATE:
14181       return NULL;
14182    }
14183 
14184    for (span = 0; span < NUM_SPANS; span++) {
14185       if (pris[span].pri.pri) {
14186          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14187             if (pris[span].pri.dchans[x]) {
14188                debug = pri_get_debug(pris[span].pri.dchans[x]);
14189                ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
14190                count++;
14191             }
14192          }
14193       }
14194 
14195    }
14196    ast_mutex_lock(&pridebugfdlock);
14197    if (pridebugfd >= 0)
14198       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14199    ast_mutex_unlock(&pridebugfdlock);
14200 
14201    if (!count)
14202       ast_cli(a->fd, "No PRI running\n");
14203    return CLI_SUCCESS;
14204 }

static char* handle_pri_show_span ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14132 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), dahdi_pri::dchannels, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, dahdi_pri::pri, sig_pri_span::pri, sig_pri_chan::pri, pris, sig_pri_cli_show_span(), ast_cli_entry::usage, and ast_cli_args::word.

14133 {
14134    int span;
14135 
14136    switch (cmd) {
14137    case CLI_INIT:
14138       e->command = "pri show span";
14139       e->usage =
14140          "Usage: pri show span <span>\n"
14141          "       Displays PRI Information on a given PRI span\n";
14142       return NULL;
14143    case CLI_GENERATE:
14144       return complete_span_4(a->line, a->word, a->pos, a->n);
14145    }
14146 
14147    if (a->argc < 4)
14148       return CLI_SHOWUSAGE;
14149    span = atoi(a->argv[3]);
14150    if ((span < 1) || (span > NUM_SPANS)) {
14151       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14152       return CLI_SUCCESS;
14153    }
14154    if (!pris[span-1].pri.pri) {
14155       ast_cli(a->fd, "No PRI running on span %d\n", span);
14156       return CLI_SUCCESS;
14157    }
14158 
14159    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14160 
14161    return CLI_SUCCESS;
14162 }

static char* handle_pri_show_spans ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14104 of file chan_dahdi.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, dahdi_pri::pri, sig_pri_span::pri, sig_pri_chan::pri, pris, sig_pri_cli_show_spans(), and ast_cli_entry::usage.

14105 {
14106    int span;
14107 
14108    switch (cmd) {
14109    case CLI_INIT:
14110       e->command = "pri show spans";
14111       e->usage =
14112          "Usage: pri show spans\n"
14113          "       Displays PRI Information\n";
14114       return NULL;
14115    case CLI_GENERATE:
14116       return NULL;
14117    }
14118 
14119    if (a->argc != 3)
14120       return CLI_SHOWUSAGE;
14121 
14122    for (span = 0; span < NUM_SPANS; span++) {
14123       if (pris[span].pri.pri) {
14124          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14125       }
14126    }
14127    return CLI_SUCCESS;
14128 }

static char* handle_pri_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 14208 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

14209 {
14210    switch (cmd) {
14211    case CLI_INIT:
14212       e->command = "pri show version";
14213       e->usage =
14214          "Usage: pri show version\n"
14215          "Show libpri version information\n";
14216       return NULL;
14217    case CLI_GENERATE:
14218       return NULL;
14219    }
14220 
14221    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14222 
14223    return CLI_SUCCESS;
14224 }

static char* handle_ss7_block_cic ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15796 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, sig_ss7_linkset::ss7, dahdi_ss7::ss7, and ast_cli_entry::usage.

15797 {
15798    int linkset, cic;
15799    int blocked = -1, i;
15800    switch (cmd) {
15801    case CLI_INIT:
15802       e->command = "ss7 block cic";
15803       e->usage =
15804          "Usage: ss7 block cic <linkset> <CIC>\n"
15805          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
15806       return NULL;
15807    case CLI_GENERATE:
15808       return NULL;
15809    }
15810    if (a->argc == 5)
15811       linkset = atoi(a->argv[3]);
15812    else
15813       return CLI_SHOWUSAGE;
15814 
15815    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15816       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15817       return CLI_SUCCESS;
15818    }
15819 
15820    if (!linksets[linkset-1].ss7.ss7) {
15821       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15822       return CLI_SUCCESS;
15823    }
15824 
15825    cic = atoi(a->argv[4]);
15826 
15827    if (cic < 1) {
15828       ast_cli(a->fd, "Invalid CIC specified!\n");
15829       return CLI_SUCCESS;
15830    }
15831 
15832    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15833       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15834          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15835          if (!blocked) {
15836             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15837             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15838             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15839          }
15840       }
15841    }
15842 
15843    if (blocked < 0) {
15844       ast_cli(a->fd, "Invalid CIC specified!\n");
15845       return CLI_SUCCESS;
15846    }
15847 
15848    if (!blocked)
15849       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15850    else
15851       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15852 
15853    /* Break poll on the linkset so it sends our messages */
15854    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15855 
15856    return CLI_SUCCESS;
15857 }

static char* handle_ss7_block_linkset ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15861 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, sig_ss7_linkset::ss7, dahdi_ss7::ss7, and ast_cli_entry::usage.

15862 {
15863    int linkset;
15864    int i;
15865    switch (cmd) {
15866    case CLI_INIT:
15867       e->command = "ss7 block linkset";
15868       e->usage =
15869          "Usage: ss7 block linkset <linkset number>\n"
15870          "       Sends a remote blocking request for all CICs on the given linkset\n";
15871       return NULL;
15872    case CLI_GENERATE:
15873       return NULL;
15874    }
15875    if (a->argc == 4)
15876       linkset = atoi(a->argv[3]);
15877    else
15878       return CLI_SHOWUSAGE;
15879 
15880    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15881       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15882       return CLI_SUCCESS;
15883    }
15884 
15885    if (!linksets[linkset-1].ss7.ss7) {
15886       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15887       return CLI_SUCCESS;
15888    }
15889 
15890    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15891       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15892       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15893       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15894       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15895    }
15896 
15897    /* Break poll on the linkset so it sends our messages */
15898    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15899 
15900    return CLI_SUCCESS;
15901 }

static char* handle_ss7_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15759 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, SIG_SS7_DEBUG, dahdi_ss7::ss7, and ast_cli_entry::usage.

15760 {
15761    int span;
15762    switch (cmd) {
15763    case CLI_INIT:
15764       e->command = "ss7 set debug {on|off} linkset";
15765       e->usage =
15766          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15767          "       Enables debugging on a given SS7 linkset\n";
15768       return NULL;
15769    case CLI_GENERATE:
15770       return NULL;
15771    }
15772    if (a->argc < 6)
15773       return CLI_SHOWUSAGE;
15774    span = atoi(a->argv[5]);
15775    if ((span < 1) || (span > NUM_SPANS)) {
15776       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15777       return CLI_SUCCESS;
15778    }
15779    if (!linksets[span-1].ss7.ss7) {
15780       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15781    } else {
15782       if (!strcasecmp(a->argv[3], "on")) {
15783          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
15784          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15785       } else {
15786          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
15787          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15788       }
15789    }
15790 
15791    return CLI_SUCCESS;
15792 }

static char* handle_ss7_show_linkset ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 16009 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, sig_ss7_linkset::LINKSET_STATE_UP, sig_ss7_linkset::ss7, and ast_cli_entry::usage.

16010 {
16011    int linkset;
16012    struct sig_ss7_linkset *ss7;
16013    switch (cmd) {
16014    case CLI_INIT:
16015       e->command = "ss7 show linkset";
16016       e->usage =
16017          "Usage: ss7 show linkset <span>\n"
16018          "       Shows the status of an SS7 linkset.\n";
16019       return NULL;
16020    case CLI_GENERATE:
16021       return NULL;
16022    }
16023 
16024    if (a->argc < 4)
16025       return CLI_SHOWUSAGE;
16026    linkset = atoi(a->argv[3]);
16027    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16028       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16029       return CLI_SUCCESS;
16030    }
16031    ss7 = &linksets[linkset - 1].ss7;
16032    if (!ss7->ss7) {
16033       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16034       return CLI_SUCCESS;
16035    }
16036 
16037    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16038 
16039    return CLI_SUCCESS;
16040 }

static char* handle_ss7_unblock_cic ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15905 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, sig_ss7_linkset::ss7, dahdi_ss7::ss7, and ast_cli_entry::usage.

15906 {
15907    int linkset, cic;
15908    int i, blocked = -1;
15909    switch (cmd) {
15910    case CLI_INIT:
15911       e->command = "ss7 unblock cic";
15912       e->usage =
15913          "Usage: ss7 unblock cic <linkset> <CIC>\n"
15914          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
15915       return NULL;
15916    case CLI_GENERATE:
15917       return NULL;
15918    }
15919 
15920    if (a->argc == 5)
15921       linkset = atoi(a->argv[3]);
15922    else
15923       return CLI_SHOWUSAGE;
15924 
15925    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15926       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15927       return CLI_SUCCESS;
15928    }
15929 
15930    if (!linksets[linkset-1].ss7.ss7) {
15931       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15932       return CLI_SUCCESS;
15933    }
15934 
15935    cic = atoi(a->argv[4]);
15936 
15937    if (cic < 1) {
15938       ast_cli(a->fd, "Invalid CIC specified!\n");
15939       return CLI_SUCCESS;
15940    }
15941 
15942    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15943       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15944          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15945          if (blocked) {
15946             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15947             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15948             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15949          }
15950       }
15951    }
15952 
15953    if (blocked > 0)
15954       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15955 
15956    /* Break poll on the linkset so it sends our messages */
15957    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15958 
15959    return CLI_SUCCESS;
15960 }

static char* handle_ss7_unblock_linkset ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 15964 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, sig_ss7_linkset::ss7, dahdi_ss7::ss7, and ast_cli_entry::usage.

15965 {
15966    int linkset;
15967    int i;
15968    switch (cmd) {
15969    case CLI_INIT:
15970       e->command = "ss7 unblock linkset";
15971       e->usage =
15972          "Usage: ss7 unblock linkset <linkset number>\n"
15973          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
15974       return NULL;
15975    case CLI_GENERATE:
15976       return NULL;
15977    }
15978 
15979    if (a->argc == 4)
15980       linkset = atoi(a->argv[3]);
15981    else
15982       return CLI_SHOWUSAGE;
15983 
15984    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15985       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15986       return CLI_SUCCESS;
15987    }
15988 
15989    if (!linksets[linkset-1].ss7.ss7) {
15990       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15991       return CLI_SUCCESS;
15992    }
15993 
15994    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15995       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15996       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15997       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15998       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15999    }
16000 
16001    /* Break poll on the linkset so it sends our messages */
16002    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16003 
16004    return CLI_SUCCESS;
16005 }

static char* handle_ss7_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 16044 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

16045 {
16046    switch (cmd) {
16047    case CLI_INIT:
16048       e->command = "ss7 show version";
16049       e->usage =
16050          "Usage: ss7 show version\n"
16051          "  Show the libss7 version\n";
16052       return NULL;
16053    case CLI_GENERATE:
16054       return NULL;
16055    }
16056 
16057    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16058 
16059    return CLI_SUCCESS;
16060 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 5122 of file chan_dahdi.c.

References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), context, dahdi_pvt::mailbox, mailbox, and strsep().

05123 {
05124    int new_msgs;
05125    struct ast_event *event;
05126    char *mailbox, *context;
05127 
05128    mailbox = context = ast_strdupa(p->mailbox);
05129    strsep(&context, "@");
05130    if (ast_strlen_zero(context))
05131       context = "default";
05132 
05133    event = ast_event_get_cached(AST_EVENT_MWI,
05134       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05135       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05136       AST_EVENT_IE_END);
05137 
05138    if (event) {
05139       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05140       ast_event_destroy(event);
05141    } else
05142       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05143 
05144    return new_msgs;
05145 }

static int is_group_or_channel_match ( struct dahdi_pvt p,
int  span,
ast_group_t  groupmatch,
int *  groupmatched,
int  channelmatch,
int *  channelmatched 
) [static]

Definition at line 12796 of file chan_dahdi.c.

References dahdi_pvt::channel, dahdi_pvt::group, dahdi_pvt::pri, and sig_pri_span::span.

Referenced by dahdi_cc_callback(), and dahdi_request().

12797 {
12798 #if defined(HAVE_PRI)
12799    if (0 < span) {
12800       /* The channel must be on the specified PRI span. */
12801       if (!p->pri || p->pri->span != span) {
12802          return 0;
12803       }
12804       if (!groupmatch && channelmatch == -1) {
12805          /* Match any group since it only needs to be on the PRI span. */
12806          *groupmatched = 1;
12807          return 1;
12808       }
12809    }
12810 #endif   /* defined(HAVE_PRI) */
12811    /* check group matching */
12812    if (groupmatch) {
12813       if ((p->group & groupmatch) != groupmatch)
12814          /* Doesn't match the specified group, try the next one */
12815          return 0;
12816       *groupmatched = 1;
12817    }
12818    /* Check to see if we have a channel match */
12819    if (channelmatch != -1) {
12820       if (p->channel != channelmatch)
12821          /* Doesn't match the specified channel, try the next one */
12822          return 0;
12823       *channelmatched = 1;
12824    }
12825 
12826    return 1;
12827 }

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

Definition at line 4604 of file chan_dahdi.c.

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

Referenced by conf_del().

04605 {
04606    /* If they're listening to our channel, they're ours */
04607    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04608       return 1;
04609    /* If they're a talker on our (allocated) conference, they're ours */
04610    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04611       return 1;
04612    return 0;
04613 }

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

Definition at line 4634 of file chan_dahdi.c.

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

Referenced by my_complete_conference_update(), and update_conf().

04635 {
04636    int x;
04637    int useslavenative;
04638    struct dahdi_pvt *slave = NULL;
04639    /* Start out optimistic */
04640    useslavenative = 1;
04641    /* Update conference state in a stateless fashion */
04642    for (x = 0; x < 3; x++) {
04643       /* Any three-way calling makes slave native mode *definitely* out
04644          of the question */
04645       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04646          useslavenative = 0;
04647    }
04648    /* If we don't have any 3-way calls, check to see if we have
04649       precisely one slave */
04650    if (useslavenative) {
04651       for (x = 0; x < MAX_SLAVES; x++) {
04652          if (p->slaves[x]) {
04653             if (slave) {
04654                /* Whoops already have a slave!  No
04655                   slave native and stop right away */
04656                slave = NULL;
04657                useslavenative = 0;
04658                break;
04659             } else {
04660                /* We have one slave so far */
04661                slave = p->slaves[x];
04662             }
04663          }
04664       }
04665    }
04666    /* If no slave, slave native definitely out */
04667    if (!slave)
04668       useslavenative = 0;
04669    else if (slave->law != p->law) {
04670       useslavenative = 0;
04671       slave = NULL;
04672    }
04673    if (out)
04674       *out = slave;
04675    return useslavenative;
04676 }

static int linkset_addsigchan ( int  sigchan  )  [static]

Definition at line 15644 of file chan_dahdi.c.

References ast_log(), cur_adjpointcode, cur_defaultdpc, cur_linkset, cur_networkindicator, cur_pointcode, cur_ss7type, dahdi_close_ss7_fd(), errno, sig_ss7_linkset::fds, sig_ss7_linkset::numsigchans, sig_ss7_add_sigchan(), dahdi_ss7::ss7, and ss7_resolve_linkset().

15645 {
15646    struct dahdi_ss7 *link;
15647    int res;
15648    int curfd;
15649    struct dahdi_params params;
15650    struct dahdi_bufferinfo bi;
15651    struct dahdi_spaninfo si;
15652 
15653    if (sigchan < 0) {
15654       ast_log(LOG_ERROR, "Invalid sigchan!\n");
15655       return -1;
15656    }
15657    if (cur_ss7type < 0) {
15658       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15659       return -1;
15660    }
15661    if (cur_pointcode < 0) {
15662       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15663       return -1;
15664    }
15665    if (cur_adjpointcode < 0) {
15666       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15667       return -1;
15668    }
15669    if (cur_defaultdpc < 0) {
15670       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15671       return -1;
15672    }
15673    if (cur_networkindicator < 0) {
15674       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15675       return -1;
15676    }
15677    link = ss7_resolve_linkset(cur_linkset);
15678    if (!link) {
15679       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15680       return -1;
15681    }
15682    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15683       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15684       return -1;
15685    }
15686 
15687    curfd = link->ss7.numsigchans;
15688 
15689    /* Open signaling channel */
15690    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15691    if (link->ss7.fds[curfd] < 0) {
15692       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15693          strerror(errno));
15694       return -1;
15695    }
15696    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15697       dahdi_close_ss7_fd(link, curfd);
15698       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
15699          strerror(errno));
15700       return -1;
15701    }
15702 
15703    /* Get signaling channel parameters */
15704    memset(&params, 0, sizeof(params));
15705    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
15706    if (res) {
15707       dahdi_close_ss7_fd(link, curfd);
15708       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
15709          strerror(errno));
15710       return -1;
15711    }
15712    if (params.sigtype != DAHDI_SIG_HDLCFCS
15713       && params.sigtype != DAHDI_SIG_HARDHDLC
15714       && params.sigtype != DAHDI_SIG_MTP2) {
15715       dahdi_close_ss7_fd(link, curfd);
15716       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15717       return -1;
15718    }
15719 
15720    /* Set signaling channel buffer policy. */
15721    memset(&bi, 0, sizeof(bi));
15722    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15723    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15724    bi.numbufs = 32;
15725    bi.bufsize = 512;
15726    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15727       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
15728          sigchan, strerror(errno));
15729       dahdi_close_ss7_fd(link, curfd);
15730       return -1;
15731    }
15732 
15733    /* Get current signaling channel alarm status. */
15734    memset(&si, 0, sizeof(si));
15735    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
15736    if (res) {
15737       dahdi_close_ss7_fd(link, curfd);
15738       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
15739          strerror(errno));
15740    }
15741 
15742    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
15743       (params.sigtype == DAHDI_SIG_MTP2)
15744          ? SS7_TRANSPORT_DAHDIMTP2
15745          : SS7_TRANSPORT_DAHDIDCHAN,
15746       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
15747    if (res) {
15748       dahdi_close_ss7_fd(link, curfd);
15749       return -1;
15750    }
15751 
15752    ++link->ss7.numsigchans;
15753 
15754    return 0;
15755 }

static int load_module ( void   )  [static]

Definition at line 17970 of file chan_dahdi.c.

References __unload_module(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_transfer(), action_transferhangup(), ARRAY_LEN, ast_cc_agent_register(), ast_cc_monitor_register(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init, ast_data_register_multiple, ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_register_application_xml, dahdi_accept_r2_call_exec(), dahdi_cli, dahdi_data_providers, dahdi_mfcr2_cli, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_callrerouting_facility_exec(), dahdi_send_keypad_facility_exec(), dahdi_ss7_cli, dahdi_ss7_error(), dahdi_ss7_message(), dahdi_tech, round_robin, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), sig_ss7_init_linkset(), and ss_thread_complete.

17971 {
17972    int res;
17973 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17974    int y;
17975 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17976 
17977 #ifdef HAVE_PRI
17978    memset(pris, 0, sizeof(pris));
17979    for (y = 0; y < NUM_SPANS; y++) {
17980       sig_pri_init_pri(&pris[y].pri);
17981    }
17982    pri_set_error(dahdi_pri_error);
17983    pri_set_message(dahdi_pri_message);
17984    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17985 #ifdef HAVE_PRI_PROG_W_CAUSE
17986    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17987 #endif
17988 #if defined(HAVE_PRI_CCSS)
17989    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
17990       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
17991       __unload_module();
17992       return AST_MODULE_LOAD_FAILURE;
17993    }
17994 #endif   /* defined(HAVE_PRI_CCSS) */
17995    if (sig_pri_load(
17996 #if defined(HAVE_PRI_CCSS)
17997       dahdi_pri_cc_type
17998 #else
17999       NULL
18000 #endif   /* defined(HAVE_PRI_CCSS) */
18001       )) {
18002       __unload_module();
18003       return AST_MODULE_LOAD_FAILURE;
18004    }
18005 #endif
18006 #if defined(HAVE_SS7)
18007    memset(linksets, 0, sizeof(linksets));
18008    for (y = 0; y < NUM_SPANS; y++) {
18009       sig_ss7_init_linkset(&linksets[y].ss7);
18010    }
18011    ss7_set_error(dahdi_ss7_error);
18012    ss7_set_message(dahdi_ss7_message);
18013 #endif   /* defined(HAVE_SS7) */
18014    res = setup_dahdi(0);
18015    /* Make sure we can register our DAHDI channel type */
18016    if (res)
18017       return AST_MODULE_LOAD_DECLINE;
18018    if (ast_channel_register(&dahdi_tech)) {
18019       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18020       __unload_module();
18021       return AST_MODULE_LOAD_FAILURE;
18022    }
18023 #ifdef HAVE_PRI
18024    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18025 #endif
18026 #if defined(HAVE_SS7)
18027    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18028 #endif   /* defined(HAVE_SS7) */
18029 #ifdef HAVE_OPENR2
18030    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18031    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18032 #endif
18033 
18034    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18035    /* register all the data providers */
18036    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18037    memset(round_robin, 0, sizeof(round_robin));
18038    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18039    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18040    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18041    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18042    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18043    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18044    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18045 
18046    ast_cond_init(&ss_thread_complete, NULL);
18047 
18048    return res;
18049 }

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

Definition at line 13600 of file chan_dahdi.c.

References ast_log(), LOG_DEBUG, and SUB_REAL.

13601 {
13602    struct dahdi_mfcr2 *mfcr2 = data;
13603    /* we should be using pthread_key_create
13604       and allocate pollers dynamically.
13605       I think do_monitor() could be leaking, since it
13606       could be cancelled at any time and is not
13607       using thread keys, why?, */
13608    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13609    int res = 0;
13610    int i = 0;
13611    int oldstate = 0;
13612    int quit_loop = 0;
13613    int maxsleep = 20;
13614    int was_idle = 0;
13615    int pollsize = 0;
13616    /* now that we're ready to get calls, unblock our side and
13617       get current line state */
13618    for (i = 0; i < mfcr2->numchans; i++) {
13619       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13620       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13621    }
13622    while (1) {
13623       /* we trust here that the mfcr2 channel list will not ever change once
13624          the module is loaded */
13625       pollsize = 0;
13626       for (i = 0; i < mfcr2->numchans; i++) {
13627          pollers[i].revents = 0;
13628          pollers[i].events = 0;
13629          if (mfcr2->pvts[i]->owner) {
13630             continue;
13631          }
13632          if (!mfcr2->pvts[i]->r2chan) {
13633             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13634             quit_loop = 1;
13635             break;
13636          }
13637          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13638          pollers[i].events = POLLIN | POLLPRI;
13639          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13640          pollsize++;
13641       }
13642       if (quit_loop) {
13643          break;
13644       }
13645       if (pollsize == 0) {
13646          if (!was_idle) {
13647             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13648             was_idle = 1;
13649          }
13650          poll(NULL, 0, maxsleep);
13651          continue;
13652       }
13653       was_idle = 0;
13654       /* probably poll() is a valid cancel point, lets just be on the safe side
13655          by calling pthread_testcancel */
13656       pthread_testcancel();
13657       res = poll(pollers, mfcr2->numchans, maxsleep);
13658       pthread_testcancel();
13659       if ((res < 0) && (errno != EINTR)) {
13660          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13661          break;
13662       }
13663       /* do we want to allow to cancel while processing events? */
13664       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13665       for (i = 0; i < mfcr2->numchans; i++) {
13666          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13667             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13668          }
13669       }
13670       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13671    }
13672    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13673    return 0;
13674 }

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

Definition at line 11917 of file chan_dahdi.c.

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

Referenced by build_channels().

11918 {
11919    /* Make a dahdi_pvt structure for this interface */
11920    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
11921    char fn[80];
11922    struct dahdi_bufferinfo bi;
11923 
11924    int res;
11925    int span = 0;
11926    int here = 0;/*!< TRUE if the channel interface already exists. */
11927    int x;
11928    struct analog_pvt *analog_p = NULL;
11929    struct dahdi_params p;
11930 #if defined(HAVE_PRI)
11931    struct dahdi_spaninfo si;
11932    struct sig_pri_chan *pri_chan = NULL;
11933 #endif   /* defined(HAVE_PRI) */
11934 #if defined(HAVE_SS7)
11935    struct sig_ss7_chan *ss7_chan = NULL;
11936 #endif   /* defined(HAVE_SS7) */
11937 
11938    /* Search channel interface list to see if it already exists. */
11939    for (tmp = iflist; tmp; tmp = tmp->next) {
11940       if (!tmp->destroy) {
11941          if (tmp->channel == channel) {
11942             /* The channel interface already exists. */
11943             here = 1;
11944             break;
11945          }
11946          if (tmp->channel > channel) {
11947             /* No way it can be in the sorted list. */
11948             tmp = NULL;
11949             break;
11950          }
11951       }
11952    }
11953 
11954    if (!here && reloading != 1) {
11955       tmp = ast_calloc(1, sizeof(*tmp));
11956       if (!tmp) {
11957          return NULL;
11958       }
11959       tmp->cc_params = ast_cc_config_params_init();
11960       if (!tmp->cc_params) {
11961          ast_free(tmp);
11962          return NULL;
11963       }
11964       ast_mutex_init(&tmp->lock);
11965       ifcount++;
11966       for (x = 0; x < 3; x++)
11967          tmp->subs[x].dfd = -1;
11968       tmp->channel = channel;
11969       tmp->priindication_oob = conf->chan.priindication_oob;
11970    }
11971 
11972    if (tmp) {
11973       int chan_sig = conf->chan.sig;
11974 
11975       if (!here) {
11976          /* Can only get here if this is a new channel interface being created. */
11977          if ((channel != CHAN_PSEUDO)) {
11978             int count = 0;
11979 
11980             snprintf(fn, sizeof(fn), "%d", channel);
11981             /* Open non-blocking */
11982             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11983             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 */
11984                usleep(1);
11985                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11986                count++;
11987             }
11988             /* Allocate a DAHDI structure */
11989             if (tmp->subs[SUB_REAL].dfd < 0) {
11990                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);
11991                destroy_dahdi_pvt(tmp);
11992                return NULL;
11993             }
11994             memset(&p, 0, sizeof(p));
11995             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
11996             if (res < 0) {
11997                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
11998                destroy_dahdi_pvt(tmp);
11999                return NULL;
12000             }
12001             if (conf->is_sig_auto)
12002                chan_sig = sigtype_to_signalling(p.sigtype);
12003             if (p.sigtype != (chan_sig & 0x3ffff)) {
12004                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
12005                destroy_dahdi_pvt(tmp);
12006                return NULL;
12007             }
12008             tmp->law_default = p.curlaw;
12009             tmp->law = p.curlaw;
12010             tmp->span = p.spanno;
12011             span = p.spanno - 1;
12012          } else {
12013             chan_sig = 0;
12014          }
12015          tmp->sig = chan_sig;
12016          tmp->outsigmod = conf->chan.outsigmod;
12017 
12018          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12019             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12020             if (!analog_p) {
12021                destroy_dahdi_pvt(tmp);
12022                return NULL;
12023             }
12024             tmp->sig_pvt = analog_p;
12025          }
12026 #if defined(HAVE_SS7)
12027          if (chan_sig == SIG_SS7) {
12028             struct dahdi_ss7 *ss7;
12029             int clear = 0;
12030 
12031             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12032                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12033                destroy_dahdi_pvt(tmp);
12034                return NULL;
12035             }
12036 
12037             ss7 = ss7_resolve_linkset(cur_linkset);
12038             if (!ss7) {
12039                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12040                destroy_dahdi_pvt(tmp);
12041                return NULL;
12042             }
12043             ss7->ss7.span = cur_linkset;
12044             if (cur_cicbeginswith < 0) {
12045                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12046                destroy_dahdi_pvt(tmp);
12047                return NULL;
12048             }
12049             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12050             if (!ss7_chan) {
12051                destroy_dahdi_pvt(tmp);
12052                return NULL;
12053             }
12054             tmp->sig_pvt = ss7_chan;
12055             tmp->ss7 = &ss7->ss7;
12056 
12057             ss7_chan->channel = tmp->channel;
12058             ss7_chan->cic = cur_cicbeginswith++;
12059 
12060             /* DB: Add CIC's DPC information */
12061             ss7_chan->dpc = cur_defaultdpc;
12062 
12063             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12064 
12065             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12066             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12067             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12068             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12069 
12070             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12071             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12072          }
12073 #endif   /* defined(HAVE_SS7) */
12074 #ifdef HAVE_OPENR2
12075          if (chan_sig == SIG_MFCR2) {
12076             struct dahdi_mfcr2 *r2_link;
12077             r2_link = dahdi_r2_get_link();
12078             if (!r2_link) {
12079                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12080                destroy_dahdi_pvt(tmp);
12081                return NULL;
12082             }
12083             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12084                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12085                destroy_dahdi_pvt(tmp);
12086                return NULL;
12087             }
12088             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12089                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12090                destroy_dahdi_pvt(tmp);
12091                return NULL;
12092             }
12093             r2_link->pvts[r2_link->numchans++] = tmp;
12094             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12095                                         tmp->subs[SUB_REAL].dfd,
12096                                         NULL, NULL);
12097             if (!tmp->r2chan) {
12098                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12099                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12100                destroy_dahdi_pvt(tmp);
12101                return NULL;
12102             }
12103             tmp->mfcr2 = r2_link;
12104             if (conf->mfcr2.call_files) {
12105                openr2_chan_enable_call_files(tmp->r2chan);
12106             }
12107             openr2_chan_set_client_data(tmp->r2chan, tmp);
12108             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12109             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12110             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12111             tmp->mfcr2_category = conf->mfcr2.category;
12112             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12113             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12114             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12115             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12116             tmp->mfcr2call = 0;
12117             tmp->mfcr2_dnis_index = 0;
12118             tmp->mfcr2_ani_index = 0;
12119             r2_link->monitored_count++;
12120          }
12121 #endif
12122 #ifdef HAVE_PRI
12123          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12124             int offset;
12125             int matchesdchan;
12126             int x,y;
12127             int myswitchtype = 0;
12128 
12129             offset = 0;
12130             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12131                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12132                destroy_dahdi_pvt(tmp);
12133                return NULL;
12134             }
12135             if (span >= NUM_SPANS) {
12136                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12137                destroy_dahdi_pvt(tmp);
12138                return NULL;
12139             } else {
12140                si.spanno = 0;
12141                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12142                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12143                   destroy_dahdi_pvt(tmp);
12144                   return NULL;
12145                }
12146                /* Store the logical span first based upon the real span */
12147                tmp->logicalspan = pris[span].prilogicalspan;
12148                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12149                if (span < 0) {
12150                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12151                   destroy_dahdi_pvt(tmp);
12152                   return NULL;
12153                }
12154                myswitchtype = conf->pri.pri.switchtype;
12155                /* Make sure this isn't a d-channel */
12156                matchesdchan=0;
12157                for (x = 0; x < NUM_SPANS; x++) {
12158                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12159                      if (pris[x].dchannels[y] == tmp->channel) {
12160                         matchesdchan = 1;
12161                         break;
12162                      }
12163                   }
12164                }
12165                if (!matchesdchan) {
12166                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12167                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12168                      destroy_dahdi_pvt(tmp);
12169                      return NULL;
12170                   }
12171                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12172                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12173                      destroy_dahdi_pvt(tmp);
12174                      return NULL;
12175                   }
12176                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12177                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
12178                      destroy_dahdi_pvt(tmp);
12179                      return NULL;
12180                   }
12181                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12182                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12183                      destroy_dahdi_pvt(tmp);
12184                      return NULL;
12185                   }
12186                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12187                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12188                      destroy_dahdi_pvt(tmp);
12189                      return NULL;
12190                   }
12191                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12192                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12193                      destroy_dahdi_pvt(tmp);
12194                      return NULL;
12195                   }
12196                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12197                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12198                      destroy_dahdi_pvt(tmp);
12199                      return NULL;
12200                   }
12201                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12202                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12203                         pris[span].pri.trunkgroup);
12204                      destroy_dahdi_pvt(tmp);
12205                      return NULL;
12206                   }
12207 
12208                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12209                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12210                   if (!pri_chan) {
12211                      destroy_dahdi_pvt(tmp);
12212                      return NULL;
12213                   }
12214                   tmp->sig_pvt = pri_chan;
12215                   tmp->pri = &pris[span].pri;
12216 
12217                   tmp->priexclusive = conf->chan.priexclusive;
12218 
12219                   if (!tmp->pri->cc_params) {
12220                      tmp->pri->cc_params = ast_cc_config_params_init();
12221                      if (!tmp->pri->cc_params) {
12222                         destroy_dahdi_pvt(tmp);
12223                         return NULL;
12224                      }
12225                   }
12226                   ast_cc_copy_config_params(tmp->pri->cc_params,
12227                      conf->chan.cc_params);
12228 
12229                   pris[span].pri.sig = chan_sig;
12230                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12231                   pris[span].pri.switchtype = myswitchtype;
12232                   pris[span].pri.nsf = conf->pri.pri.nsf;
12233                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12234                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12235                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12236                   pris[span].pri.minunused = conf->pri.pri.minunused;
12237                   pris[span].pri.minidle = conf->pri.pri.minidle;
12238                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12239                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12240                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12241 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12242                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12243 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12244 #ifdef HAVE_PRI_INBANDDISCONNECT
12245                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12246 #endif
12247 #if defined(HAVE_PRI_CALL_HOLD)
12248                   pris[span].pri.hold_disconnect_transfer =
12249                      conf->pri.pri.hold_disconnect_transfer;
12250 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12251 #if defined(HAVE_PRI_CCSS)
12252                   pris[span].pri.cc_ptmp_recall_mode =
12253                      conf->pri.pri.cc_ptmp_recall_mode;
12254                   pris[span].pri.cc_qsig_signaling_link_req =
12255                      conf->pri.pri.cc_qsig_signaling_link_req;
12256                   pris[span].pri.cc_qsig_signaling_link_rsp =
12257                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12258 #endif   /* defined(HAVE_PRI_CCSS) */
12259 #if defined(HAVE_PRI_CALL_WAITING)
12260                   pris[span].pri.max_call_waiting_calls =
12261                      conf->pri.pri.max_call_waiting_calls;
12262                   pris[span].pri.allow_call_waiting_calls =
12263                      conf->pri.pri.allow_call_waiting_calls;
12264 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12265                   pris[span].pri.transfer = conf->chan.transfer;
12266                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12267 #if defined(HAVE_PRI_AOC_EVENTS)
12268                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12269                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12270 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12271                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12272                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12273                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12274 #if defined(HAVE_PRI_MWI)
12275                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12276                      conf->pri.pri.mwi_mailboxes,
12277                      sizeof(pris[span].pri.mwi_mailboxes));
12278 #endif   /* defined(HAVE_PRI_MWI) */
12279                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12280                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12281                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12282                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12283                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12284                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12285                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12286                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12287 
12288                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12289                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12290                   }
12291 
12292 #if defined(HAVE_PRI_CALL_WAITING)
12293                   /* Channel initial config parameters. */
12294                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12295                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12296                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12297                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12298                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12299                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12300                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12301                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12302                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12303                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12304 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12305                } else {
12306                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12307                   destroy_dahdi_pvt(tmp);
12308                   return NULL;
12309                }
12310             }
12311          }
12312 #endif
12313       } else {
12314          /* already exists in interface list */
12315          ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig));
12316          chan_sig = tmp->sig;
12317          if (tmp->subs[SUB_REAL].dfd > -1) {
12318             memset(&p, 0, sizeof(p));
12319             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12320          }
12321       }
12322       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12323       switch (chan_sig) {
12324       case SIG_FXSKS:
12325       case SIG_FXSLS:
12326       case SIG_EM:
12327       case SIG_EM_E1:
12328       case SIG_EMWINK:
12329       case SIG_FEATD:
12330       case SIG_FEATDMF:
12331       case SIG_FEATDMF_TA:
12332       case SIG_FEATB:
12333       case SIG_E911:
12334       case SIG_SF:
12335       case SIG_SFWINK:
12336       case SIG_FGC_CAMA:
12337       case SIG_FGC_CAMAMF:
12338       case SIG_SF_FEATD:
12339       case SIG_SF_FEATDMF:
12340       case SIG_SF_FEATB:
12341          p.starttime = 250;
12342          break;
12343       }
12344 
12345       if (tmp->radio) {
12346          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12347          p.channo = channel;
12348          p.rxwinktime = 1;
12349          p.rxflashtime = 1;
12350          p.starttime = 1;
12351          p.debouncetime = 5;
12352       } else {
12353          p.channo = channel;
12354          /* Override timing settings based on config file */
12355          if (conf->timing.prewinktime >= 0)
12356             p.prewinktime = conf->timing.prewinktime;
12357          if (conf->timing.preflashtime >= 0)
12358             p.preflashtime = conf->timing.preflashtime;
12359          if (conf->timing.winktime >= 0)
12360             p.winktime = conf->timing.winktime;
12361          if (conf->timing.flashtime >= 0)
12362             p.flashtime = conf->timing.flashtime;
12363          if (conf->timing.starttime >= 0)
12364             p.starttime = conf->timing.starttime;
12365          if (conf->timing.rxwinktime >= 0)
12366             p.rxwinktime = conf->timing.rxwinktime;
12367          if (conf->timing.rxflashtime >= 0)
12368             p.rxflashtime = conf->timing.rxflashtime;
12369          if (conf->timing.debouncetime >= 0)
12370             p.debouncetime = conf->timing.debouncetime;
12371       }
12372 
12373       /* don't set parms on a pseudo-channel */
12374       if (tmp->subs[SUB_REAL].dfd >= 0)
12375       {
12376          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12377          if (res < 0) {
12378             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12379             destroy_dahdi_pvt(tmp);
12380             return NULL;
12381          }
12382       }
12383 #if 1
12384       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12385          memset(&bi, 0, sizeof(bi));
12386          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12387          if (!res) {
12388             bi.txbufpolicy = conf->chan.buf_policy;
12389             bi.rxbufpolicy = conf->chan.buf_policy;
12390             bi.numbufs = conf->chan.buf_no;
12391             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12392             if (res < 0) {
12393                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12394             }
12395          } else {
12396             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12397          }
12398          tmp->buf_policy = conf->chan.buf_policy;
12399          tmp->buf_no = conf->chan.buf_no;
12400          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12401          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12402          tmp->faxbuf_no = conf->chan.faxbuf_no;
12403          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12404           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12405           * The reason the ioctl call above failed should to be determined before worrying about the
12406           * faxbuffer-related ioctl calls */
12407          tmp->bufsize = bi.bufsize;
12408       }
12409 #endif
12410       tmp->immediate = conf->chan.immediate;
12411       tmp->transfertobusy = conf->chan.transfertobusy;
12412       if (chan_sig & __DAHDI_SIG_FXS) {
12413          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12414          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12415          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12416       }
12417       tmp->ringt_base = ringt_base;
12418       tmp->firstradio = 0;
12419       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12420          tmp->permcallwaiting = conf->chan.callwaiting;
12421       else
12422          tmp->permcallwaiting = 0;
12423       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12424       tmp->destroy = 0;
12425       tmp->drings = conf->chan.drings;
12426 
12427       /* 10 is a nice default. */
12428       if (tmp->drings.ringnum[0].range == 0)
12429          tmp->drings.ringnum[0].range = 10;
12430       if (tmp->drings.ringnum[1].range == 0)
12431          tmp->drings.ringnum[1].range = 10;
12432       if (tmp->drings.ringnum[2].range == 0)
12433          tmp->drings.ringnum[2].range = 10;
12434 
12435       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12436       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12437       tmp->threewaycalling = conf->chan.threewaycalling;
12438       tmp->adsi = conf->chan.adsi;
12439       tmp->use_smdi = conf->chan.use_smdi;
12440       tmp->permhidecallerid = conf->chan.hidecallerid;
12441       tmp->hidecalleridname = conf->chan.hidecalleridname;
12442       tmp->callreturn = conf->chan.callreturn;
12443       tmp->echocancel = conf->chan.echocancel;
12444       tmp->echotraining = conf->chan.echotraining;
12445       tmp->pulse = conf->chan.pulse;
12446       if (tmp->echocancel.head.tap_length) {
12447          tmp->echocanbridged = conf->chan.echocanbridged;
12448       } else {
12449          if (conf->chan.echocanbridged)
12450             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12451          tmp->echocanbridged = 0;
12452       }
12453       tmp->busydetect = conf->chan.busydetect;
12454       tmp->busycount = conf->chan.busycount;
12455       tmp->busycompare = conf->chan.busycompare;
12456       tmp->busytonelength = conf->chan.busytonelength;
12457       tmp->busyquietlength = conf->chan.busyquietlength;
12458       tmp->busyfuzziness = conf->chan.busyfuzziness;
12459       tmp->silencethreshold = conf->chan.silencethreshold;
12460       tmp->callprogress = conf->chan.callprogress;
12461       tmp->waitfordialtone = conf->chan.waitfordialtone;
12462       tmp->cancallforward = conf->chan.cancallforward;
12463       tmp->dtmfrelax = conf->chan.dtmfrelax;
12464       tmp->callwaiting = tmp->permcallwaiting;
12465       tmp->hidecallerid = tmp->permhidecallerid;
12466       tmp->channel = channel;
12467       tmp->stripmsd = conf->chan.stripmsd;
12468       tmp->use_callerid = conf->chan.use_callerid;
12469       tmp->cid_signalling = conf->chan.cid_signalling;
12470       tmp->cid_start = conf->chan.cid_start;
12471       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12472       tmp->restrictcid = conf->chan.restrictcid;
12473       tmp->use_callingpres = conf->chan.use_callingpres;
12474       if (tmp->usedistinctiveringdetection) {
12475          if (!tmp->use_callerid) {
12476             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12477             tmp->use_callerid = 1;
12478          }
12479       }
12480 
12481       if (tmp->cid_signalling == CID_SIG_SMDI) {
12482          if (!tmp->use_smdi) {
12483             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12484             tmp->use_smdi = 1;
12485          }
12486       }
12487       if (tmp->use_smdi) {
12488          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12489          if (!(tmp->smdi_iface)) {
12490             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12491             tmp->use_smdi = 0;
12492          }
12493       }
12494 
12495       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12496       tmp->amaflags = conf->chan.amaflags;
12497       if (!here) {
12498          tmp->confno = -1;
12499          tmp->propconfno = -1;
12500       }
12501       tmp->canpark = conf->chan.canpark;
12502       tmp->transfer = conf->chan.transfer;
12503       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12504       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12505       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12506       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12507       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12508       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12509       tmp->cid_ton = 0;
12510       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12511          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12512          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12513       } else {
12514          tmp->cid_num[0] = '\0';
12515          tmp->cid_name[0] = '\0';
12516       }
12517 #if defined(HAVE_PRI)
12518       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12519          tmp->cid_tag[0] = '\0';
12520       } else
12521 #endif   /* defined(HAVE_PRI) */
12522       {
12523          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12524       }
12525       tmp->cid_subaddr[0] = '\0';
12526       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12527       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12528          char *mailbox, *context;
12529          mailbox = context = ast_strdupa(tmp->mailbox);
12530          strsep(&context, "@");
12531          if (ast_strlen_zero(context))
12532             context = "default";
12533          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12534             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12535             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12536             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12537             AST_EVENT_IE_END);
12538       }
12539 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12540       tmp->mwisend_setting = conf->chan.mwisend_setting;
12541       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12542       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12543 #endif
12544 
12545       tmp->group = conf->chan.group;
12546       tmp->callgroup = conf->chan.callgroup;
12547       tmp->pickupgroup= conf->chan.pickupgroup;
12548       if (conf->chan.vars) {
12549          struct ast_variable *v, *tmpvar;
12550                    for (v = conf->chan.vars ; v ; v = v->next) {
12551                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12552                                   tmpvar->next = tmp->vars;
12553                                    tmp->vars = tmpvar;
12554                            }
12555                   }
12556       }
12557       tmp->cid_rxgain = conf->chan.cid_rxgain;
12558       tmp->rxgain = conf->chan.rxgain;
12559       tmp->txgain = conf->chan.txgain;
12560       tmp->txdrc = conf->chan.txdrc;
12561       tmp->rxdrc = conf->chan.rxdrc;
12562       tmp->tonezone = conf->chan.tonezone;
12563       if (tmp->subs[SUB_REAL].dfd > -1) {
12564          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12565          if (tmp->dsp)
12566             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12567          update_conf(tmp);
12568          if (!here) {
12569             switch (chan_sig) {
12570             case SIG_PRI_LIB_HANDLE_CASES:
12571             case SIG_SS7:
12572             case SIG_MFCR2:
12573                break;
12574             default:
12575                /* Hang it up to be sure it's good */
12576                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12577                break;
12578             }
12579          }
12580          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12581 #ifdef HAVE_PRI
12582          memset(&si, 0, sizeof(si));
12583          if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12584             ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12585             destroy_dahdi_pvt(tmp);
12586             return NULL;
12587          }
12588 #endif
12589          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12590             /* the dchannel is down so put the channel in alarm */
12591             switch (tmp->sig) {
12592 #ifdef HAVE_PRI
12593             case SIG_PRI_LIB_HANDLE_CASES:
12594                sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms);
12595                break;
12596 #endif
12597 #if defined(HAVE_SS7)
12598             case SIG_SS7:
12599                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12600                break;
12601 #endif   /* defined(HAVE_SS7) */
12602             default:
12603                /* The only sig submodule left should be sig_analog. */
12604                analog_p = tmp->sig_pvt;
12605                if (analog_p) {
12606                   analog_p->inalarm = 1;
12607                }
12608                tmp->inalarm = 1;
12609                break;
12610             }
12611             handle_alarms(tmp, res);
12612          }
12613       }
12614 
12615       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12616       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12617       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12618       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12619       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12620 
12621       if (!here) {
12622          tmp->locallyblocked = 0;
12623          tmp->remotelyblocked = 0;
12624          switch (tmp->sig) {
12625 #if defined(HAVE_PRI)
12626          case SIG_PRI_LIB_HANDLE_CASES:
12627             tmp->inservice = 1;/* Inservice until actually implemented. */
12628 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12629             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12630             if (chan_sig == SIG_PRI) {
12631                char db_chan_name[20];
12632                char db_answer[5];
12633 
12634                /*
12635                 * Initialize the active out-of-service status
12636                 * and delete any record if the feature is not enabled.
12637                 */
12638                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12639                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12640                   unsigned *why;
12641 
12642                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12643                   if (tmp->pri->enable_service_message_support) {
12644                      char state;
12645 
12646                      sscanf(db_answer, "%1c:%30u", &state, why);
12647 
12648                      /* Ensure that only the implemented bits could be set.*/
12649                      *why &= (SRVST_NEAREND | SRVST_FAREND);
12650                   }
12651                   if (!*why) {
12652                      ast_db_del(db_chan_name, SRVST_DBKEY);
12653                   }
12654                }
12655             }
12656 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12657             break;
12658 #endif   /* defined(HAVE_PRI) */
12659 #if defined(HAVE_SS7)
12660          case SIG_SS7:
12661             tmp->inservice = 0;
12662             break;
12663 #endif   /* defined(HAVE_SS7) */
12664          default:
12665              /* We default to in service on protocols that don't have a reset */
12666             tmp->inservice = 1;
12667             break;
12668          }
12669       }
12670 
12671       switch (tmp->sig) {
12672 #if defined(HAVE_PRI)
12673       case SIG_PRI_LIB_HANDLE_CASES:
12674          if (pri_chan) {
12675             pri_chan->channel = tmp->channel;
12676             pri_chan->hidecallerid = tmp->hidecallerid;
12677             pri_chan->hidecalleridname = tmp->hidecalleridname;
12678             pri_chan->immediate = tmp->immediate;
12679             pri_chan->inalarm = tmp->inalarm;
12680             pri_chan->priexclusive = tmp->priexclusive;
12681             pri_chan->priindication_oob = tmp->priindication_oob;
12682             pri_chan->use_callerid = tmp->use_callerid;
12683             pri_chan->use_callingpres = tmp->use_callingpres;
12684             ast_copy_string(pri_chan->context, tmp->context,
12685                sizeof(pri_chan->context));
12686             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12687                sizeof(pri_chan->mohinterpret));
12688             pri_chan->stripmsd = tmp->stripmsd;
12689          }
12690          break;
12691 #endif   /* defined(HAVE_PRI) */
12692 #if defined(HAVE_SS7)
12693       case SIG_SS7:
12694          if (ss7_chan) {
12695             ss7_chan->inalarm = tmp->inalarm;
12696 
12697             ss7_chan->stripmsd = tmp->stripmsd;
12698             ss7_chan->hidecallerid = tmp->hidecallerid;
12699             ss7_chan->use_callerid = tmp->use_callerid;
12700             ss7_chan->use_callingpres = tmp->use_callingpres;
12701             ss7_chan->immediate = tmp->immediate;
12702             ss7_chan->locallyblocked = tmp->locallyblocked;
12703             ss7_chan->remotelyblocked = tmp->remotelyblocked;
12704             ast_copy_string(ss7_chan->context, tmp->context,
12705                sizeof(ss7_chan->context));
12706             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12707                sizeof(ss7_chan->mohinterpret));
12708          }
12709          break;
12710 #endif   /* defined(HAVE_SS7) */
12711       default:
12712          /* The only sig submodule left should be sig_analog. */
12713          analog_p = tmp->sig_pvt;
12714          if (analog_p) {
12715             analog_p->channel = tmp->channel;
12716             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12717             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12718             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12719             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
12720             analog_p->callreturn = conf->chan.callreturn;
12721             analog_p->cancallforward = conf->chan.cancallforward;
12722             analog_p->canpark = conf->chan.canpark;
12723             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12724             analog_p->immediate = conf->chan.immediate;
12725             analog_p->permhidecallerid = conf->chan.permhidecallerid;
12726             analog_p->pulse = conf->chan.pulse;
12727             analog_p->threewaycalling = conf->chan.threewaycalling;
12728             analog_p->transfer = conf->chan.transfer;
12729             analog_p->transfertobusy = conf->chan.transfertobusy;
12730             analog_p->use_callerid = tmp->use_callerid;
12731             analog_p->use_smdi = tmp->use_smdi;
12732             analog_p->smdi_iface = tmp->smdi_iface;
12733             analog_p->outsigmod = ANALOG_SIG_NONE;
12734             analog_p->echotraining = conf->chan.echotraining;
12735             analog_p->cid_signalling = conf->chan.cid_signalling;
12736             analog_p->stripmsd = conf->chan.stripmsd;
12737             switch (conf->chan.cid_start) {
12738             case CID_START_POLARITY:
12739                analog_p->cid_start = ANALOG_CID_START_POLARITY;
12740                break;
12741             case CID_START_POLARITY_IN:
12742                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12743                break;
12744             case CID_START_DTMF_NOALERT:
12745                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12746                break;
12747             default:
12748                analog_p->cid_start = ANALOG_CID_START_RING;
12749                break;
12750             }
12751             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12752             analog_p->ringt = conf->chan.ringt;
12753             analog_p->ringt_base = ringt_base;
12754             analog_p->chan_tech = &dahdi_tech;
12755             analog_p->onhooktime = time(NULL);
12756             if (chan_sig & __DAHDI_SIG_FXO) {
12757                memset(&p, 0, sizeof(p));
12758                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12759                if (!res) {
12760                   analog_p->fxsoffhookstate = p.rxisoffhook;
12761                }
12762 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12763                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12764 #endif
12765             }
12766             analog_p->msgstate = -1;
12767 
12768             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12769             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12770             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12771 
12772             analog_config_complete(analog_p);
12773          }
12774          break;
12775       }
12776 #if defined(HAVE_PRI)
12777       if (tmp->channel == CHAN_PSEUDO) {
12778          /*
12779           * Save off pseudo channel buffer policy values for dynamic creation of
12780           * no B channel interfaces.
12781           */
12782          dahdi_pseudo_parms.buf_no = tmp->buf_no;
12783          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
12784          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
12785          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
12786       }
12787 #endif   /* defined(HAVE_PRI) */
12788    }
12789    if (tmp && !here) {
12790       /* Add the new channel interface to the sorted channel interface list. */
12791       dahdi_iflist_insert(tmp);
12792    }
12793    return tmp;
12794 }

static void mwi_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 460 of file chan_dahdi.c.

Referenced by add_peer_mwi_subs(), build_peer(), config_line(), and skinny_register().

00461 {
00462    /* This module does not handle MWI in an event-based manner.  However, it
00463     * subscribes to MWI for each mailbox that is configured so that the core
00464     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00465     * event cache instead of checking the mailbox directly. */
00466 }

static int mwi_send_init ( struct dahdi_pvt pvt  )  [static]

Definition at line 10860 of file chan_dahdi.c.

References ast_callerid_vmwi_generate(), ast_calloc, ast_free, AST_LAW, ast_log(), CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, has_voicemail(), MAX_CALLERID_SIZE, MWI_SEND_SA, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisend_fsk, dahdi_pvt::mwisend_rpas, dahdi_pvt::mwisendactive, SUB_REAL, and dahdi_pvt::subs.

10861 {
10862    int x, res;
10863 
10864 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10865    /* Determine how this spill is to be sent */
10866    if (pvt->mwisend_rpas) {
10867       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10868       pvt->mwisendactive = 1;
10869    } else if (pvt->mwisend_fsk) {
10870       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10871       pvt->mwisendactive = 1;
10872    } else {
10873       pvt->mwisendactive = 0;
10874       return 0;
10875    }
10876 #else
10877    if (mwisend_rpas) {
10878       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10879    } else {
10880       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10881    }
10882    pvt->mwisendactive = 1;
10883 #endif
10884 
10885    if (pvt->cidspill) {
10886       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
10887       ast_free(pvt->cidspill);
10888       pvt->cidspill = NULL;
10889       pvt->cidpos = 0;
10890       pvt->cidlen = 0;
10891    }
10892    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
10893    if (!pvt->cidspill) {
10894       pvt->mwisendactive = 0;
10895       return -1;
10896    }
10897    x = DAHDI_FLUSH_BOTH;
10898    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
10899    x = 3000;
10900    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
10901 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10902    if (pvt->mwisend_fsk) {
10903 #endif
10904       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
10905                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
10906       pvt->cidpos = 0;
10907 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10908    }
10909 #endif
10910    return 0;
10911 }

static int mwi_send_process_buffer ( struct dahdi_pvt pvt,
int  num_read 
) [static]

Definition at line 10913 of file chan_dahdi.c.

References AS_RP_cadence, ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), errno, MWI_SEND_CLEANUP, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisend_fsk, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.

10914 {
10915    struct timeval    now;
10916    int         res;
10917 
10918    /* sanity check to catch if this had been interrupted previously
10919    *  i.e. state says there is more to do but there is no spill allocated
10920    */
10921    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
10922       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10923    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
10924       /* Normal processing -- Perform mwi send action */
10925       switch ( pvt->mwisend_data.mwisend_current) {
10926       case MWI_SEND_SA:
10927          /* Send the Ring Pulse Signal Alert */
10928          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
10929          if (res) {
10930             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
10931             goto quit;
10932          }
10933          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
10934          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
10935          break;
10936       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
10937          break;
10938       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
10939 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10940          if (pvt->mwisend_fsk) {
10941 #endif
10942             gettimeofday(&now, NULL);
10943             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
10944                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10945             }
10946 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10947          } else { /* support for mwisendtype=nofsk */
10948             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10949          }
10950 #endif
10951          break;
10952       case MWI_SEND_SPILL:
10953          /* We read some number of bytes.  Write an equal amount of data */
10954          if(0 < num_read) {
10955             if (num_read > pvt->cidlen - pvt->cidpos)
10956                num_read = pvt->cidlen - pvt->cidpos;
10957             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
10958             if (res > 0) {
10959                pvt->cidpos += res;
10960                if (pvt->cidpos >= pvt->cidlen) {
10961                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10962                }
10963             } else {
10964                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
10965                goto quit;
10966             }
10967          }
10968          break;
10969       case MWI_SEND_CLEANUP:
10970          /* For now, do nothing */
10971          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10972          break;
10973       default:
10974          /* Should not get here, punt*/
10975          goto quit;
10976       }
10977    }
10978 
10979    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
10980       if (pvt->cidspill) {
10981          ast_free(pvt->cidspill);
10982          pvt->cidspill = NULL;
10983          pvt->cidpos = 0;
10984          pvt->cidlen = 0;
10985       }
10986       pvt->mwisendactive = 0;
10987    }
10988    return 0;
10989 quit:
10990    if (pvt->cidspill) {
10991       ast_free(pvt->cidspill);
10992       pvt->cidspill = NULL;
10993       pvt->cidpos = 0;
10994       pvt->cidlen = 0;
10995    }
10996    pvt->mwisendactive = 0;
10997    return -1;
10998 }

static int mwi_send_process_event ( struct dahdi_pvt pvt,
int  event 
) [static]

Definition at line 11000 of file chan_dahdi.c.

References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), errno, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA_WAIT, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.

11001 {
11002    int handled = 0;
11003 
11004    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11005       switch (event) {
11006       case DAHDI_EVENT_RINGEROFF:
11007          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11008             handled = 1;
11009 
11010             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11011                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11012                ast_free(pvt->cidspill);
11013                pvt->cidspill = NULL;
11014                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11015                pvt->mwisendactive = 0;
11016             } else {
11017                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11018                gettimeofday(&pvt->mwisend_data.pause, NULL);
11019             }
11020          }
11021          break;
11022       /* Going off hook, I need to punt this spill */
11023       case DAHDI_EVENT_RINGOFFHOOK:
11024          if (pvt->cidspill) {
11025             ast_free(pvt->cidspill);
11026             pvt->cidspill = NULL;
11027             pvt->cidpos = 0;
11028             pvt->cidlen = 0;
11029          }
11030          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11031          pvt->mwisendactive = 0;
11032          break;
11033       case DAHDI_EVENT_RINGERON:
11034       case DAHDI_EVENT_HOOKCOMPLETE:
11035          break;
11036       default:
11037          break;
11038       }
11039    }
11040    return handled;
11041 }

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

Definition at line 10704 of file chan_dahdi.c.

References analog_lib_handles(), analog_ss_thread(), analog_ss_thread_start(), ast_hangup(), AST_LAW, ast_log(), ast_pthread_create_detached, AST_STATE_RING, mwi_thread_data::buf, bump_gains(), calc_energy(), callerid_feed(), callerid_free(), callerid_new(), dahdi_pvt::channel, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), errno, event2str(), get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, analog_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, mwilevel, dahdi_pvt::mwimonitoractive, name, dahdi_pvt::oprmode, mwi_thread_data::pvt, dahdi_pvt::radio, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

10705 {
10706    struct mwi_thread_data *mtd = data;
10707    struct callerid_state *cs;
10708    pthread_t threadid;
10709    int samples = 0;
10710    char *name, *number;
10711    int flags;
10712    int i, res;
10713    unsigned int spill_done = 0;
10714    int spill_result = -1;
10715 
10716    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10717       mtd->pvt->mwimonitoractive = 0;
10718 
10719       return NULL;
10720    }
10721 
10722    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10723 
10724    bump_gains(mtd->pvt);
10725 
10726    for (;;) {
10727       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10728       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10729          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10730          goto quit;
10731       }
10732 
10733       if (i & DAHDI_IOMUX_SIGEVENT) {
10734          struct ast_channel *chan;
10735 
10736          /* If we get an event, screen out events that we do not act on.
10737           * Otherwise, cancel and go to the simple switch to let it deal with it.
10738           */
10739          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10740 
10741          switch (res) {
10742          case DAHDI_EVENT_NEONMWI_ACTIVE:
10743          case DAHDI_EVENT_NEONMWI_INACTIVE:
10744          case DAHDI_EVENT_NONE:
10745          case DAHDI_EVENT_BITSCHANGED:
10746             break;
10747          case DAHDI_EVENT_NOALARM:
10748             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10749                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10750 
10751                analog_p->inalarm = 0;
10752             }
10753             mtd->pvt->inalarm = 0;
10754             handle_clear_alarms(mtd->pvt);
10755             break;
10756          case DAHDI_EVENT_ALARM:
10757             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10758                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10759 
10760                analog_p->inalarm = 1;
10761             }
10762             mtd->pvt->inalarm = 1;
10763             res = get_alarms(mtd->pvt);
10764             handle_alarms(mtd->pvt, res);
10765             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
10766          default:
10767             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
10768             callerid_free(cs);
10769 
10770             restore_gains(mtd->pvt);
10771             mtd->pvt->ringt = mtd->pvt->ringt_base;
10772 
10773             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10774                int result;
10775                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10776                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10777                } else {
10778                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10779                }
10780                if (result) {
10781                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10782                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10783                   if (res < 0)
10784                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10785                   ast_hangup(chan);
10786                   goto quit;
10787                }
10788                goto quit_no_clean;
10789 
10790             } else {
10791                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
10792             }
10793          }
10794       } else if (i & DAHDI_IOMUX_READ) {
10795          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
10796             if (errno != ELAST) {
10797                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10798                goto quit;
10799             }
10800             break;
10801          }
10802          samples += res;
10803          if (!spill_done) {
10804             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
10805                /*
10806                 * The previous diagnostic message output likely
10807                 * explains why it failed.
10808                 */
10809                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
10810                break;
10811             } else if (spill_result) {
10812                spill_done = 1;
10813             }
10814          } else {
10815             /* keep reading data until the energy level drops below the threshold
10816                so we don't get another 'trigger' on the remaining carrier signal
10817             */
10818             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
10819                break;
10820          }
10821          if (samples > (8000 * 4)) /*Termination case - time to give up*/
10822             break;
10823       }
10824    }
10825 
10826    if (spill_result == 1) {
10827       callerid_get(cs, &name, &number, &flags);
10828       if (flags & CID_MSGWAITING) {
10829          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
10830          notify_message(mtd->pvt->mailbox, 1);
10831       } else if (flags & CID_NOMSGWAITING) {
10832          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
10833          notify_message(mtd->pvt->mailbox, 0);
10834       } else {
10835          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
10836       }
10837    }
10838 
10839 
10840 quit:
10841    callerid_free(cs);
10842 
10843    restore_gains(mtd->pvt);
10844 
10845 quit_no_clean:
10846    mtd->pvt->mwimonitoractive = 0;
10847 
10848    ast_free(mtd);
10849 
10850    return NULL;
10851 }

static void my_all_subchannels_hungup ( void *  pvt  )  [static]

Definition at line 2326 of file chan_dahdi.c.

References ast_dsp_free(), ast_log(), dahdi_pvt::channel, dahdi_setlinear(), dahdi_pvt::didtdd, dahdi_pvt::dsp, errno, dahdi_pvt::faxhandled, dahdi_pvt::law, dahdi_pvt::law_default, LOG_WARNING, num_restart_pending, dahdi_subchannel::owner, dahdi_pvt::owner, reset_conf(), restart_monitor(), SUB_REAL, and dahdi_pvt::subs.

02327 {
02328    struct dahdi_pvt *p = pvt;
02329    int res, law;
02330 
02331    p->faxhandled = 0;
02332    p->didtdd = 0;
02333 
02334    if (p->dsp) {
02335       ast_dsp_free(p->dsp);
02336       p->dsp = NULL;
02337    }
02338 
02339    p->law = p->law_default;
02340    law = p->law_default;
02341    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02342    if (res < 0)
02343       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02344 
02345    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02346 
02347 #if 1
02348    {
02349    int i;
02350    p->owner = NULL;
02351    /* Cleanup owners here */
02352    for (i = 0; i < 3; i++) {
02353       p->subs[i].owner = NULL;
02354    }
02355    }
02356 #endif
02357 
02358    reset_conf(p);
02359    if (num_restart_pending == 0) {
02360       restart_monitor();
02361    }
02362 }

static int my_allocate_sub ( void *  pvt,
enum analog_sub  analogsub 
) [static]

Definition at line 2604 of file chan_dahdi.c.

References alloc_sub(), and analogsub_to_dahdisub().

02605 {
02606    struct dahdi_pvt *p = pvt;
02607 
02608    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02609 }

static void my_answer_polarityswitch ( void *  pvt  )  [static]

Definition at line 2842 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

02843 {
02844    struct dahdi_pvt *p = pvt;
02845 
02846    if (!p->answeronpolarityswitch) {
02847       return;
02848    }
02849 
02850    my_set_polarity(pvt, 1);
02851 }

static int my_callwait ( void *  pvt  )  [static]

Definition at line 1884 of file chan_dahdi.c.

References ast_free, 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, LOG_WARNING, READ_SIZE, save_conference(), and send_callerid().

01885 {
01886    struct dahdi_pvt *p = pvt;
01887    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01888    if (p->cidspill) {
01889       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01890       ast_free(p->cidspill);
01891    }
01892 
01893    /*
01894     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01895     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01896     */
01897    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01898       return -1;
01899    save_conference(p);
01900    /* Silence */
01901    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01902    if (!p->callwaitrings && p->callwaitingcallerid) {
01903       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01904       p->callwaitcas = 1;
01905       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01906    } else {
01907       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01908       p->callwaitcas = 0;
01909       p->cidlen = 2400 + READ_SIZE * 4;
01910    }
01911    p->cidpos = 0;
01912    send_callerid(p);
01913 
01914    return 0;
01915 }

static void my_cancel_cidspill ( void *  pvt  )  [static]

Definition at line 2276 of file chan_dahdi.c.

References ast_free, dahdi_pvt::cidspill, and restore_conference().

02277 {
02278    struct dahdi_pvt *p = pvt;
02279 
02280    ast_free(p->cidspill);
02281    p->cidspill = NULL;
02282    restore_conference(p);
02283 }

static int my_check_confirmanswer ( void *  pvt  )  [static]

Definition at line 2259 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02260 {
02261    struct dahdi_pvt *p = pvt;
02262    if (p->confirmanswer) {
02263       return 1;
02264    }
02265 
02266    return 0;
02267 }

static int my_check_for_conference ( void *  pvt  )  [static]

Definition at line 2436 of file chan_dahdi.c.

References check_for_conference().

02437 {
02438    struct dahdi_pvt *p = pvt;
02439    return check_for_conference(p);
02440 }

static int my_check_waitingfordt ( void *  pvt  )  [static]

Definition at line 2242 of file chan_dahdi.c.

References dahdi_pvt::waitingfordt.

02243 {
02244    struct dahdi_pvt *p = pvt;
02245 
02246    if (p->waitingfordt.tv_usec) {
02247       return 1;
02248    }
02249 
02250    return 0;
02251 }

static int my_complete_conference_update ( void *  pvt,
int  needconference 
) [static]

Definition at line 2386 of file chan_dahdi.c.

References conf_add(), GET_CHANNEL, isslavenative(), MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.

02387 {
02388    struct dahdi_pvt *p = pvt;
02389    int needconf = needconference;
02390    int x;
02391    int useslavenative;
02392    struct dahdi_pvt *slave = NULL;
02393 
02394    useslavenative = isslavenative(p, &slave);
02395 
02396    /* If we have a slave, add him to our conference now. or DAX
02397       if this is slave native */
02398    for (x = 0; x < MAX_SLAVES; x++) {
02399       if (p->slaves[x]) {
02400          if (useslavenative)
02401             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02402          else {
02403             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02404             needconf++;
02405          }
02406       }
02407    }
02408    /* If we're supposed to be in there, do so now */
02409    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02410       if (useslavenative)
02411          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02412       else {
02413          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02414          needconf++;
02415       }
02416    }
02417    /* If we have a master, add ourselves to his conference */
02418    if (p->master) {
02419       if (isslavenative(p->master, NULL)) {
02420          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02421       } else {
02422          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02423       }
02424    }
02425    if (!needconf) {
02426       /* Nobody is left (or should be left) in our conference.
02427          Kill it. */
02428       p->confno = -1;
02429    }
02430 
02431    return 0;
02432 }

static int my_conf_add ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2376 of file chan_dahdi.c.

References analogsub_to_dahdisub(), conf_add(), and dahdi_pvt::subs.

02377 {
02378    struct dahdi_pvt *p = pvt;
02379    int x = analogsub_to_dahdisub(sub);
02380 
02381    return conf_add(p, &p->subs[x], x, 0);
02382 }

static int my_conf_del ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2366 of file chan_dahdi.c.

References analogsub_to_dahdisub(), conf_del(), and dahdi_pvt::subs.

02367 {
02368    struct dahdi_pvt *p = pvt;
02369    int x = analogsub_to_dahdisub(sub);
02370 
02371    return conf_del(p, &p->subs[x], x);
02372 }

static int my_confmute ( void *  pvt,
int  mute 
) [static]

Definition at line 2285 of file chan_dahdi.c.

References dahdi_confmute().

02286 {
02287    struct dahdi_pvt *p = pvt;
02288    return dahdi_confmute(p, mute);
02289 }

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

Definition at line 9039 of file chan_dahdi.c.

References ast_debug, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, READ_SIZE, and dahdi_pvt::subs.

Referenced by dahdi_write().

09040 {
09041    int sent=0;
09042    int size;
09043    int res;
09044    int fd;
09045    fd = p->subs[idx].dfd;
09046    while (len) {
09047       size = len;
09048       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09049          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09050       res = write(fd, buf, size);
09051       if (res != size) {
09052          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09053          return sent;
09054       }
09055       len -= size;
09056       buf += size;
09057    }
09058    return sent;
09059 }

static void my_deadlock_avoidance_private ( void *  pvt  )  [static]

Definition at line 2102 of file chan_dahdi.c.

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

02103 {
02104    struct dahdi_pvt *p = pvt;
02105 
02106    DEADLOCK_AVOIDANCE(&p->lock);
02107 }

static void my_decrease_ss_count ( void   )  [static]

Definition at line 2318 of file chan_dahdi.c.

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ss_thread_complete, ss_thread_count, and ss_thread_lock.

static int my_dial_digits ( void *  pvt,
enum analog_sub  sub,
struct analog_dialoperation dop 
) [static]

Definition at line 2876 of file chan_dahdi.c.

References ANALOG_DIAL_OP_REPLACE, ANALOG_SUB_REAL, analogsub_to_dahdisub(), ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, analog_dialoperation::dialstr, errno, LOG_DEBUG, LOG_ERROR, ast_channel::name, analog_dialoperation::op, dahdi_pvt::owner, and dahdi_pvt::subs.

02877 {
02878    int index = analogsub_to_dahdisub(sub);
02879    int res;
02880    struct dahdi_pvt *p = pvt;
02881    struct dahdi_dialoperation ddop;
02882 
02883    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02884       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02885       return -1;
02886    }
02887 
02888    if (sub != ANALOG_SUB_REAL)
02889       printf("Trying to dial digits on sub %d\n", sub);
02890 
02891    ddop.op = DAHDI_DIAL_OP_REPLACE;
02892    strncpy(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02893 
02894    printf("Dialing %s on %d\n", ddop.dialstr, p->channel);
02895 
02896    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02897 
02898    if (res == -1)
02899       ast_log(LOG_DEBUG, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02900 
02901    return res;
02902 }

static int my_distinctive_ring ( struct ast_channel chan,
void *  pvt,
int  idx,
int *  ringdata 
) [static]

Definition at line 1748 of file chan_dahdi.c.

References ast_copy_string(), ast_hangup(), ast_log(), ast_verb, ast_channel::context, dahdi_pvt::context, dahdi_get_event(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, errno, event2str(), analog_pvt::inalarm, dahdi_pvt::inalarm, LOG_NOTICE, LOG_WARNING, RING_PATTERNS, analog_pvt::ringt, analog_pvt::ringt_base, dahdi_pvt::sig_pvt, and dahdi_pvt::subs.

01749 {
01750    unsigned char buf[256];
01751    int distMatches;
01752    int curRingData[RING_PATTERNS];
01753    int receivedRingT;
01754    int counter1;
01755    int counter;
01756    int i;
01757    int res;
01758    int checkaftercid = 0;
01759 
01760    struct dahdi_pvt *p = pvt;
01761    struct analog_pvt *analog_p = p->sig_pvt;
01762 
01763    if (ringdata == NULL) {
01764       ringdata = curRingData;
01765    } else {
01766       checkaftercid = 1;
01767    }
01768 
01769    /* We must have a ring by now, so, if configured, lets try to listen for
01770     * distinctive ringing */
01771    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01772       /* Clear the current ring data array so we don't have old data in it. */
01773       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01774          ringdata[receivedRingT] = 0;
01775       receivedRingT = 0;
01776       if (checkaftercid && distinctiveringaftercid)
01777          ast_verb(3, "Detecting post-CID distinctive ring\n");
01778       /* Check to see if context is what it should be, if not set to be. */
01779       else if (strcmp(p->context,p->defcontext) != 0) {
01780          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01781          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01782       }
01783 
01784       for (;;) {
01785          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01786          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01787             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01788             ast_hangup(chan);
01789             return 1;
01790          }
01791          if (i & DAHDI_IOMUX_SIGEVENT) {
01792             res = dahdi_get_event(p->subs[idx].dfd);
01793             if (res == DAHDI_EVENT_NOALARM) {
01794                p->inalarm = 0;
01795                analog_p->inalarm = 0;
01796             }
01797             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01798             res = 0;
01799             /* Let us detect distinctive ring */
01800 
01801             ringdata[receivedRingT] = analog_p->ringt;
01802 
01803             if (analog_p->ringt < analog_p->ringt_base/2)
01804                break;
01805             /* Increment the ringT counter so we can match it against
01806                values in chan_dahdi.conf for distinctive ring */
01807             if (++receivedRingT == RING_PATTERNS)
01808                break;
01809          } else if (i & DAHDI_IOMUX_READ) {
01810             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01811             if (res < 0) {
01812                if (errno != ELAST) {
01813                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01814                   ast_hangup(chan);
01815                   return 1;
01816                }
01817                break;
01818             }
01819             if (analog_p->ringt > 0) {
01820                if (!(--analog_p->ringt)) {
01821                   res = -1;
01822                   break;
01823                }
01824             }
01825          }
01826       }
01827    }
01828    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01829       /* this only shows up if you have n of the dring patterns filled in */
01830       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01831       for (counter = 0; counter < 3; counter++) {
01832       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01833          distMatches = 0;
01834          /* this only shows up if you have n of the dring patterns filled in */
01835          ast_verb(3, "Checking %d,%d,%d\n",
01836                p->drings.ringnum[counter].ring[0],
01837                p->drings.ringnum[counter].ring[1],
01838                p->drings.ringnum[counter].ring[2]);
01839          for (counter1 = 0; counter1 < 3; counter1++) {
01840             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01841             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01842                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01843                ringdata[counter1]);
01844                distMatches++;
01845             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01846                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01847                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01848                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01849                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01850                distMatches++;
01851             }
01852          }
01853 
01854          if (distMatches == 3) {
01855             /* The ring matches, set the context to whatever is for distinctive ring.. */
01856             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01857             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01858             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01859             break;
01860          }
01861       }
01862    }
01863    /* Restore linear mode (if appropriate) for Caller*ID processing */
01864    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01865    restore_gains(p);
01866 
01867    return 0;
01868 }

static int my_dsp_reset_and_flush_digits ( void *  pvt  )  [static]

Definition at line 1952 of file chan_dahdi.c.

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

01953 {
01954    struct dahdi_pvt *p = pvt;
01955    if (p->dsp)
01956       ast_dsp_digitreset(p->dsp);
01957 
01958    return 0;
01959 }

static int my_dsp_set_digitmode ( void *  pvt,
enum analog_dsp_digitmode  mode 
) [static]

Definition at line 1961 of file chan_dahdi.c.

References ANALOG_DIGITMODE_DTMF, ANALOG_DIGITMODE_MF, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_log(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, dahdi_pvt::hardwaredtmf, and LOG_ERROR.

01962 {
01963    struct dahdi_pvt *p = pvt;
01964 
01965    if (p->channel == CHAN_PSEUDO)
01966       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01967 
01968    if (mode == ANALOG_DIGITMODE_DTMF) {
01969       /* If we do hardware dtmf, no need for a DSP */
01970       if (p->hardwaredtmf) {
01971          if (p->dsp) {
01972             ast_dsp_free(p->dsp);
01973             p->dsp = NULL;
01974          }
01975          return 0;
01976       }
01977 
01978       if (!p->dsp) {
01979          p->dsp = ast_dsp_new();
01980          if (!p->dsp) {
01981             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01982             return -1;
01983          }
01984       }
01985 
01986       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01987    } else if (mode == ANALOG_DIGITMODE_MF) {
01988       if (!p->dsp) {
01989          p->dsp = ast_dsp_new();
01990          if (!p->dsp) {
01991             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01992             return -1;
01993          }
01994       }
01995       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01996    }
01997    return 0;
01998 }

static int my_flash ( void *  pvt  )  [static]

Definition at line 2801 of file chan_dahdi.c.

References SUB_REAL, and dahdi_pvt::subs.

02802 {
02803    struct dahdi_pvt *p = pvt;
02804    int func = DAHDI_FLASH;
02805    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02806 }

static void my_get_and_handle_alarms ( void *  pvt  )  [static]

Definition at line 2134 of file chan_dahdi.c.

References get_alarms(), and handle_alarms().

02135 {
02136    int res;
02137    struct dahdi_pvt *p = pvt;
02138 
02139    res = get_alarms(p);
02140    handle_alarms(p, res);
02141 }

static int my_get_callerid ( void *  pvt,
char *  namebuf,
char *  numbuf,
enum analog_event ev,
size_t  timeout 
) [static]

Definition at line 1671 of file chan_dahdi.c.

References ANALOG_EVENT_NONE, ANALOG_MAX_CID, ast_copy_string(), AST_LAW, ast_log(), callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cs, dahdi_get_event(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, errno, LOG_DEBUG, LOG_WARNING, name, analog_pvt::ringt, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

01672 {
01673    struct dahdi_pvt *p = pvt;
01674    struct analog_pvt *analog_p = p->sig_pvt;
01675    struct pollfd poller;
01676    char *name, *num;
01677    int index = SUB_REAL;
01678    int res;
01679    unsigned char buf[256];
01680    int flags;
01681 
01682    poller.fd = p->subs[SUB_REAL].dfd;
01683    poller.events = POLLPRI | POLLIN;
01684    poller.revents = 0;
01685 
01686    res = poll(&poller, 1, timeout);
01687 
01688    if (poller.revents & POLLPRI) {
01689       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01690       return 1;
01691    }
01692 
01693    if (poller.revents & POLLIN) {
01694       /*** NOTES ***/
01695       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01696        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01697        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01698        * a failure and die, and returning 2 means no event was received. */
01699       res = read(p->subs[index].dfd, buf, sizeof(buf));
01700       if (res < 0) {
01701          if (errno != ELAST) {
01702             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01703             callerid_free(p->cs);
01704             return -1;
01705          }
01706       }
01707 
01708       if (analog_p->ringt > 0) {
01709          if (!(--analog_p->ringt)) {
01710             /* only return if we timeout from a ring event */
01711             return -1;
01712          }
01713       }
01714 
01715       if (p->cid_signalling == CID_SIG_V23_JP) {
01716          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01717       } else {
01718          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01719       }
01720       if (res < 0) {
01721          /*
01722           * The previous diagnostic message output likely
01723           * explains why it failed.
01724           */
01725          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01726          return -1;
01727       }
01728 
01729       if (res == 1) {
01730          callerid_get(p->cs, &name, &num, &flags);
01731          if (name)
01732             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01733          if (num)
01734             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01735 
01736          ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01737          return 0;
01738       }
01739    }
01740 
01741    *ev = ANALOG_EVENT_NONE;
01742    return 2;
01743 }

static int my_get_event ( void *  pvt  )  [static]

Definition at line 2734 of file chan_dahdi.c.

References dahdi_get_event(), dahdievent_to_analogevent(), dahdi_pvt::fake_event, SUB_REAL, and dahdi_pvt::subs.

02735 {
02736    struct dahdi_pvt *p = pvt;
02737    int res;
02738 
02739    if (p->fake_event) {
02740       res = p->fake_event;
02741       p->fake_event = 0;
02742    } else
02743       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02744 
02745    return dahdievent_to_analogevent(res);
02746 }

static const char* my_get_orig_dialstring ( void *  pvt  )  [static]

Definition at line 2304 of file chan_dahdi.c.

References dahdi_pvt::dialstring.

02305 {
02306    struct dahdi_pvt *p = pvt;
02307 
02308    return p->dialstring;
02309 }

static void* my_get_sigpvt_bridged_channel ( struct ast_channel chan  )  [static]

Definition at line 2143 of file chan_dahdi.c.

References ast_bridged_channel(), dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.

02144 {
02145    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02146    if (p)
02147       return p->sig_pvt;
02148    else
02149       return NULL;
02150 }

static int my_get_sub_fd ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2152 of file chan_dahdi.c.

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

02153 {
02154    struct dahdi_pvt *p = pvt;
02155    int dahdi_sub = analogsub_to_dahdisub(sub);
02156    return p->subs[dahdi_sub].dfd;
02157 }

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

Definition at line 9496 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

09497 {
09498    char c;
09499 
09500    *str = 0; /* start with empty output buffer */
09501    for (;;)
09502    {
09503       /* Wait for the first digit (up to specified ms). */
09504       c = ast_waitfordigit(chan, ms);
09505       /* if timeout, hangup or error, return as such */
09506       if (c < 1)
09507          return c;
09508       *str++ = c;
09509       *str = 0;
09510       if (strchr(term, c))
09511          return 1;
09512    }
09513 }

static void my_handle_dchan_exception ( struct sig_pri_span pri,
int  index 
) [static]

Definition at line 2996 of file chan_dahdi.c.

References ast_log(), event2str(), sig_pri_span::fds, LOG_NOTICE, dahdi_pvt::pri, pri_event_alarm(), pri_event_noalarm(), and sig_pri_span::span.

02997 {
02998    int x, res;
02999 
03000    res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03001    if (x) {
03002       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03003    }
03004    /* Keep track of alarm state */
03005    switch (x) {
03006    case DAHDI_EVENT_ALARM:
03007       pri_event_alarm(pri, index, 0);
03008       break;
03009    case DAHDI_EVENT_NOALARM:
03010       pri_event_noalarm(pri, index, 0);
03011       break;
03012    default:
03013       break;
03014    }
03015 }

static void my_handle_dtmf ( void *  pvt,
struct ast_channel ast,
enum analog_sub  analog_index,
struct ast_frame **  dest 
) [static]

Definition at line 2018 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_async_goto(), ast_channel_lock, ast_channel_unlock, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, ast_channel::caller, dahdi_pvt::callprogress, CALLPROGRESS_FAX, ast_channel::context, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::name, ast_party_id::number, pbx_builtin_setvar_helper(), S_COR, S_OR, ast_party_number::str, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::usefaxbuffers, and ast_party_number::valid.

02019 {
02020    struct ast_frame *f = *dest;
02021    struct dahdi_pvt *p = pvt;
02022    int idx = analogsub_to_dahdisub(analog_index);
02023 
02024    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02025       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02026       f->subclass.integer, f->subclass.integer, ast->name);
02027 
02028    if (f->subclass.integer == 'f') {
02029       if (f->frametype == AST_FRAME_DTMF_END) {
02030          /* Fax tone -- Handle and return NULL */
02031          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02032             /* If faxbuffers are configured, use them for the fax transmission */
02033             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02034                struct dahdi_bufferinfo bi = {
02035                   .txbufpolicy = p->faxbuf_policy,
02036                   .bufsize = p->bufsize,
02037                   .numbufs = p->faxbuf_no
02038                };
02039                int res;
02040 
02041                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02042                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02043                } else {
02044                   p->bufferoverrideinuse = 1;
02045                }
02046             }
02047             p->faxhandled = 1;
02048             if (p->dsp) {
02049                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02050                ast_dsp_set_features(p->dsp, p->dsp_features);
02051                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02052             }
02053             if (strcmp(ast->exten, "fax")) {
02054                const char *target_context = S_OR(ast->macrocontext, ast->context);
02055 
02056                /* We need to unlock 'ast' here because ast_exists_extension has the
02057                 * potential to start autoservice on the channel. Such action is prone
02058                 * to deadlock.
02059                 */
02060                ast_mutex_unlock(&p->lock);
02061                ast_channel_unlock(ast);
02062                if (ast_exists_extension(ast, target_context, "fax", 1,
02063                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02064                   ast_channel_lock(ast);
02065                   ast_mutex_lock(&p->lock);
02066                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02067                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02068                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02069                   if (ast_async_goto(ast, target_context, "fax", 1))
02070                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02071                } else {
02072                   ast_channel_lock(ast);
02073                   ast_mutex_lock(&p->lock);
02074                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02075                }
02076             } else {
02077                ast_debug(1, "Already in a fax extension, not redirecting\n");
02078             }
02079          } else {
02080             ast_debug(1, "Fax already handled\n");
02081          }
02082          dahdi_confmute(p, 0);
02083       }
02084       p->subs[idx].f.frametype = AST_FRAME_NULL;
02085       p->subs[idx].f.subclass.integer = 0;
02086       *dest = &p->subs[idx].f;
02087    }
02088 }

static void my_handle_link_exception ( struct sig_ss7_linkset linkset,
int  which 
) [static]

Definition at line 3308 of file chan_dahdi.c.

References ast_log(), event2str(), sig_ss7_linkset::fds, LOG_ERROR, LOG_NOTICE, sig_ss7_link_alarm(), sig_ss7_link_noalarm(), and sig_ss7_linkset::span.

03309 {
03310    int event;
03311 
03312    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03313       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03314          linkset->span, which);
03315       return;
03316    }
03317    switch (event) {
03318    case DAHDI_EVENT_NONE:
03319       break;
03320    case DAHDI_EVENT_ALARM:
03321       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03322          event2str(event), event, linkset->span, which);
03323       sig_ss7_link_alarm(linkset, which);
03324       break;
03325    case DAHDI_EVENT_NOALARM:
03326       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03327          event2str(event), event, linkset->span, which);
03328       sig_ss7_link_noalarm(linkset, which);
03329       break;
03330    default:
03331       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03332          event2str(event), event, linkset->span, which);
03333       break;
03334    }
03335 }

static void my_handle_notify_message ( struct ast_channel chan,
void *  pvt,
int  cid_flags,
int  neon_mwievent 
) [static]

Definition at line 3504 of file chan_dahdi.c.

References ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ast_hangup(), ast_log(), dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, LOG_NOTICE, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, and notify_message().

03505 {
03506    struct dahdi_pvt *p = pvt;
03507 
03508    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03509       return;
03510 
03511    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03512       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03513       notify_message(p->mailbox, 1);
03514    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03515       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03516       notify_message(p->mailbox, 0);
03517    }
03518    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03519    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03520    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03521       ast_hangup(chan);
03522       return;
03523    }
03524 }

static void my_hangup_polarityswitch ( void *  pvt  )  [static]

Definition at line 2853 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().

02854 {
02855    struct dahdi_pvt *p = pvt;
02856 
02857    if (!p->hanguponpolarityswitch) {
02858       return;
02859    }
02860 
02861    if (p->answeronpolarityswitch) {
02862       my_set_polarity(pvt, 0);
02863    } else {
02864       my_set_polarity(pvt, 1);
02865    }
02866 }

static int my_has_voicemail ( void *  pvt  )  [static]

Definition at line 2613 of file chan_dahdi.c.

References has_voicemail().

02614 {
02615    struct dahdi_pvt *p = pvt;
02616 
02617    return has_voicemail(p);
02618 }

static void my_increase_ss_count ( void   )  [static]

Definition at line 2311 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, ss_thread_count, and ss_thread_lock.

static int my_is_dialing ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2915 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_log(), dahdi_subchannel::dfd, LOG_DEBUG, and dahdi_pvt::subs.

02916 {
02917    struct dahdi_pvt *p = pvt;
02918    int index;
02919    int x;
02920 
02921    index = analogsub_to_dahdisub(sub);
02922 
02923    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
02924       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
02925       return -1;
02926    }
02927 
02928    return x;
02929 }

static int my_is_off_hook ( void *  pvt  )  [static]

Definition at line 2748 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SUB_REAL, and dahdi_pvt::subs.

02749 {
02750    struct dahdi_pvt *p = pvt;
02751    int res;
02752    struct dahdi_params par;
02753 
02754    memset(&par, 0, sizeof(par));
02755 
02756    if (p->subs[SUB_REAL].dfd > -1)
02757       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02758    else {
02759       /* Assume not off hook on CVRS */
02760       res = 0;
02761       par.rxisoffhook = 0;
02762    }
02763    if (res) {
02764       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02765    }
02766 
02767    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02768       /* When "onhook" that means no battery on the line, and thus
02769       it is out of service..., if it's on a TDM card... If it's a channel
02770       bank, there is no telling... */
02771       return (par.rxbits > -1) || par.rxisoffhook;
02772    }
02773 
02774    return par.rxisoffhook;
02775 }

static void my_lock_private ( void *  pvt  )  [static]

Definition at line 2090 of file chan_dahdi.c.

References ast_mutex_lock, and dahdi_pvt::lock.

02091 {
02092    struct dahdi_pvt *p = pvt;
02093    ast_mutex_lock(&p->lock);
02094 }

static void my_module_ref ( void   )  [static]

Definition at line 3242 of file chan_dahdi.c.

References ast_module_ref().

03243 {
03244    ast_module_ref(ast_module_info->self);
03245 }

static void my_module_unref ( void   )  [static]

Definition at line 3256 of file chan_dahdi.c.

References ast_module_unref().

03257 {
03258    ast_module_unref(ast_module_info->self);
03259 }

static struct ast_channel* my_new_analog_ast_channel ( void *  pvt,
int  state,
int  startpbx,
enum analog_sub  sub,
const struct ast_channel requestor 
) [static]

Definition at line 2476 of file chan_dahdi.c.

References analogsub_to_dahdisub(), dahdi_new(), and ast_channel::linkedid.

02477 {
02478    struct dahdi_pvt *p = pvt;
02479    int dsub = analogsub_to_dahdisub(sub);
02480 
02481    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02482 }

static struct ast_channel* my_new_pri_ast_channel ( void *  pvt,
int  state,
enum sig_pri_law  law,
char *  exten,
const struct ast_channel requestor 
) [static]

Definition at line 2496 of file chan_dahdi.c.

References ast_copy_string(), ast_log(), dahdi_pvt::channel, dahdi_new(), dahdi_setlaw(), errno, dahdi_pvt::exten, ast_channel::linkedid, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_ALAW, SIG_PRI_DEFLAW, SIG_PRI_LIB_HANDLE_CASES, SIG_PRI_ULAW, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

02497 {
02498    struct dahdi_pvt *p = pvt;
02499    int audio;
02500    int newlaw = -1;
02501 
02502    switch (p->sig) {
02503    case SIG_PRI_LIB_HANDLE_CASES:
02504       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02505          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02506          break;
02507       }
02508       /* Fall through */
02509    default:
02510       /* Set to audio mode at this point */
02511       audio = 1;
02512       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02513          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02514             p->channel, audio, strerror(errno));
02515       }
02516       break;
02517    }
02518 
02519    if (law != SIG_PRI_DEFLAW) {
02520       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02521    }
02522 
02523    ast_copy_string(p->exten, exten, sizeof(p->exten));
02524 
02525    switch (law) {
02526       case SIG_PRI_DEFLAW:
02527          newlaw = 0;
02528          break;
02529       case SIG_PRI_ALAW:
02530          newlaw = DAHDI_LAW_ALAW;
02531          break;
02532       case SIG_PRI_ULAW:
02533          newlaw = DAHDI_LAW_MULAW;
02534          break;
02535    }
02536    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02537 }

static struct ast_channel* my_new_ss7_ast_channel ( void *  pvt,
int  state,
enum sig_ss7_law  law,
char *  exten,
const struct ast_channel requestor 
) [static]

Definition at line 3365 of file chan_dahdi.c.

References ast_copy_string(), ast_log(), dahdi_pvt::channel, dahdi_new(), dahdi_setlaw(), errno, dahdi_pvt::exten, ast_channel::linkedid, LOG_WARNING, SIG_SS7_ALAW, SIG_SS7_DEFLAW, SIG_SS7_ULAW, SUB_REAL, and dahdi_pvt::subs.

03366 {
03367    struct dahdi_pvt *p = pvt;
03368    int audio;
03369    int newlaw;
03370 
03371    /* Set to audio mode at this point */
03372    audio = 1;
03373    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03374       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03375          p->channel, audio, strerror(errno));
03376 
03377    if (law != SIG_SS7_DEFLAW) {
03378       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03379          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03380    }
03381 
03382    ast_copy_string(p->exten, exten, sizeof(p->exten));
03383 
03384    newlaw = -1;
03385    switch (law) {
03386    case SIG_SS7_DEFLAW:
03387       newlaw = 0;
03388       break;
03389    case SIG_SS7_ALAW:
03390       newlaw = DAHDI_LAW_ALAW;
03391       break;
03392    case SIG_SS7_ULAW:
03393       newlaw = DAHDI_LAW_MULAW;
03394       break;
03395    }
03396    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03397 }

static int my_off_hook ( void *  pvt  )  [static]

Definition at line 2810 of file chan_dahdi.c.

References dahdi_set_hook(), SUB_REAL, and dahdi_pvt::subs.

02811 {
02812    struct dahdi_pvt *p = pvt;
02813    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02814 }

static int my_on_hook ( void *  pvt  )  [static]

Definition at line 2931 of file chan_dahdi.c.

References ANALOG_SUB_REAL, dahdi_set_hook(), and dahdi_pvt::subs.

02932 {
02933    struct dahdi_pvt *p = pvt;
02934    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
02935 }

static int my_play_tone ( void *  pvt,
enum analog_sub  sub,
enum analog_tone  tone 
) [static]

Definition at line 2620 of file chan_dahdi.c.

References analog_tone_to_dahditone(), analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.

02621 {
02622    struct dahdi_pvt *p = pvt;
02623    int index;
02624 
02625    index = analogsub_to_dahdisub(sub);
02626 
02627    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02628 }

static void my_pri_fixup_chans ( void *  chan_old,
void *  chan_new 
) [static]

Definition at line 2938 of file chan_dahdi.c.

References dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dialstring, dahdi_pvt::digital, dahdi_pvt::dsp, dahdi_pvt::dsp_features, ast_channel::fds, dahdi_pvt::law, dahdi_pvt::outgoing, dahdi_subchannel::owner, dahdi_pvt::owner, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

02939 {
02940    struct dahdi_pvt *old_chan = chan_old;
02941    struct dahdi_pvt *new_chan = chan_new;
02942 
02943    new_chan->owner = old_chan->owner;
02944    old_chan->owner = NULL;
02945    if (new_chan->owner) {
02946       new_chan->owner->tech_pvt = new_chan;
02947       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
02948       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
02949       old_chan->subs[SUB_REAL].owner = NULL;
02950    }
02951    /* Copy any DSP that may be present */
02952    new_chan->dsp = old_chan->dsp;
02953    new_chan->dsp_features = old_chan->dsp_features;
02954    old_chan->dsp = NULL;
02955    old_chan->dsp_features = 0;
02956 
02957    /* Transfer flags from the old channel. */
02958    new_chan->dialing = old_chan->dialing;
02959    new_chan->digital = old_chan->digital;
02960    new_chan->outgoing = old_chan->outgoing;
02961    old_chan->dialing = 0;
02962    old_chan->digital = 0;
02963    old_chan->outgoing = 0;
02964 
02965    /* More stuff to transfer to the new channel. */
02966    new_chan->law = old_chan->law;
02967    strcpy(new_chan->dialstring, old_chan->dialstring);
02968 }

static void my_pri_make_cc_dialstring ( void *  priv,
char *  buf,
size_t  buf_size 
) [static]

Definition at line 3126 of file chan_dahdi.c.

References args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_NONSTANDARD_APP_ARGS, and ast_strdupa.

03127 {
03128    char *dial;
03129    struct dahdi_pvt *pvt;
03130    AST_DECLARE_APP_ARGS(args,
03131       AST_APP_ARG(tech);   /* channel technology token */
03132       AST_APP_ARG(group);  /* channel/group token */
03133       //AST_APP_ARG(ext);  /* extension token */
03134       //AST_APP_ARG(opts); /* options token */
03135       //AST_APP_ARG(other);   /* Any remining unused arguments */
03136    );
03137 
03138    pvt = priv;
03139    dial = ast_strdupa(pvt->dialstring);
03140    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03141    if (!args.tech) {
03142       ast_copy_string(buf, pvt->dialstring, buf_size);
03143       return;
03144    }
03145    if (!args.group) {
03146       /* Append the ISDN span channel restriction to the dialstring. */
03147       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03148       return;
03149    }
03150    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03151       /* The ISDN span channel restriction is not needed or already
03152        * in the dialstring. */
03153       ast_copy_string(buf, pvt->dialstring, buf_size);
03154       return;
03155    }
03156    /* Insert the ISDN span channel restriction into the dialstring. */
03157    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03158 }

static void my_pri_open_media ( void *  p  )  [static]

Definition at line 2552 of file chan_dahdi.c.

References ast_dsp_set_features(), ast_log(), dahdi_pvt::channel, dahdi_setlaw(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dsp, dahdi_pvt::dsp_features, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, and dahdi_pvt::txgain.

02553 {
02554    struct dahdi_pvt *pvt = p;
02555    int res;
02556    int dfd;
02557    int set_val;
02558 
02559    dfd = pvt->subs[SUB_REAL].dfd;
02560 
02561    /* Open the media path. */
02562    set_val = 1;
02563    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02564    if (res < 0) {
02565       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02566          pvt->channel, strerror(errno));
02567    }
02568 
02569    /* Set correct companding law for this call. */
02570    res = dahdi_setlaw(dfd, pvt->law);
02571    if (res < 0) {
02572       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02573    }
02574 
02575    /* Set correct gain for this call. */
02576    if (pvt->digital) {
02577       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02578    } else {
02579       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02580          pvt->law);
02581    }
02582    if (res < 0) {
02583       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02584    }
02585 
02586    if (pvt->dsp_features && pvt->dsp) {
02587       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02588       pvt->dsp_features = 0;
02589    }
02590 }

static int my_pri_play_tone ( void *  pvt,
enum sig_pri_tone  tone 
) [static]

Definition at line 3019 of file chan_dahdi.c.

References sig_pri_tone_to_dahditone(), SUB_REAL, and dahdi_pvt::subs.

03020 {
03021    struct dahdi_pvt *p = pvt;
03022 
03023    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03024 }

static int my_ring ( void *  pvt  )  [static]

Definition at line 2794 of file chan_dahdi.c.

References dahdi_ring_phone().

02795 {
02796    struct dahdi_pvt *p = pvt;
02797 
02798    return dahdi_ring_phone(p);
02799 }

static int my_send_callerid ( void *  pvt,
int  cwcid,
struct ast_party_caller caller 
) [static]

Definition at line 1917 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), ast_callerid_generate(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, ast_verb, dahdi_pvt::callwaitcas, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, ast_party_caller::id, LOG_WARNING, MAX_CALLERID_SIZE, ast_party_id::name, ast_party_id::number, READ_SIZE, send_callerid(), ast_party_number::str, and ast_party_name::str.

01918 {
01919    struct dahdi_pvt *p = pvt;
01920 
01921    ast_debug(2, "Starting cid spill\n");
01922 
01923    if (p->cidspill) {
01924       ast_log(LOG_WARNING, "cidspill already exists??\n");
01925       ast_free(p->cidspill);
01926    }
01927 
01928    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01929       if (cwcid == 0) {
01930          p->cidlen = ast_callerid_generate(p->cidspill,
01931             caller->id.name.str,
01932             caller->id.number.str,
01933             AST_LAW(p));
01934       } else {
01935          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01936             caller->id.name.str, caller->id.number.str);
01937          p->callwaitcas = 0;
01938          p->cidcwexpire = 0;
01939          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01940             caller->id.name.str,
01941             caller->id.number.str,
01942             AST_LAW(p));
01943          p->cidlen += READ_SIZE * 4;
01944       }
01945       p->cidpos = 0;
01946       p->cid_suppress_expire = 0;
01947       send_callerid(p);
01948    }
01949    return 0;
01950 }

static void my_set_alarm ( void *  pvt,
int  in_alarm 
) [static]

Definition at line 2175 of file chan_dahdi.c.

References dahdi_pvt::inalarm.

02176 {
02177    struct dahdi_pvt *p = pvt;
02178 
02179    p->inalarm = in_alarm;
02180 }

static void my_set_cadence ( void *  pvt,
int *  cidrings,
struct ast_channel ast 
) [static]

Definition at line 2159 of file chan_dahdi.c.

References ast_log(), cadences, dahdi_pvt::distinctivering, errno, LOG_WARNING, ast_channel::name, num_cadence, dahdi_pvt::sendcalleridafter, SUB_REAL, and dahdi_pvt::subs.

02160 {
02161    struct dahdi_pvt *p = pvt;
02162 
02163    /* Choose proper cadence */
02164    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02165       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02166          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02167       *cidrings = cidrings[p->distinctivering - 1];
02168    } else {
02169       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02170          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02171       *cidrings = p->sendcalleridafter;
02172    }
02173 }

static void my_set_callerid ( void *  pvt,
const struct ast_party_caller caller 
) [static]

Definition at line 3038 of file chan_dahdi.c.

References ast_party_caller::ani, ast_party_caller::ani2, ast_copy_string(), ast_party_id_presentation(), dahdi_pvt::callingpres, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_party_number::plan, S_COR, ast_party_subaddress::str, ast_party_name::str, ast_party_number::str, ast_party_id::subaddress, ast_party_id::tag, ast_party_subaddress::valid, ast_party_name::valid, and ast_party_number::valid.

03039 {
03040    struct dahdi_pvt *p = pvt;
03041 
03042    ast_copy_string(p->cid_num,
03043       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03044       sizeof(p->cid_num));
03045    ast_copy_string(p->cid_name,
03046       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03047       sizeof(p->cid_name));
03048    ast_copy_string(p->cid_subaddr,
03049       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03050       sizeof(p->cid_subaddr));
03051    p->cid_ton = caller->id.number.plan;
03052    p->callingpres = ast_party_id_presentation(&caller->id);
03053    if (caller->id.tag) {
03054       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03055    }
03056    ast_copy_string(p->cid_ani,
03057       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03058       sizeof(p->cid_ani));
03059    p->cid_ani2 = caller->ani2;
03060 }

static void my_set_callwaiting ( void *  pvt,
int  callwaiting_enable 
) [static]

Definition at line 2269 of file chan_dahdi.c.

References dahdi_pvt::callwaiting.

02270 {
02271    struct dahdi_pvt *p = pvt;
02272 
02273    p->callwaiting = callwaiting_enable;
02274 }

static void my_set_confirmanswer ( void *  pvt,
int  flag 
) [static]

Definition at line 2253 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02254 {
02255    struct dahdi_pvt *p = pvt;
02256    p->confirmanswer = flag;
02257 }

static void my_set_dialing ( void *  pvt,
int  is_dialing 
) [static]

Definition at line 2182 of file chan_dahdi.c.

References dahdi_pvt::dialing.

02183 {
02184    struct dahdi_pvt *p = pvt;
02185 
02186    p->dialing = is_dialing;
02187 }

static void my_set_digital ( void *  pvt,
int  is_digital 
) [static]

Definition at line 2190 of file chan_dahdi.c.

References dahdi_pvt::digital.

02191 {
02192    struct dahdi_pvt *p = pvt;
02193 
02194    p->digital = is_digital;
02195 }

static void my_set_dnid ( void *  pvt,
const char *  dnid 
) [static]

Definition at line 3074 of file chan_dahdi.c.

References ast_copy_string(), and dahdi_pvt::dnid.

03075 {
03076    struct dahdi_pvt *p = pvt;
03077 
03078    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03079 }

static int my_set_echocanceller ( void *  pvt,
int  enable 
) [static]

Definition at line 2780 of file chan_dahdi.c.

References dahdi_disable_ec(), and dahdi_enable_ec().

02781 {
02782    struct dahdi_pvt *p = pvt;
02783 
02784    if (enable)
02785       dahdi_enable_ec(p);
02786    else
02787       dahdi_disable_ec(p);
02788 
02789    return 0;
02790 }

static void my_set_inservice ( void *  pvt,
int  is_inservice 
) [static]

Definition at line 2199 of file chan_dahdi.c.

References dahdi_pvt::inservice.

02200 {
02201    struct dahdi_pvt *p = pvt;
02202 
02203    p->inservice = is_inservice;
02204 }

static void my_set_inthreeway ( void *  pvt,
enum analog_sub  sub,
int  inthreeway 
) [static]

Definition at line 2124 of file chan_dahdi.c.

References analogsub_to_dahdisub(), dahdi_subchannel::inthreeway, and dahdi_pvt::subs.

02125 {
02126    struct dahdi_pvt *p = pvt;
02127    int idx = analogsub_to_dahdisub(sub);
02128 
02129    p->subs[idx].inthreeway = inthreeway;
02130 }

static int my_set_linear_mode ( void *  pvt,
enum analog_sub  sub,
int  linear_mode 
) [static]

Definition at line 2112 of file chan_dahdi.c.

References analogsub_to_dahdisub(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, and dahdi_pvt::subs.

02113 {
02114    struct dahdi_pvt *p = pvt;
02115    int oldval;
02116    int idx = analogsub_to_dahdisub(sub);
02117    
02118    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02119    oldval = p->subs[idx].linear;
02120    p->subs[idx].linear = linear_mode ? 1 : 0;
02121    return oldval;
02122 }

static void my_set_locallyblocked ( void *  pvt,
int  is_blocked 
) [static]

Definition at line 2208 of file chan_dahdi.c.

References dahdi_pvt::locallyblocked.

02209 {
02210    struct dahdi_pvt *p = pvt;
02211 
02212    p->locallyblocked = is_blocked;
02213 }

static void my_set_needringing ( void *  pvt,
int  value 
) [static]

Definition at line 2816 of file chan_dahdi.c.

References dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.

02817 {
02818    struct dahdi_pvt *p = pvt;
02819    p->subs[SUB_REAL].needringing = value;
02820 }

static void my_set_new_owner ( void *  pvt,
struct ast_channel new_owner 
) [static]

Definition at line 2297 of file chan_dahdi.c.

References dahdi_pvt::owner.

02298 {
02299    struct dahdi_pvt *p = pvt;
02300 
02301    p->owner = new_owner;
02302 }

static void my_set_polarity ( void *  pvt,
int  value 
) [static]

Definition at line 2822 of file chan_dahdi.c.

References CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::polarity, SUB_REAL, and dahdi_pvt::subs.

Referenced by my_answer_polarityswitch(), my_hangup_polarityswitch(), and my_start_polarityswitch().

02823 {
02824    struct dahdi_pvt *p = pvt;
02825 
02826    if (p->channel == CHAN_PSEUDO) {
02827       return;
02828    }
02829    p->polarity = value;
02830    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02831 }

static void my_set_pulsedial ( void *  pvt,
int  flag 
) [static]

Definition at line 2291 of file chan_dahdi.c.

References dahdi_pvt::pulsedial.

02292 {
02293    struct dahdi_pvt *p = pvt;
02294    p->pulsedial = flag;
02295 }

static void my_set_rdnis ( void *  pvt,
const char *  rdnis 
) [static]

Definition at line 3093 of file chan_dahdi.c.

References ast_copy_string(), and dahdi_pvt::rdnis.

03094 {
03095    struct dahdi_pvt *p = pvt;
03096 
03097    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03098 }

static void my_set_remotelyblocked ( void *  pvt,
int  is_blocked 
) [static]

Definition at line 2217 of file chan_dahdi.c.

References dahdi_pvt::remotelyblocked.

02218 {
02219    struct dahdi_pvt *p = pvt;
02220 
02221    p->remotelyblocked = is_blocked;
02222 }

static void my_set_ringtimeout ( void *  pvt,
int  ringt 
) [static]

Definition at line 2225 of file chan_dahdi.c.

References dahdi_pvt::ringt.

02226 {
02227    struct dahdi_pvt *p = pvt;
02228    p->ringt = ringt;
02229 }

static void my_set_waitingfordt ( void *  pvt,
struct ast_channel ast 
) [static]

Definition at line 2231 of file chan_dahdi.c.

References ast_log(), ast_setstate(), AST_STATE_OFFHOOK, CANPROGRESSDETECT, dahdi_pvt::dsp, LOG_DEBUG, dahdi_pvt::waitfordialtone, and dahdi_pvt::waitingfordt.

02232 {
02233    struct dahdi_pvt *p = pvt;
02234 
02235    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02236       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02237       gettimeofday(&p->waitingfordt, NULL);
02238       ast_setstate(ast, AST_STATE_OFFHOOK);
02239    }
02240 }

static int my_ss7_play_tone ( void *  pvt,
enum sig_ss7_tone  tone 
) [static]

Definition at line 3425 of file chan_dahdi.c.

References sig_ss7_tone_to_dahditone(), SUB_REAL, and dahdi_pvt::subs.

03426 {
03427    struct dahdi_pvt *p = pvt;
03428 
03429    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03430 }

static void my_ss7_set_loopback ( void *  pvt,
int  enable 
) [static]

Definition at line 3339 of file chan_dahdi.c.

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

03340 {
03341    struct dahdi_pvt *p = pvt;
03342 
03343    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03344       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03345          strerror(errno));
03346    }
03347 }

static int my_start ( void *  pvt  )  [static]

Definition at line 2868 of file chan_dahdi.c.

References SUB_REAL, and dahdi_pvt::subs.

02869 {
02870    struct dahdi_pvt *p = pvt;
02871    int x = DAHDI_START;
02872 
02873    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02874 }

static int my_start_cid_detect ( void *  pvt,
int  cid_signalling 
) [static]

Definition at line 1646 of file chan_dahdi.c.

References ast_log(), bump_gains(), callerid_new(), dahdi_pvt::cs, dahdi_setlinear(), dahdi_subchannel::dfd, LOG_ERROR, SUB_REAL, and dahdi_pvt::subs.

01647 {
01648    struct dahdi_pvt *p = pvt;
01649    int index = SUB_REAL;
01650    p->cs = callerid_new(cid_signalling);
01651    if (!p->cs) {
01652       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01653       return -1;
01654    }
01655    bump_gains(p);
01656    dahdi_setlinear(p->subs[index].dfd, 0);
01657 
01658    return 0;
01659 }

static void my_start_polarityswitch ( void *  pvt  )  [static]

Definition at line 2833 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().

02834 {
02835    struct dahdi_pvt *p = pvt;
02836 
02837    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02838       my_set_polarity(pvt, 0);
02839    }
02840 }

static int my_stop_callwait ( void *  pvt  )  [static]

Definition at line 1870 of file chan_dahdi.c.

References dahdi_pvt::callwaitingrepeat, dahdi_pvt::cid_suppress_expire, and dahdi_pvt::cidcwexpire.

01871 {
01872    struct dahdi_pvt *p = pvt;
01873    p->callwaitingrepeat = 0;
01874    p->cidcwexpire = 0;
01875    p->cid_suppress_expire = 0;
01876 
01877    return 0;
01878 }

static int my_stop_cid_detect ( void *  pvt  )  [static]

Definition at line 1661 of file chan_dahdi.c.

References callerid_free(), dahdi_pvt::cs, dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, SUB_REAL, and dahdi_pvt::subs.

01662 {
01663    struct dahdi_pvt *p = pvt;
01664    int index = SUB_REAL;
01665    if (p->cs)
01666       callerid_free(p->cs);
01667    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01668    return 0;
01669 }

static void my_swap_subchannels ( void *  pvt,
enum analog_sub  a,
struct ast_channel ast_a,
enum analog_sub  b,
struct ast_channel ast_b 
) [static]

Definition at line 2442 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_channel_set_fd(), dahdi_subchannel::chan, db, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().

02443 {
02444    struct dahdi_pvt *p = pvt;
02445    int da, db;
02446    int tchan;
02447    int tinthreeway;
02448 
02449    da = analogsub_to_dahdisub(a);
02450    db = analogsub_to_dahdisub(b);
02451 
02452    tchan = p->subs[da].chan;
02453    p->subs[da].chan = p->subs[db].chan;
02454    p->subs[db].chan = tchan;
02455 
02456    tinthreeway = p->subs[da].inthreeway;
02457    p->subs[da].inthreeway = p->subs[db].inthreeway;
02458    p->subs[db].inthreeway = tinthreeway;
02459 
02460    p->subs[da].owner = ast_a;
02461    p->subs[db].owner = ast_b;
02462 
02463    if (ast_a)
02464       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02465    if (ast_b)
02466       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02467 
02468    wakeup_sub(p, a);
02469    wakeup_sub(p, b);
02470 
02471    return;
02472 }

static int my_train_echocanceller ( void *  pvt  )  [static]

Definition at line 2906 of file chan_dahdi.c.

References dahdi_train_ec().

02907 {
02908    struct dahdi_pvt *p = pvt;
02909 
02910    dahdi_train_ec(p);
02911 
02912    return 0;
02913 }

static int my_unallocate_sub ( void *  pvt,
enum analog_sub  analogsub 
) [static]

Definition at line 2595 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and unalloc_sub().

02596 {
02597    struct dahdi_pvt *p = pvt;
02598 
02599    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02600 }

static void my_unlock_private ( void *  pvt  )  [static]

Definition at line 2096 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pvt::lock.

02097 {
02098    struct dahdi_pvt *p = pvt;
02099    ast_mutex_unlock(&p->lock);
02100 }

static int my_wait_event ( void *  pvt  )  [static]

Definition at line 2727 of file chan_dahdi.c.

References dahdi_wait_event(), SUB_REAL, and dahdi_pvt::subs.

02728 {
02729    struct dahdi_pvt *p = pvt;
02730 
02731    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02732 }

static int my_wink ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2002 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_log(), dahdi_wink(), LOG_ERROR, and SUB_REAL.

02003 {
02004    struct dahdi_pvt *p = pvt;
02005    int index = analogsub_to_dahdisub(sub);
02006    if (index != SUB_REAL) {
02007       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02008    }
02009    return dahdi_wink(p, index);
02010 }

static void notify_message ( char *  mailbox_full,
int  thereornot 
) [static]

Send MWI state change.

Returns:
nothing
This function does two things:

1) It generates an internal Asterisk event notifying any other module that cares about MWI that the state of a mailbox has changed.

2) It runs the script specified by the mwimonitornotify option to allow some custom handling of the state change.

Definition at line 3475 of file chan_dahdi.c.

References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_safe_system(), ast_strdupa, ast_strlen_zero(), context, mailbox, mwimonitornotify, and strsep().

Referenced by handle_init_event(), and my_handle_notify_message().

03476 {
03477    char s[sizeof(mwimonitornotify) + 80];
03478    struct ast_event *event;
03479    char *mailbox, *context;
03480 
03481    /* Strip off @default */
03482    context = mailbox = ast_strdupa(mailbox_full);
03483    strsep(&context, "@");
03484    if (ast_strlen_zero(context))
03485       context = "default";
03486 
03487    if (!(event = ast_event_new(AST_EVENT_MWI,
03488          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03489          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03490          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03491          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03492          AST_EVENT_IE_END))) {
03493       return;
03494    }
03495 
03496    ast_event_queue_and_cache(event);
03497 
03498    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03499       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03500       ast_safe_system(s);
03501    }
03502 }

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

Definition at line 6820 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write().

06821 {
06822    int res;
06823    char policy_str[21] = "";
06824 
06825    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06826       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06827       return 1;
06828    }
06829    if (*num_buffers < 0) {
06830       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06831       return -1;
06832    }
06833    if (!strcasecmp(policy_str, "full")) {
06834       *policy = DAHDI_POLICY_WHEN_FULL;
06835    } else if (!strcasecmp(policy_str, "immediate")) {
06836       *policy = DAHDI_POLICY_IMMEDIATE;
06837 #if defined(HAVE_DAHDI_HALF_FULL)
06838    } else if (!strcasecmp(policy_str, "half")) {
06839       *policy = DAHDI_POLICY_HALF_FULL;
06840 #endif
06841    } else {
06842       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06843       return -1;
06844    }
06845 
06846    return 0;
06847 }

static unsigned int parse_pointcode ( const char *  pcstring  )  [static]

Definition at line 11739 of file chan_dahdi.c.

11740 {
11741    unsigned int code1, code2, code3;
11742    int numvals;
11743 
11744    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11745    if (numvals == 1)
11746       return code1;
11747    if (numvals == 3)
11748       return (code1 << 16) | (code2 << 8) | code3;
11749 
11750    return 0;
11751 }

static char* parse_spanchan ( char *  chanstr,
char **  subdir 
) [static]

Definition at line 16294 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

16295 {
16296    char *p;
16297 
16298    if ((p = strrchr(chanstr, '!')) == NULL) {
16299       *subdir = NULL;
16300       return chanstr;
16301    }
16302    *p++ = '\0';
16303    string_replace(chanstr, '!', '/');
16304    *subdir = chanstr;
16305    return p;
16306 }

static int prepare_pri ( struct dahdi_pri pri  )  [static]

Definition at line 13766 of file chan_dahdi.c.

References ast_log(), sig_pri_span::calls, dahdi_close_pri_fd(), dahdi_pri_callbacks, sig_pri_span::dchan_logical_span, dahdi_pri::dchannels, errno, sig_pri_span::fds, dahdi_pri::pri, pri_event_alarm(), pri_event_noalarm(), dahdi_pri::prilogicalspan, and pris.

Referenced by setup_dahdi_int().

13767 {
13768    int i, res, x;
13769    struct dahdi_params p;
13770    struct dahdi_bufferinfo bi;
13771    struct dahdi_spaninfo si;
13772 
13773    pri->pri.calls = &dahdi_pri_callbacks;
13774 
13775    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
13776       if (!pri->dchannels[i])
13777          break;
13778       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
13779       x = pri->dchannels[i];
13780       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
13781          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13782          return -1;
13783       }
13784       memset(&p, 0, sizeof(p));
13785       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
13786       if (res) {
13787          dahdi_close_pri_fd(pri, i);
13788          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13789          return -1;
13790       }
13791       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13792          dahdi_close_pri_fd(pri, i);
13793          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13794          return -1;
13795       }
13796       memset(&si, 0, sizeof(si));
13797       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
13798       if (res) {
13799          dahdi_close_pri_fd(pri, i);
13800          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13801       }
13802       if (!si.alarms) {
13803          pri_event_noalarm(&pri->pri, i, 1);
13804       } else {
13805          pri_event_alarm(&pri->pri, i, 1);
13806       }
13807       memset(&bi, 0, sizeof(bi));
13808       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13809       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13810       bi.numbufs = 32;
13811       bi.bufsize = 1024;
13812       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
13813          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13814          dahdi_close_pri_fd(pri, i);
13815          return -1;
13816       }
13817       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
13818    }
13819    return 0;
13820 }

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

Definition at line 11726 of file chan_dahdi.c.

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

Referenced by setup_dahdi_int().

11727 {
11728    if (pris[span].mastertrunkgroup) {
11729       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);
11730       return -1;
11731    }
11732    pris[span].mastertrunkgroup = trunkgroup;
11733    pris[span].prilogicalspan = logicalspan;
11734    return 0;
11735 }

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

Definition at line 11663 of file chan_dahdi.c.

References ast_log(), NUM_SPANS, and pris.

Referenced by setup_dahdi_int().

11664 {
11665    struct dahdi_spaninfo si;
11666    struct dahdi_params p;
11667    int fd;
11668    int span;
11669    int ospan=0;
11670    int x,y;
11671    for (x = 0; x < NUM_SPANS; x++) {
11672       if (pris[x].pri.trunkgroup == trunkgroup) {
11673          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11674          return -1;
11675       }
11676    }
11677    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11678       if (!channels[y])
11679          break;
11680       memset(&si, 0, sizeof(si));
11681       memset(&p, 0, sizeof(p));
11682       fd = open("/dev/dahdi/channel", O_RDWR);
11683       if (fd < 0) {
11684          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11685          return -1;
11686       }
11687       x = channels[y];
11688       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11689          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11690          close(fd);
11691          return -1;
11692       }
11693       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11694          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11695          return -1;
11696       }
11697       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11698          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11699          close(fd);
11700          return -1;
11701       }
11702       span = p.spanno - 1;
11703       if (pris[span].pri.trunkgroup) {
11704          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11705          close(fd);
11706          return -1;
11707       }
11708       if (pris[span].pri.pvts[0]) {
11709          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11710          close(fd);
11711          return -1;
11712       }
11713       if (!y) {
11714          pris[span].pri.trunkgroup = trunkgroup;
11715          ospan = span;
11716       }
11717       pris[ospan].dchannels[y] = channels[y];
11718       pris[span].pri.span = span + 1;
11719       close(fd);
11720    }
11721    return 0;
11722 }

static int pri_resolve_span ( int *  span,
int  channel,
int  offset,
struct dahdi_spaninfo *  si 
) [static]

Definition at line 11617 of file chan_dahdi.c.

References ast_log(), dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pvt::pri, pris, and sig_pri_span::trunkgroup.

11618 {
11619    int x;
11620    int trunkgroup;
11621    /* Get appropriate trunk group if there is one */
11622    trunkgroup = pris[*span].mastertrunkgroup;
11623    if (trunkgroup) {
11624       /* Select a specific trunk group */
11625       for (x = 0; x < NUM_SPANS; x++) {
11626          if (pris[x].pri.trunkgroup == trunkgroup) {
11627             *span = x;
11628             return 0;
11629          }
11630       }
11631       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11632       *span = -1;
11633    } else {
11634       if (pris[*span].pri.trunkgroup) {
11635          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
11636          *span = -1;
11637       } else if (pris[*span].mastertrunkgroup) {
11638          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11639          *span = -1;
11640       } else {
11641          if (si->totalchans == 31) {
11642             /* E1 */
11643             pris[*span].dchannels[0] = 16 + offset;
11644          } else if (si->totalchans == 24) {
11645             /* T1 or J1 */
11646             pris[*span].dchannels[0] = 24 + offset;
11647          } else if (si->totalchans == 3) {
11648             /* BRI */
11649             pris[*span].dchannels[0] = 3 + offset;
11650          } else {
11651             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);
11652             *span = -1;
11653             return 0;
11654          }
11655          pris[*span].pri.span = *span + 1;
11656       }
11657    }
11658    return 0;
11659 }

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

Definition at line 16437 of file chan_dahdi.c.

References ast_copy_string(), ast_jb_read_conf(), ast_log(), build_channels(), dahdi_chan_conf::chan, global_jbconf, ast_variable::lineno, MAX_CHANLIST_LEN, ast_variable::name, ast_variable::next, dahdi_pvt::parkinglot, PROC_DAHDI_OPT_NOCHAN, and ast_variable::value.

Referenced by setup_dahdi_int().

16438 {
16439    struct dahdi_pvt *tmp;
16440    int y;
16441    int found_pseudo = 0;
16442    char dahdichan[MAX_CHANLIST_LEN] = {};
16443 
16444    for (; v; v = v->next) {
16445       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16446          continue;
16447 
16448       /* must have parkinglot in confp before build_channels is called */
16449       if (!strcasecmp(v->name, "parkinglot")) {
16450          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16451       }
16452 
16453       /* Create the interface list */
16454       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16455          if (options & PROC_DAHDI_OPT_NOCHAN) {
16456             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16457             continue;
16458          }
16459          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16460             if (confp->ignore_failed_channels) {
16461                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16462                continue;
16463             } else {
16464                return -1;
16465             }
16466          }
16467          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16468       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16469          confp->ignore_failed_channels = ast_true(v->value);
16470       } else if (!strcasecmp(v->name, "buffers")) {
16471          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16472             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16473             confp->chan.buf_no = numbufs;
16474             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16475          }
16476       } else if (!strcasecmp(v->name, "faxbuffers")) {
16477          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16478             confp->chan.usefaxbuffers = 1;
16479          }
16480       } else if (!strcasecmp(v->name, "dahdichan")) {
16481          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16482       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16483          usedistinctiveringdetection = ast_true(v->value);
16484       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16485          distinctiveringaftercid = ast_true(v->value);
16486       } else if (!strcasecmp(v->name, "dring1context")) {
16487          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16488       } else if (!strcasecmp(v->name, "dring2context")) {
16489          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16490       } else if (!strcasecmp(v->name, "dring3context")) {
16491          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16492       } else if (!strcasecmp(v->name, "dring1range")) {
16493          confp->chan.drings.ringnum[0].range = atoi(v->value);
16494       } else if (!strcasecmp(v->name, "dring2range")) {
16495          confp->chan.drings.ringnum[1].range = atoi(v->value);
16496       } else if (!strcasecmp(v->name, "dring3range")) {
16497          confp->chan.drings.ringnum[2].range = atoi(v->value);
16498       } else if (!strcasecmp(v->name, "dring1")) {
16499          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
16500       } else if (!strcasecmp(v->name, "dring2")) {
16501          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
16502       } else if (!strcasecmp(v->name, "dring3")) {
16503          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
16504       } else if (!strcasecmp(v->name, "usecallerid")) {
16505          confp->chan.use_callerid = ast_true(v->value);
16506       } else if (!strcasecmp(v->name, "cidsignalling")) {
16507          if (!strcasecmp(v->value, "bell"))
16508             confp->chan.cid_signalling = CID_SIG_BELL;
16509          else if (!strcasecmp(v->value, "v23"))
16510             confp->chan.cid_signalling = CID_SIG_V23;
16511          else if (!strcasecmp(v->value, "dtmf"))
16512             confp->chan.cid_signalling = CID_SIG_DTMF;
16513          else if (!strcasecmp(v->value, "smdi"))
16514             confp->chan.cid_signalling = CID_SIG_SMDI;
16515          else if (!strcasecmp(v->value, "v23_jp"))
16516             confp->chan.cid_signalling = CID_SIG_V23_JP;
16517          else if (ast_true(v->value))
16518             confp->chan.cid_signalling = CID_SIG_BELL;
16519       } else if (!strcasecmp(v->name, "cidstart")) {
16520          if (!strcasecmp(v->value, "ring"))
16521             confp->chan.cid_start = CID_START_RING;
16522          else if (!strcasecmp(v->value, "polarity_in"))
16523             confp->chan.cid_start = CID_START_POLARITY_IN;
16524          else if (!strcasecmp(v->value, "polarity"))
16525             confp->chan.cid_start = CID_START_POLARITY;
16526          else if (!strcasecmp(v->value, "dtmf"))
16527             confp->chan.cid_start = CID_START_DTMF_NOALERT;
16528          else if (ast_true(v->value))
16529             confp->chan.cid_start = CID_START_RING;
16530       } else if (!strcasecmp(v->name, "threewaycalling")) {
16531          confp->chan.threewaycalling = ast_true(v->value);
16532       } else if (!strcasecmp(v->name, "cancallforward")) {
16533          confp->chan.cancallforward = ast_true(v->value);
16534       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16535          if (ast_true(v->value))
16536             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16537          else
16538             confp->chan.dtmfrelax = 0;
16539       } else if (!strcasecmp(v->name, "mailbox")) {
16540          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16541       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16542          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16543             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16544          }
16545       } else if (!strcasecmp(v->name, "adsi")) {
16546          confp->chan.adsi = ast_true(v->value);
16547       } else if (!strcasecmp(v->name, "usesmdi")) {
16548          confp->chan.use_smdi = ast_true(v->value);
16549       } else if (!strcasecmp(v->name, "smdiport")) {
16550          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16551       } else if (!strcasecmp(v->name, "transfer")) {
16552          confp->chan.transfer = ast_true(v->value);
16553       } else if (!strcasecmp(v->name, "canpark")) {
16554          confp->chan.canpark = ast_true(v->value);
16555       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16556          confp->chan.echocanbridged = ast_true(v->value);
16557       } else if (!strcasecmp(v->name, "busydetect")) {
16558          confp->chan.busydetect = ast_true(v->value);
16559       } else if (!strcasecmp(v->name, "busycount")) {
16560          confp->chan.busycount = atoi(v->value);
16561       } else if (!strcasecmp(v->name, "silencethreshold")) {
16562          confp->chan.silencethreshold = atoi(v->value);
16563       } else if (!strcasecmp(v->name, "busycompare")) {
16564          confp->chan.busycompare = ast_true(v->value);
16565       } else if (!strcasecmp(v->name, "busypattern")) {
16566          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
16567             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16568          }
16569          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
16570          if (count == 1)
16571             confp->chan.busyquietlength = 0;
16572          else if (count < 1)
16573             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
16574       } else if (!strcasecmp(v->name, "busyfuzziness")) {
16575          confp->chan.busyfuzziness = atoi(v->value);
16576       } else if (!strcasecmp(v->name, "callprogress")) {
16577          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16578          if (ast_true(v->value))
16579             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16580       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16581          confp->chan.waitfordialtone = atoi(v->value);
16582       } else if (!strcasecmp(v->name, "faxdetect")) {
16583          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16584          if (!strcasecmp(v->value, "incoming")) {
16585             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16586          } else if (!strcasecmp(v->value, "outgoing")) {
16587             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16588          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16589             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16590       } else if (!strcasecmp(v->name, "echocancel")) {
16591          process_echocancel(confp, v->value, v->lineno);
16592       } else if (!strcasecmp(v->name, "echotraining")) {
16593          if (sscanf(v->value, "%30d", &y) == 1) {
16594             if ((y < 10) || (y > 4000)) {
16595                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16596             } else {
16597                confp->chan.echotraining = y;
16598             }
16599          } else if (ast_true(v->value)) {
16600             confp->chan.echotraining = 400;
16601          } else
16602             confp->chan.echotraining = 0;
16603       } else if (!strcasecmp(v->name, "hidecallerid")) {
16604          confp->chan.hidecallerid = ast_true(v->value);
16605       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16606          confp->chan.hidecalleridname = ast_true(v->value);
16607       } else if (!strcasecmp(v->name, "pulsedial")) {
16608          confp->chan.pulse = ast_true(v->value);
16609       } else if (!strcasecmp(v->name, "callreturn")) {
16610          confp->chan.callreturn = ast_true(v->value);
16611       } else if (!strcasecmp(v->name, "callwaiting")) {
16612          confp->chan.callwaiting = ast_true(v->value);
16613       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16614          confp->chan.callwaitingcallerid = ast_true(v->value);
16615       } else if (!strcasecmp(v->name, "context")) {
16616          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16617       } else if (!strcasecmp(v->name, "language")) {
16618          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16619       } else if (!strcasecmp(v->name, "progzone")) {
16620          ast_copy_string(progzone, v->value, sizeof(progzone));
16621       } else if (!strcasecmp(v->name, "mohinterpret")
16622          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16623          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16624       } else if (!strcasecmp(v->name, "mohsuggest")) {
16625          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16626       } else if (!strcasecmp(v->name, "parkinglot")) {
16627          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16628       } else if (!strcasecmp(v->name, "stripmsd")) {
16629          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16630          confp->chan.stripmsd = atoi(v->value);
16631       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16632          numbufs = atoi(v->value);
16633       } else if (!strcasecmp(v->name, "group")) {
16634          confp->chan.group = ast_get_group(v->value);
16635       } else if (!strcasecmp(v->name, "callgroup")) {
16636          if (!strcasecmp(v->value, "none"))
16637             confp->chan.callgroup = 0;
16638          else
16639             confp->chan.callgroup = ast_get_group(v->value);
16640       } else if (!strcasecmp(v->name, "pickupgroup")) {
16641          if (!strcasecmp(v->value, "none"))
16642             confp->chan.pickupgroup = 0;
16643          else
16644             confp->chan.pickupgroup = ast_get_group(v->value);
16645       } else if (!strcasecmp(v->name, "setvar")) {
16646          char *varname = ast_strdupa(v->value), *varval = NULL;
16647          struct ast_variable *tmpvar;
16648          if (varname && (varval = strchr(varname, '='))) {
16649             *varval++ = '\0';
16650             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16651                tmpvar->next = confp->chan.vars;
16652                confp->chan.vars = tmpvar;
16653             }
16654          }
16655       } else if (!strcasecmp(v->name, "immediate")) {
16656          confp->chan.immediate = ast_true(v->value);
16657       } else if (!strcasecmp(v->name, "transfertobusy")) {
16658          confp->chan.transfertobusy = ast_true(v->value);
16659       } else if (!strcasecmp(v->name, "mwimonitor")) {
16660          confp->chan.mwimonitor_neon = 0;
16661          confp->chan.mwimonitor_fsk = 0;
16662          confp->chan.mwimonitor_rpas = 0;
16663          if (strcasestr(v->value, "fsk")) {
16664             confp->chan.mwimonitor_fsk = 1;
16665          }
16666          if (strcasestr(v->value, "rpas")) {
16667             confp->chan.mwimonitor_rpas = 1;
16668          }
16669          if (strcasestr(v->value, "neon")) {
16670             confp->chan.mwimonitor_neon = 1;
16671          }
16672          /* If set to true or yes, assume that simple fsk is desired */
16673          if (ast_true(v->value)) {
16674             confp->chan.mwimonitor_fsk = 1;
16675          }
16676       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16677          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16678             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16679          }
16680       } else if (!strcasecmp(v->name, "rxgain")) {
16681          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16682             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16683          }
16684       } else if (!strcasecmp(v->name, "txgain")) {
16685          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16686             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16687          }
16688       } else if (!strcasecmp(v->name, "txdrc")) {
16689          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
16690             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
16691          }
16692       } else if (!strcasecmp(v->name, "rxdrc")) {
16693          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
16694             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
16695          }
16696       } else if (!strcasecmp(v->name, "tonezone")) {
16697          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16698             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16699          }
16700       } else if (!strcasecmp(v->name, "callerid")) {
16701          if (!strcasecmp(v->value, "asreceived")) {
16702             confp->chan.cid_num[0] = '\0';
16703             confp->chan.cid_name[0] = '\0';
16704          } else {
16705             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16706          }
16707       } else if (!strcasecmp(v->name, "fullname")) {
16708          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16709       } else if (!strcasecmp(v->name, "cid_number")) {
16710          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16711       } else if (!strcasecmp(v->name, "cid_tag")) {
16712          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
16713       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16714          confp->chan.dahditrcallerid = ast_true(v->value);
16715       } else if (!strcasecmp(v->name, "restrictcid")) {
16716          confp->chan.restrictcid = ast_true(v->value);
16717       } else if (!strcasecmp(v->name, "usecallingpres")) {
16718          confp->chan.use_callingpres = ast_true(v->value);
16719       } else if (!strcasecmp(v->name, "accountcode")) {
16720          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16721       } else if (!strcasecmp(v->name, "amaflags")) {
16722          y = ast_cdr_amaflags2int(v->value);
16723          if (y < 0)
16724             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16725          else
16726             confp->chan.amaflags = y;
16727       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16728          confp->chan.polarityonanswerdelay = atoi(v->value);
16729       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16730          confp->chan.answeronpolarityswitch = ast_true(v->value);
16731       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16732          confp->chan.hanguponpolarityswitch = ast_true(v->value);
16733       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16734          confp->chan.sendcalleridafter = atoi(v->value);
16735       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16736          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16737       } else if (ast_cc_is_config_param(v->name)) {
16738          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
16739       } else if (!strcasecmp(v->name, "mwisendtype")) {
16740 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
16741          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
16742             mwisend_rpas = 1;
16743          } else {
16744             mwisend_rpas = 0;
16745          }
16746 #else
16747          /* Default is fsk, to turn it off you must specify nofsk */
16748          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16749          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
16750             confp->chan.mwisend_fsk = 0;
16751          } else {             /* Default FSK */
16752             confp->chan.mwisend_fsk = 1;
16753          }
16754          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
16755             confp->chan.mwisend_rpas = 1;
16756          } else {
16757             confp->chan.mwisend_rpas = 0;
16758          }
16759          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
16760             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16761          }
16762          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
16763             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16764          }
16765          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
16766             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16767          }
16768 #endif
16769       } else if (reload != 1) {
16770           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16771             int orig_radio = confp->chan.radio;
16772             int orig_outsigmod = confp->chan.outsigmod;
16773             int orig_auto = confp->is_sig_auto;
16774 
16775             confp->chan.radio = 0;
16776             confp->chan.outsigmod = -1;
16777             confp->is_sig_auto = 0;
16778             if (!strcasecmp(v->value, "em")) {
16779                confp->chan.sig = SIG_EM;
16780             } else if (!strcasecmp(v->value, "em_e1")) {
16781                confp->chan.sig = SIG_EM_E1;
16782             } else if (!strcasecmp(v->value, "em_w")) {
16783                confp->chan.sig = SIG_EMWINK;
16784             } else if (!strcasecmp(v->value, "fxs_ls")) {
16785                confp->chan.sig = SIG_FXSLS;
16786             } else if (!strcasecmp(v->value, "fxs_gs")) {
16787                confp->chan.sig = SIG_FXSGS;
16788             } else if (!strcasecmp(v->value, "fxs_ks")) {
16789                confp->chan.sig = SIG_FXSKS;
16790             } else if (!strcasecmp(v->value, "fxo_ls")) {
16791                confp->chan.sig = SIG_FXOLS;
16792             } else if (!strcasecmp(v->value, "fxo_gs")) {
16793                confp->chan.sig = SIG_FXOGS;
16794             } else if (!strcasecmp(v->value, "fxo_ks")) {
16795                confp->chan.sig = SIG_FXOKS;
16796             } else if (!strcasecmp(v->value, "fxs_rx")) {
16797                confp->chan.sig = SIG_FXSKS;
16798                confp->chan.radio = 1;
16799             } else if (!strcasecmp(v->value, "fxo_rx")) {
16800                confp->chan.sig = SIG_FXOLS;
16801                confp->chan.radio = 1;
16802             } else if (!strcasecmp(v->value, "fxs_tx")) {
16803                confp->chan.sig = SIG_FXSLS;
16804                confp->chan.radio = 1;
16805             } else if (!strcasecmp(v->value, "fxo_tx")) {
16806                confp->chan.sig = SIG_FXOGS;
16807                confp->chan.radio = 1;
16808             } else if (!strcasecmp(v->value, "em_rx")) {
16809                confp->chan.sig = SIG_EM;
16810                confp->chan.radio = 1;
16811             } else if (!strcasecmp(v->value, "em_tx")) {
16812                confp->chan.sig = SIG_EM;
16813                confp->chan.radio = 1;
16814             } else if (!strcasecmp(v->value, "em_rxtx")) {
16815                confp->chan.sig = SIG_EM;
16816                confp->chan.radio = 2;
16817             } else if (!strcasecmp(v->value, "em_txrx")) {
16818                confp->chan.sig = SIG_EM;
16819                confp->chan.radio = 2;
16820             } else if (!strcasecmp(v->value, "sf")) {
16821                confp->chan.sig = SIG_SF;
16822             } else if (!strcasecmp(v->value, "sf_w")) {
16823                confp->chan.sig = SIG_SFWINK;
16824             } else if (!strcasecmp(v->value, "sf_featd")) {
16825                confp->chan.sig = SIG_FEATD;
16826             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16827                confp->chan.sig = SIG_FEATDMF;
16828             } else if (!strcasecmp(v->value, "sf_featb")) {
16829                confp->chan.sig = SIG_SF_FEATB;
16830             } else if (!strcasecmp(v->value, "sf")) {
16831                confp->chan.sig = SIG_SF;
16832             } else if (!strcasecmp(v->value, "sf_rx")) {
16833                confp->chan.sig = SIG_SF;
16834                confp->chan.radio = 1;
16835             } else if (!strcasecmp(v->value, "sf_tx")) {
16836                confp->chan.sig = SIG_SF;
16837                confp->chan.radio = 1;
16838             } else if (!strcasecmp(v->value, "sf_rxtx")) {
16839                confp->chan.sig = SIG_SF;
16840                confp->chan.radio = 2;
16841             } else if (!strcasecmp(v->value, "sf_txrx")) {
16842                confp->chan.sig = SIG_SF;
16843                confp->chan.radio = 2;
16844             } else if (!strcasecmp(v->value, "featd")) {
16845                confp->chan.sig = SIG_FEATD;
16846             } else if (!strcasecmp(v->value, "featdmf")) {
16847                confp->chan.sig = SIG_FEATDMF;
16848             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16849                confp->chan.sig = SIG_FEATDMF_TA;
16850             } else if (!strcasecmp(v->value, "e911")) {
16851                confp->chan.sig = SIG_E911;
16852             } else if (!strcasecmp(v->value, "fgccama")) {
16853                confp->chan.sig = SIG_FGC_CAMA;
16854             } else if (!strcasecmp(v->value, "fgccamamf")) {
16855                confp->chan.sig = SIG_FGC_CAMAMF;
16856             } else if (!strcasecmp(v->value, "featb")) {
16857                confp->chan.sig = SIG_FEATB;
16858 #ifdef HAVE_PRI
16859             } else if (!strcasecmp(v->value, "pri_net")) {
16860                confp->chan.sig = SIG_PRI;
16861                confp->pri.pri.nodetype = PRI_NETWORK;
16862             } else if (!strcasecmp(v->value, "pri_cpe")) {
16863                confp->chan.sig = SIG_PRI;
16864                confp->pri.pri.nodetype = PRI_CPE;
16865             } else if (!strcasecmp(v->value, "bri_cpe")) {
16866                confp->chan.sig = SIG_BRI;
16867                confp->pri.pri.nodetype = PRI_CPE;
16868             } else if (!strcasecmp(v->value, "bri_net")) {
16869                confp->chan.sig = SIG_BRI;
16870                confp->pri.pri.nodetype = PRI_NETWORK;
16871             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16872                confp->chan.sig = SIG_BRI_PTMP;
16873                confp->pri.pri.nodetype = PRI_CPE;
16874             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16875 #if defined(HAVE_PRI_CALL_HOLD)
16876                confp->chan.sig = SIG_BRI_PTMP;
16877                confp->pri.pri.nodetype = PRI_NETWORK;
16878 #else
16879                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
16880 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
16881 #endif
16882 #if defined(HAVE_SS7)
16883             } else if (!strcasecmp(v->value, "ss7")) {
16884                confp->chan.sig = SIG_SS7;
16885 #endif   /* defined(HAVE_SS7) */
16886 #ifdef HAVE_OPENR2
16887             } else if (!strcasecmp(v->value, "mfcr2")) {
16888                confp->chan.sig = SIG_MFCR2;
16889 #endif
16890             } else if (!strcasecmp(v->value, "auto")) {
16891                confp->is_sig_auto = 1;
16892             } else {
16893                confp->chan.outsigmod = orig_outsigmod;
16894                confp->chan.radio = orig_radio;
16895                confp->is_sig_auto = orig_auto;
16896                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16897             }
16898           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16899             if (!strcasecmp(v->value, "em")) {
16900                confp->chan.outsigmod = SIG_EM;
16901             } else if (!strcasecmp(v->value, "em_e1")) {
16902                confp->chan.outsigmod = SIG_EM_E1;
16903             } else if (!strcasecmp(v->value, "em_w")) {
16904                confp->chan.outsigmod = SIG_EMWINK;
16905             } else if (!strcasecmp(v->value, "sf")) {
16906                confp->chan.outsigmod = SIG_SF;
16907             } else if (!strcasecmp(v->value, "sf_w")) {
16908                confp->chan.outsigmod = SIG_SFWINK;
16909             } else if (!strcasecmp(v->value, "sf_featd")) {
16910                confp->chan.outsigmod = SIG_FEATD;
16911             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16912                confp->chan.outsigmod = SIG_FEATDMF;
16913             } else if (!strcasecmp(v->value, "sf_featb")) {
16914                confp->chan.outsigmod = SIG_SF_FEATB;
16915             } else if (!strcasecmp(v->value, "sf")) {
16916                confp->chan.outsigmod = SIG_SF;
16917             } else if (!strcasecmp(v->value, "featd")) {
16918                confp->chan.outsigmod = SIG_FEATD;
16919             } else if (!strcasecmp(v->value, "featdmf")) {
16920                confp->chan.outsigmod = SIG_FEATDMF;
16921             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16922                confp->chan.outsigmod = SIG_FEATDMF_TA;
16923             } else if (!strcasecmp(v->value, "e911")) {
16924                confp->chan.outsigmod = SIG_E911;
16925             } else if (!strcasecmp(v->value, "fgccama")) {
16926                confp->chan.outsigmod = SIG_FGC_CAMA;
16927             } else if (!strcasecmp(v->value, "fgccamamf")) {
16928                confp->chan.outsigmod = SIG_FGC_CAMAMF;
16929             } else if (!strcasecmp(v->value, "featb")) {
16930                confp->chan.outsigmod = SIG_FEATB;
16931             } else {
16932                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16933             }
16934 #ifdef HAVE_PRI
16935          } else if (!strcasecmp(v->name, "pridialplan")) {
16936             if (!strcasecmp(v->value, "national")) {
16937                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
16938             } else if (!strcasecmp(v->value, "unknown")) {
16939                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
16940             } else if (!strcasecmp(v->value, "private")) {
16941                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
16942             } else if (!strcasecmp(v->value, "international")) {
16943                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16944             } else if (!strcasecmp(v->value, "local")) {
16945                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
16946             } else if (!strcasecmp(v->value, "dynamic")) {
16947                confp->pri.pri.dialplan = -1;
16948             } else if (!strcasecmp(v->value, "redundant")) {
16949                confp->pri.pri.dialplan = -2;
16950             } else {
16951                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16952             }
16953          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16954             if (!strcasecmp(v->value, "national")) {
16955                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16956             } else if (!strcasecmp(v->value, "unknown")) {
16957                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
16958             } else if (!strcasecmp(v->value, "private")) {
16959                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
16960             } else if (!strcasecmp(v->value, "international")) {
16961                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16962             } else if (!strcasecmp(v->value, "local")) {
16963                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
16964             } else if (!strcasecmp(v->value, "dynamic")) {
16965                confp->pri.pri.localdialplan = -1;
16966             } else if (!strcasecmp(v->value, "redundant")) {
16967                confp->pri.pri.localdialplan = -2;
16968             } else {
16969                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16970             }
16971          } else if (!strcasecmp(v->name, "switchtype")) {
16972             if (!strcasecmp(v->value, "national"))
16973                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
16974             else if (!strcasecmp(v->value, "ni1"))
16975                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
16976             else if (!strcasecmp(v->value, "dms100"))
16977                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
16978             else if (!strcasecmp(v->value, "4ess"))
16979                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
16980             else if (!strcasecmp(v->value, "5ess"))
16981                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
16982             else if (!strcasecmp(v->value, "euroisdn"))
16983                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16984             else if (!strcasecmp(v->value, "qsig"))
16985                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
16986             else {
16987                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16988                return -1;
16989             }
16990          } else if (!strcasecmp(v->name, "msn")) {
16991             ast_copy_string(confp->pri.pri.msn_list, v->value,
16992                sizeof(confp->pri.pri.msn_list));
16993          } else if (!strcasecmp(v->name, "nsf")) {
16994             if (!strcasecmp(v->value, "sdn"))
16995                confp->pri.pri.nsf = PRI_NSF_SDN;
16996             else if (!strcasecmp(v->value, "megacom"))
16997                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
16998             else if (!strcasecmp(v->value, "tollfreemegacom"))
16999                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17000             else if (!strcasecmp(v->value, "accunet"))
17001                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17002             else if (!strcasecmp(v->value, "none"))
17003                confp->pri.pri.nsf = PRI_NSF_NONE;
17004             else {
17005                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17006                confp->pri.pri.nsf = PRI_NSF_NONE;
17007             }
17008          } else if (!strcasecmp(v->name, "priindication")) {
17009             if (!strcasecmp(v->value, "outofband"))
17010                confp->chan.priindication_oob = 1;
17011             else if (!strcasecmp(v->value, "inband"))
17012                confp->chan.priindication_oob = 0;
17013             else
17014                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17015                   v->value, v->lineno);
17016          } else if (!strcasecmp(v->name, "priexclusive")) {
17017             confp->chan.priexclusive = ast_true(v->value);
17018          } else if (!strcasecmp(v->name, "internationalprefix")) {
17019             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17020          } else if (!strcasecmp(v->name, "nationalprefix")) {
17021             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17022          } else if (!strcasecmp(v->name, "localprefix")) {
17023             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17024          } else if (!strcasecmp(v->name, "privateprefix")) {
17025             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17026          } else if (!strcasecmp(v->name, "unknownprefix")) {
17027             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17028          } else if (!strcasecmp(v->name, "resetinterval")) {
17029             if (!strcasecmp(v->value, "never"))
17030                confp->pri.pri.resetinterval = -1;
17031             else if (atoi(v->value) >= 60)
17032                confp->pri.pri.resetinterval = atoi(v->value);
17033             else
17034                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17035                   v->value, v->lineno);
17036          } else if (!strcasecmp(v->name, "minunused")) {
17037             confp->pri.pri.minunused = atoi(v->value);
17038          } else if (!strcasecmp(v->name, "minidle")) {
17039             confp->pri.pri.minidle = atoi(v->value);
17040          } else if (!strcasecmp(v->name, "idleext")) {
17041             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17042          } else if (!strcasecmp(v->name, "idledial")) {
17043             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17044          } else if (!strcasecmp(v->name, "overlapdial")) {
17045             if (ast_true(v->value)) {
17046                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17047             } else if (!strcasecmp(v->value, "incoming")) {
17048                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17049             } else if (!strcasecmp(v->value, "outgoing")) {
17050                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17051             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17052                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17053             } else {
17054                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17055             }
17056 #ifdef HAVE_PRI_PROG_W_CAUSE
17057          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17058             if (!strcasecmp(v->value, "logical")) {
17059                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17060             } else if (!strcasecmp(v->value, "physical")) {
17061                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17062             } else {
17063                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17064             }
17065 #endif
17066          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17067             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17068 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17069          } else if (!strcasecmp(v->name, "service_message_support")) {
17070             /* assuming switchtype for this channel group has been configured already */
17071             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17072                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17073                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17074                confp->pri.pri.enable_service_message_support = 1;
17075             } else {
17076                confp->pri.pri.enable_service_message_support = 0;
17077             }
17078 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17079 #ifdef HAVE_PRI_INBANDDISCONNECT
17080          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17081             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17082 #endif
17083          } else if (!strcasecmp(v->name, "pritimer")) {
17084 #ifdef PRI_GETSET_TIMERS
17085             char tmp[20];
17086             char *timerc;
17087             char *c;
17088             int timer;
17089             int timeridx;
17090 
17091             ast_copy_string(tmp, v->value, sizeof(tmp));
17092             c = tmp;
17093             timerc = strsep(&c, ",");
17094             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17095                timeridx = pri_timer2idx(timerc);
17096                timer = atoi(c);
17097                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17098                   ast_log(LOG_WARNING,
17099                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17100                      v->lineno);
17101                } else if (!timer) {
17102                   ast_log(LOG_WARNING,
17103                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17104                      c, timerc, v->lineno);
17105                } else {
17106                   confp->pri.pri.pritimers[timeridx] = timer;
17107                }
17108             } else {
17109                ast_log(LOG_WARNING,
17110                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17111                   v->value, v->lineno);
17112             }
17113 #endif /* PRI_GETSET_TIMERS */
17114          } else if (!strcasecmp(v->name, "facilityenable")) {
17115             confp->pri.pri.facilityenable = ast_true(v->value);
17116 #if defined(HAVE_PRI_AOC_EVENTS)
17117          } else if (!strcasecmp(v->name, "aoc_enable")) {
17118             confp->pri.pri.aoc_passthrough_flag = 0;
17119             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17120                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17121             }
17122             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17123                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17124             }
17125             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17126                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17127             }
17128          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17129             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17130 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17131 #if defined(HAVE_PRI_CALL_HOLD)
17132          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17133             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17134 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17135 #if defined(HAVE_PRI_CCSS)
17136          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17137             if (!strcasecmp(v->value, "global")) {
17138                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17139             } else if (!strcasecmp(v->value, "specific")) {
17140                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17141             } else {
17142                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17143             }
17144          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17145             if (!strcasecmp(v->value, "release")) {
17146                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17147             } else if (!strcasecmp(v->value, "retain")) {
17148                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17149             } else if (!strcasecmp(v->value, "do_not_care")) {
17150                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17151             } else {
17152                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17153             }
17154          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17155             if (!strcasecmp(v->value, "release")) {
17156                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17157             } else if (!strcasecmp(v->value, "retain")) {
17158                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17159             } else {
17160                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17161             }
17162 #endif   /* defined(HAVE_PRI_CCSS) */
17163 #if defined(HAVE_PRI_CALL_WAITING)
17164          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17165             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17166             if (confp->pri.pri.max_call_waiting_calls < 0) {
17167                /* Negative values are not allowed. */
17168                confp->pri.pri.max_call_waiting_calls = 0;
17169             }
17170          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17171             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17172 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17173 #if defined(HAVE_PRI_MWI)
17174          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17175             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17176                sizeof(confp->pri.pri.mwi_mailboxes));
17177 #endif   /* defined(HAVE_PRI_MWI) */
17178          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17179             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17180 #endif /* HAVE_PRI */
17181 #if defined(HAVE_SS7)
17182          } else if (!strcasecmp(v->name, "ss7type")) {
17183             if (!strcasecmp(v->value, "itu")) {
17184                cur_ss7type = SS7_ITU;
17185             } else if (!strcasecmp(v->value, "ansi")) {
17186                cur_ss7type = SS7_ANSI;
17187             } else
17188                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17189          } else if (!strcasecmp(v->name, "linkset")) {
17190             cur_linkset = atoi(v->value);
17191          } else if (!strcasecmp(v->name, "pointcode")) {
17192             cur_pointcode = parse_pointcode(v->value);
17193          } else if (!strcasecmp(v->name, "adjpointcode")) {
17194             cur_adjpointcode = parse_pointcode(v->value);
17195          } else if (!strcasecmp(v->name, "defaultdpc")) {
17196             cur_defaultdpc = parse_pointcode(v->value);
17197          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17198             cur_cicbeginswith = atoi(v->value);
17199          } else if (!strcasecmp(v->name, "networkindicator")) {
17200             if (!strcasecmp(v->value, "national"))
17201                cur_networkindicator = SS7_NI_NAT;
17202             else if (!strcasecmp(v->value, "national_spare"))
17203                cur_networkindicator = SS7_NI_NAT_SPARE;
17204             else if (!strcasecmp(v->value, "international"))
17205                cur_networkindicator = SS7_NI_INT;
17206             else if (!strcasecmp(v->value, "international_spare"))
17207                cur_networkindicator = SS7_NI_INT_SPARE;
17208             else
17209                cur_networkindicator = -1;
17210          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17211             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17212          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17213             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17214          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17215             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17216          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17217             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17218          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17219             if (!strcasecmp(v->value, "national")) {
17220                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17221             } else if (!strcasecmp(v->value, "international")) {
17222                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17223             } else if (!strcasecmp(v->value, "subscriber")) {
17224                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17225             } else if (!strcasecmp(v->value, "unknown")) {
17226                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17227             } else if (!strcasecmp(v->value, "dynamic")) {
17228                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17229             } else {
17230                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17231             }
17232          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17233             if (!strcasecmp(v->value, "national")) {
17234                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17235             } else if (!strcasecmp(v->value, "international")) {
17236                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17237             } else if (!strcasecmp(v->value, "subscriber")) {
17238                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17239             } else if (!strcasecmp(v->value, "unknown")) {
17240                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17241             } else if (!strcasecmp(v->value, "dynamic")) {
17242                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17243             } else {
17244                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17245             }
17246          } else if (!strcasecmp(v->name, "sigchan")) {
17247             int sigchan, res;
17248             sigchan = atoi(v->value);
17249             res = linkset_addsigchan(sigchan);
17250             if (res < 0)
17251                return -1;
17252 
17253          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17254             struct dahdi_ss7 *link;
17255             link = ss7_resolve_linkset(cur_linkset);
17256             if (!link) {
17257                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17258                return -1;
17259             }
17260             if (ast_true(v->value))
17261                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17262 #endif   /* defined(HAVE_SS7) */
17263 #ifdef HAVE_OPENR2
17264          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17265             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17266             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", confp->mfcr2.r2proto_file);
17267          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17268             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17269          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17270             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17271             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17272                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17273                confp->mfcr2.variant = OR2_VAR_ITU;
17274             }
17275          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17276             confp->mfcr2.mfback_timeout = atoi(v->value);
17277             if (!confp->mfcr2.mfback_timeout) {
17278                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17279                confp->mfcr2.mfback_timeout = -1;
17280             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17281                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17282             }
17283          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17284             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17285             if (confp->mfcr2.metering_pulse_timeout > 500) {
17286                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17287             }
17288          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17289             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17290          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17291             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17292          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17293             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17294          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17295             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17296          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17297             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17298          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17299             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17300          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17301             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17302 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17303          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17304             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17305 #endif
17306          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17307             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17308          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17309             confp->mfcr2.max_ani = atoi(v->value);
17310             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17311                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17312             }
17313          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17314             confp->mfcr2.max_dnis = atoi(v->value);
17315             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17316                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17317             }
17318          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17319             confp->mfcr2.category = openr2_proto_get_category(v->value);
17320             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17321                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17322                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17323                      v->value, v->lineno);
17324             }
17325          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17326             openr2_log_level_t tmplevel;
17327             char *clevel;
17328             char *logval = ast_strdupa(v->value);
17329             while (logval) {
17330                clevel = strsep(&logval,",");
17331                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17332                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17333                   continue;
17334                }
17335                confp->mfcr2.loglevel |= tmplevel;
17336             }
17337 #endif /* HAVE_OPENR2 */
17338          } else if (!strcasecmp(v->name, "cadence")) {
17339             /* setup to scan our argument */
17340             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17341             int i;
17342             struct dahdi_ring_cadence new_cadence;
17343             int cid_location = -1;
17344             int firstcadencepos = 0;
17345             char original_args[80];
17346             int cadence_is_ok = 1;
17347 
17348             ast_copy_string(original_args, v->value, sizeof(original_args));
17349             /* 16 cadences allowed (8 pairs) */
17350             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]);
17351 
17352             /* Cadence must be even (on/off) */
17353             if (element_count % 2 == 1) {
17354                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17355                cadence_is_ok = 0;
17356             }
17357 
17358             /* Ring cadences cannot be negative */
17359             for (i = 0; i < element_count; i++) {
17360                if (c[i] == 0) {
17361                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17362                   cadence_is_ok = 0;
17363                   break;
17364                } else if (c[i] < 0) {
17365                   if (i % 2 == 1) {
17366                      /* Silence duration, negative possibly okay */
17367                      if (cid_location == -1) {
17368                         cid_location = i;
17369                         c[i] *= -1;
17370                      } else {
17371                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17372                         cadence_is_ok = 0;
17373                         break;
17374                      }
17375                   } else {
17376                      if (firstcadencepos == 0) {
17377                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17378                                  /* duration will be passed negative to the DAHDI driver */
17379                      } else {
17380                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17381                         cadence_is_ok = 0;
17382                         break;
17383                      }
17384                   }
17385                }
17386             }
17387 
17388             /* Substitute our scanned cadence */
17389             for (i = 0; i < 16; i++) {
17390                new_cadence.ringcadence[i] = c[i];
17391             }
17392 
17393             if (cadence_is_ok) {
17394                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17395                if (element_count < 2) {
17396                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17397                } else {
17398                   if (cid_location == -1) {
17399                      /* user didn't say; default to first pause */
17400                      cid_location = 1;
17401                   } else {
17402                      /* convert element_index to cidrings value */
17403                      cid_location = (cid_location + 1) / 2;
17404                   }
17405                   /* ---we like their cadence; try to install it--- */
17406                   if (!user_has_defined_cadences++)
17407                      /* this is the first user-defined cadence; clear the default user cadences */
17408                      num_cadence = 0;
17409                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17410                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17411                   else {
17412                      cadences[num_cadence] = new_cadence;
17413                      cidrings[num_cadence++] = cid_location;
17414                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17415                   }
17416                }
17417             }
17418          } else if (!strcasecmp(v->name, "ringtimeout")) {
17419             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17420          } else if (!strcasecmp(v->name, "prewink")) {
17421             confp->timing.prewinktime = atoi(v->value);
17422          } else if (!strcasecmp(v->name, "preflash")) {
17423             confp->timing.preflashtime = atoi(v->value);
17424          } else if (!strcasecmp(v->name, "wink")) {
17425             confp->timing.winktime = atoi(v->value);
17426          } else if (!strcasecmp(v->name, "flash")) {
17427             confp->timing.flashtime = atoi(v->value);
17428          } else if (!strcasecmp(v->name, "start")) {
17429             confp->timing.starttime = atoi(v->value);
17430          } else if (!strcasecmp(v->name, "rxwink")) {
17431             confp->timing.rxwinktime = atoi(v->value);
17432          } else if (!strcasecmp(v->name, "rxflash")) {
17433             confp->timing.rxflashtime = atoi(v->value);
17434          } else if (!strcasecmp(v->name, "debounce")) {
17435             confp->timing.debouncetime = atoi(v->value);
17436          } else if (!strcasecmp(v->name, "toneduration")) {
17437             int toneduration;
17438             int ctlfd;
17439             int res;
17440             struct dahdi_dialparams dps;
17441 
17442             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17443             if (ctlfd == -1) {
17444                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17445                return -1;
17446             }
17447 
17448             toneduration = atoi(v->value);
17449             if (toneduration > -1) {
17450                memset(&dps, 0, sizeof(dps));
17451 
17452                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17453                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17454                if (res < 0) {
17455                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17456                   close(ctlfd);
17457                   return -1;
17458                }
17459             }
17460             close(ctlfd);
17461          } else if (!strcasecmp(v->name, "defaultcic")) {
17462             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17463          } else if (!strcasecmp(v->name, "defaultozz")) {
17464             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17465          } else if (!strcasecmp(v->name, "mwilevel")) {
17466             mwilevel = atoi(v->value);
17467          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17468             dtmfcid_level = atoi(v->value);
17469          } else if (!strcasecmp(v->name, "reportalarms")) {
17470             if (!strcasecmp(v->value, "all"))
17471                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17472             if (!strcasecmp(v->value, "none"))
17473                report_alarms = 0;
17474             else if (!strcasecmp(v->value, "channels"))
17475                report_alarms = REPORT_CHANNEL_ALARMS;
17476             else if (!strcasecmp(v->value, "spans"))
17477                report_alarms = REPORT_SPAN_ALARMS;
17478           }
17479       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17480          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17481    }
17482    if (dahdichan[0]) {
17483       /* The user has set 'dahdichan' */
17484       /*< \todo pass proper line number instead of 0 */
17485       if (build_channels(confp, dahdichan, reload, 0, &found_pseudo)) {
17486          return -1;
17487       }
17488    }
17489 
17490    /* mark the first channels of each DAHDI span to watch for their span alarms */
17491    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17492       if (!tmp->destroy && tmp->span != y) {
17493          tmp->manages_span_alarms = 1;
17494          y = tmp->span; 
17495       } else {
17496          tmp->manages_span_alarms = 0;
17497       }
17498    }
17499 
17500    /*< \todo why check for the pseudo in the per-channel section.
17501     * Any actual use for manual setup of the pseudo channel? */
17502    if (!found_pseudo && reload != 1) {
17503       /* use the default configuration for a channel, so
17504          that any settings from real configured channels
17505          don't "leak" into the pseudo channel config
17506       */
17507       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17508 
17509       if (conf.chan.cc_params) {
17510          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17511       } else {
17512          tmp = NULL;
17513       }
17514       if (tmp) {
17515          ast_verb(3, "Automatically generated pseudo channel\n");
17516       } else {
17517          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17518       }
17519       ast_cc_config_params_destroy(conf.chan.cc_params);
17520    }
17521    return 0;
17522 }

static void process_echocancel ( struct dahdi_chan_conf confp,
const char *  data,
unsigned int  line 
) [static]

Definition at line 16381 of file chan_dahdi.c.

References ARRAY_LEN, ast_app_separate_args, ast_log(), ast_strdupa, ast_strlen_zero(), ast_true(), dahdi_chan_conf::chan, dahdi_pvt::echocancel, dahdi_pvt::head, name, dahdi_pvt::params, parse(), and value.

16382 {
16383    char *parse = ast_strdupa(data);
16384    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16385    unsigned int param_count;
16386    unsigned int x;
16387 
16388    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16389       return;
16390 
16391    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16392 
16393    /* first parameter is tap length, process it here */
16394 
16395    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16396 
16397    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16398       confp->chan.echocancel.head.tap_length = x;
16399    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16400       confp->chan.echocancel.head.tap_length = 128;
16401 
16402    /* now process any remaining parameters */
16403 
16404    for (x = 1; x < param_count; x++) {
16405       struct {
16406          char *name;
16407          char *value;
16408       } param;
16409 
16410       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16411          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16412          continue;
16413       }
16414 
16415       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16416          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16417          continue;
16418       }
16419 
16420       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16421 
16422       if (param.value) {
16423          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16424             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16425             continue;
16426          }
16427       }
16428       confp->chan.echocancel.head.param_count++;
16429    }
16430 }

static int reload ( void   )  [static]

Definition at line 18151 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

18152 {
18153    int res = 0;
18154 
18155    res = setup_dahdi(1);
18156    if (res) {
18157       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18158       return -1;
18159    }
18160    return 0;
18161 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 4678 of file chan_dahdi.c.

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

Referenced by dahdi_hangup(), and my_all_subchannels_hungup().

04679 {
04680    p->confno = -1;
04681    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04682    if (p->subs[SUB_REAL].dfd > -1) {
04683       struct dahdi_confinfo zi;
04684 
04685       memset(&zi, 0, sizeof(zi));
04686       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04687          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04688    }
04689    return 0;
04690 }

static int restart_monitor ( void   )  [static]

Definition at line 11590 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, monitor_thread, and monlock.

Referenced by dahdi_hangup(), dahdi_request(), h323_reload(), load_module(), mgcp_reload(), mgcp_request(), my_all_subchannels_hungup(), oh323_request(), phone_hangup(), phone_request(), sip_reload(), sip_request_call(), skinny_request(), unistim_reload(), and unistim_request().

11591 {
11592    /* If we're supposed to be stopped -- stay stopped */
11593    if (monitor_thread == AST_PTHREADT_STOP)
11594       return 0;
11595    ast_mutex_lock(&monlock);
11596    if (monitor_thread == pthread_self()) {
11597       ast_mutex_unlock(&monlock);
11598       ast_log(LOG_WARNING, "Cannot kill myself\n");
11599       return -1;
11600    }
11601    if (monitor_thread != AST_PTHREADT_NULL) {
11602       /* Wake up the thread */
11603       pthread_kill(monitor_thread, SIGURG);
11604    } else {
11605       /* Start a new monitor */
11606       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11607          ast_mutex_unlock(&monlock);
11608          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11609          return -1;
11610       }
11611    }
11612    ast_mutex_unlock(&monlock);
11613    return 0;
11614 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 5091 of file chan_dahdi.c.

References ast_debug, ast_log(), errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.

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

05092 {
05093    int res;
05094    if (p->saveconf.confmode) {
05095       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05096       p->saveconf.confmode = 0;
05097       if (res) {
05098          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05099          return -1;
05100       }
05101       ast_debug(1, "Restored conferencing\n");
05102    }
05103    return 0;
05104 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 4998 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), dahdi_hangup(), and mwi_thread().

04999 {
05000    int res;
05001 
05002    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05003    if (res) {
05004       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05005       return -1;
05006    }
05007 
05008    return 0;
05009 }

static int revert_fax_buffers ( struct dahdi_pvt p,
struct ast_channel ast 
) [static]

Definition at line 5981 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, errno, LOG_WARNING, ast_channel::name, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_hangup().

05982 {
05983    if (p->bufferoverrideinuse) {
05984       /* faxbuffers are in use, revert them */
05985       struct dahdi_bufferinfo bi = {
05986          .txbufpolicy = p->buf_policy,
05987          .rxbufpolicy = p->buf_policy,
05988          .bufsize = p->bufsize,
05989          .numbufs = p->buf_no
05990       };
05991       int bpres;
05992 
05993       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05994          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
05995       }
05996       p->bufferoverrideinuse = 0;
05997       return bpres;
05998    }
05999 
06000    return -1;
06001 }

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 5065 of file chan_dahdi.c.

References ast_debug, ast_log(), errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_callwait(), dahdi_handle_event(), and my_callwait().

05066 {
05067    struct dahdi_confinfo c;
05068    int res;
05069    if (p->saveconf.confmode) {
05070       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05071       return -1;
05072    }
05073    p->saveconf.chan = 0;
05074    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05075    if (res) {
05076       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05077       p->saveconf.confmode = 0;
05078       return -1;
05079    }
05080    memset(&c, 0, sizeof(c));
05081    c.confmode = DAHDI_CONF_NORMAL;
05082    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05083    if (res) {
05084       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05085       return -1;
05086    }
05087    ast_debug(1, "Disabled conferencing\n");
05088    return 0;
05089 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 5149 of file chan_dahdi.c.

References ast_debug, ast_free, 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(), errno, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_callwait(), dahdi_read(), my_callwait(), my_send_callerid(), and send_cwcidspill().

05150 {
05151    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05152    int res;
05153    /* Take out of linear mode if necessary */
05154    if (p->subs[SUB_REAL].linear) {
05155       p->subs[SUB_REAL].linear = 0;
05156       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05157    }
05158    while (p->cidpos < p->cidlen) {
05159       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05160       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05161       if (res < 0) {
05162          if (errno == EAGAIN)
05163             return 0;
05164          else {
05165             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05166             return -1;
05167          }
05168       }
05169       if (!res)
05170          return 0;
05171       p->cidpos += res;
05172    }
05173    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05174    ast_free(p->cidspill);
05175    p->cidspill = NULL;
05176    if (p->callwaitcas) {
05177       /* Wait for CID/CW to expire */
05178       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05179       p->cid_suppress_expire = p->cidcwexpire;
05180    } else
05181       restore_conference(p);
05182    return 0;
05183 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

Definition at line 5106 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verb, 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, READ_SIZE, and send_callerid().

Referenced by dahdi_handle_dtmf().

05107 {
05108    p->callwaitcas = 0;
05109    p->cidcwexpire = 0;
05110    p->cid_suppress_expire = 0;
05111    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05112       return -1;
05113    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05114    /* Make sure we account for the end */
05115    p->cidlen += READ_SIZE * 4;
05116    p->cidpos = 0;
05117    send_callerid(p);
05118    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05119    return 0;
05120 }

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

Definition at line 4979 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

Referenced by bump_gains(), dahdi_call(), my_pri_open_media(), and restore_gains().

04980 {
04981    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
04982 }

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

Definition at line 4962 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().

04963 {
04964    struct dahdi_gains g;
04965    int res;
04966 
04967    memset(&g, 0, sizeof(g));
04968    res = ioctl(fd, DAHDI_GETGAINS, &g);
04969    if (res) {
04970       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04971       return res;
04972    }
04973 
04974    fill_rxgain(&g, gain, drc, law);
04975 
04976    return ioctl(fd, DAHDI_SETGAINS, &g);
04977 }

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

Definition at line 4945 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().

04946 {
04947    struct dahdi_gains g;
04948    int res;
04949 
04950    memset(&g, 0, sizeof(g));
04951    res = ioctl(fd, DAHDI_GETGAINS, &g);
04952    if (res) {
04953       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04954       return res;
04955    }
04956 
04957    fill_txgain(&g, gain, drc, law);
04958 
04959    return ioctl(fd, DAHDI_SETGAINS, &g);
04960 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 17796 of file chan_dahdi.c.

References ast_cc_config_params_destroy(), dahdi_pvt::cc_params, dahdi_chan_conf::chan, dahdi_chan_conf_default(), and setup_dahdi_int().

Referenced by load_module(), and reload().

17797 {
17798    int res;
17799    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17800    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17801 
17802    if (base_conf.chan.cc_params && conf.chan.cc_params) {
17803       res = setup_dahdi_int(reload, &base_conf, &conf);
17804    } else {
17805       res = -1;
17806    }
17807    ast_cc_config_params_destroy(base_conf.chan.cc_params);
17808    ast_cc_config_params_destroy(conf.chan.cc_params);
17809 
17810    return res;
17811 }

static int setup_dahdi_int ( int  reload,
struct dahdi_chan_conf base_conf,
struct dahdi_chan_conf conf 
) [static]

Definition at line 17555 of file chan_dahdi.c.

References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, deep_copy_dahdi_chan_conf(), default_jbconf, global_jbconf, ast_variable::lineno, LOG_NOTICE, mwimonitornotify, ast_variable::name, ast_variable::next, prepare_pri(), pri_create_spanmap(), pri_create_trunkgroup(), PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_start_pri(), and ast_variable::value.

Referenced by setup_dahdi().

17556 {
17557    struct ast_config *cfg;
17558    struct ast_config *ucfg;
17559    struct ast_variable *v;
17560    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17561    const char *cat;
17562    int res;
17563 
17564 #ifdef HAVE_PRI
17565    char *c;
17566    int spanno;
17567    int i;
17568    int logicalspan;
17569    int trunkgroup;
17570    int dchannels[SIG_PRI_NUM_DCHANS];
17571 #endif
17572 
17573    cfg = ast_config_load(config, config_flags);
17574 
17575    /* Error if we have no config file */
17576    if (!cfg) {
17577       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17578       return 0;
17579    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17580       ucfg = ast_config_load("users.conf", config_flags);
17581       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17582          return 0;
17583       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17584          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17585          return 0;
17586       }
17587       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17588       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17589          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17590          ast_config_destroy(ucfg);
17591          return 0;
17592       }
17593    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17594       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17595       return 0;
17596    } else {
17597       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17598       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17599          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17600          ast_config_destroy(cfg);
17601          return 0;
17602       }
17603    }
17604 
17605    /* It's a little silly to lock it, but we might as well just to be sure */
17606    ast_mutex_lock(&iflock);
17607 #ifdef HAVE_PRI
17608    if (reload != 1) {
17609       /* Process trunkgroups first */
17610       v = ast_variable_browse(cfg, "trunkgroups");
17611       while (v) {
17612          if (!strcasecmp(v->name, "trunkgroup")) {
17613             trunkgroup = atoi(v->value);
17614             if (trunkgroup > 0) {
17615                if ((c = strchr(v->value, ','))) {
17616                   i = 0;
17617                   memset(dchannels, 0, sizeof(dchannels));
17618                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
17619                      dchannels[i] = atoi(c + 1);
17620                      if (dchannels[i] < 0) {
17621                         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);
17622                      } else
17623                         i++;
17624                      c = strchr(c + 1, ',');
17625                   }
17626                   if (i) {
17627                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17628                         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);
17629                   } else
17630                         ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
17631                   } else
17632                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17633                } else
17634                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17635             } else
17636                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17637          } else if (!strcasecmp(v->name, "spanmap")) {
17638             spanno = atoi(v->value);
17639             if (spanno > 0) {
17640                if ((c = strchr(v->value, ','))) {
17641                   trunkgroup = atoi(c + 1);
17642                   if (trunkgroup > 0) {
17643                      if ((c = strchr(c + 1, ',')))
17644                         logicalspan = atoi(c + 1);
17645                      else
17646                         logicalspan = 0;
17647                      if (logicalspan >= 0) {
17648                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17649                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17650                      } else
17651                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17652                      } else
17653                         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);
17654                   } else
17655                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17656                } else
17657                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17658             } else
17659                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17660          } else {
17661             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17662          }
17663          v = v->next;
17664       }
17665    }
17666 #endif
17667 
17668    /* Copy the default jb config over global_jbconf */
17669    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17670 
17671    mwimonitornotify[0] = '\0';
17672 
17673    v = ast_variable_browse(cfg, "channels");
17674    if ((res = process_dahdi(base_conf, "", v, reload, 0))) {
17675       ast_mutex_unlock(&iflock);
17676       ast_config_destroy(cfg);
17677       if (ucfg) {
17678          ast_config_destroy(ucfg);
17679       }
17680       return res;
17681    }
17682 
17683    /* Now get configuration from all normal sections in chan_dahdi.conf: */
17684    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17685       /* [channels] and [trunkgroups] are used. Let's also reserve
17686        * [globals] and [general] for future use
17687        */
17688       if (!strcasecmp(cat, "general") ||
17689          !strcasecmp(cat, "trunkgroups") ||
17690          !strcasecmp(cat, "globals") ||
17691          !strcasecmp(cat, "channels")) {
17692          continue;
17693       }
17694 
17695       /* Copy base_conf to conf. */
17696       deep_copy_dahdi_chan_conf(conf, base_conf);
17697 
17698       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17699          ast_mutex_unlock(&iflock);
17700          ast_config_destroy(cfg);
17701          if (ucfg) {
17702             ast_config_destroy(ucfg);
17703          }
17704          return res;
17705       }
17706    }
17707 
17708    ast_config_destroy(cfg);
17709 
17710    if (ucfg) {
17711       const char *chans;
17712 
17713       process_dahdi(base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17714 
17715       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17716          if (!strcasecmp(cat, "general")) {
17717             continue;
17718          }
17719 
17720          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17721 
17722          if (ast_strlen_zero(chans)) {
17723             continue;
17724          }
17725 
17726          /* Copy base_conf to conf. */
17727          deep_copy_dahdi_chan_conf(conf, base_conf);
17728 
17729          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17730             ast_config_destroy(ucfg);
17731             ast_mutex_unlock(&iflock);
17732             return res;
17733          }
17734       }
17735       ast_config_destroy(ucfg);
17736    }
17737    ast_mutex_unlock(&iflock);
17738 
17739 #ifdef HAVE_PRI
17740    if (reload != 1) {
17741       int x;
17742       for (x = 0; x < NUM_SPANS; x++) {
17743          if (pris[x].pri.pvts[0]) {
17744             prepare_pri(pris + x);
17745             if (sig_pri_start_pri(&pris[x].pri)) {
17746                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17747                return -1;
17748             } else
17749                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17750          }
17751       }
17752    }
17753 #endif
17754 #if defined(HAVE_SS7)
17755    if (reload != 1) {
17756       int x;
17757       for (x = 0; x < NUM_SPANS; x++) {
17758          if (linksets[x].ss7.ss7) {
17759             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
17760             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
17761                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17762                return -1;
17763             } else
17764                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17765          }
17766       }
17767    }
17768 #endif   /* defined(HAVE_SS7) */
17769 #ifdef HAVE_OPENR2
17770    if (reload != 1) {
17771       int x;
17772       for (x = 0; x < r2links_count; x++) {
17773          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17774             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17775             return -1;
17776          } else {
17777             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17778          }
17779       }
17780    }
17781 #endif
17782    /* And start the monitor for the first time */
17783    restart_monitor();
17784    return 0;
17785 }

static int sig_pri_tone_to_dahditone ( enum sig_pri_tone  tone  )  [static]

Definition at line 2972 of file chan_dahdi.c.

References SIG_PRI_TONE_BUSY, SIG_PRI_TONE_CONGESTION, SIG_PRI_TONE_DIALRECALL, SIG_PRI_TONE_DIALTONE, SIG_PRI_TONE_INFO, SIG_PRI_TONE_RINGTONE, and SIG_PRI_TONE_STUTTER.

Referenced by my_pri_play_tone().

02973 {
02974    switch (tone) {
02975    case SIG_PRI_TONE_RINGTONE:
02976       return DAHDI_TONE_RINGTONE;
02977    case SIG_PRI_TONE_STUTTER:
02978       return DAHDI_TONE_STUTTER;
02979    case SIG_PRI_TONE_CONGESTION:
02980       return DAHDI_TONE_CONGESTION;
02981    case SIG_PRI_TONE_DIALTONE:
02982       return DAHDI_TONE_DIALTONE;
02983    case SIG_PRI_TONE_DIALRECALL:
02984       return DAHDI_TONE_DIALRECALL;
02985    case SIG_PRI_TONE_INFO:
02986       return DAHDI_TONE_INFO;
02987    case SIG_PRI_TONE_BUSY:
02988       return DAHDI_TONE_BUSY;
02989    default:
02990       return -1;
02991    }
02992 }

static int sig_ss7_tone_to_dahditone ( enum sig_ss7_tone  tone  )  [static]

Definition at line 3401 of file chan_dahdi.c.

References SIG_SS7_TONE_BUSY, SIG_SS7_TONE_CONGESTION, SIG_SS7_TONE_DIALRECALL, SIG_SS7_TONE_DIALTONE, SIG_SS7_TONE_INFO, SIG_SS7_TONE_RINGTONE, and SIG_SS7_TONE_STUTTER.

Referenced by my_ss7_play_tone().

03402 {
03403    switch (tone) {
03404    case SIG_SS7_TONE_RINGTONE:
03405       return DAHDI_TONE_RINGTONE;
03406    case SIG_SS7_TONE_STUTTER:
03407       return DAHDI_TONE_STUTTER;
03408    case SIG_SS7_TONE_CONGESTION:
03409       return DAHDI_TONE_CONGESTION;
03410    case SIG_SS7_TONE_DIALTONE:
03411       return DAHDI_TONE_DIALTONE;
03412    case SIG_SS7_TONE_DIALRECALL:
03413       return DAHDI_TONE_DIALRECALL;
03414    case SIG_SS7_TONE_INFO:
03415       return DAHDI_TONE_INFO;
03416    case SIG_SS7_TONE_BUSY:
03417       return DAHDI_TONE_BUSY;
03418    default:
03419       return -1;
03420    }
03421 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 11866 of file chan_dahdi.c.

11867 {
11868    return sigtype;
11869 }

static struct dahdi_ss7* ss7_resolve_linkset ( int  linkset  )  [static]

Definition at line 11755 of file chan_dahdi.c.

References linksets, and NUM_SPANS.

Referenced by linkset_addsigchan().

11756 {
11757    if ((linkset < 0) || (linkset >= NUM_SPANS))
11758       return NULL;
11759    else
11760       return &linksets[linkset - 1];
11761 }

static void string_replace ( char *  str,
int  char1,
int  char2 
) [static]

Definition at line 16285 of file chan_dahdi.c.

Referenced by parse_spanchan().

16286 {
16287    for (; *str; str++) {
16288       if (*str == char1) {
16289          *str = char2;
16290       }
16291    }
16292 }

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

Definition at line 4137 of file chan_dahdi.c.

References ast_channel_set_fd(), ast_debug, dahdi_subchannel::chan, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().

Referenced by analog_ss_thread(), attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), HandleCallOutgoing(), and unistim_hangup().

04138 {
04139    int tchan;
04140    int tinthreeway;
04141    struct ast_channel *towner;
04142 
04143    ast_debug(1, "Swapping %d and %d\n", a, b);
04144 
04145    tchan = p->subs[a].chan;
04146    towner = p->subs[a].owner;
04147    tinthreeway = p->subs[a].inthreeway;
04148 
04149    p->subs[a].chan = p->subs[b].chan;
04150    p->subs[a].owner = p->subs[b].owner;
04151    p->subs[a].inthreeway = p->subs[b].inthreeway;
04152 
04153    p->subs[b].chan = tchan;
04154    p->subs[b].owner = towner;
04155    p->subs[b].inthreeway = tinthreeway;
04156 
04157    if (p->subs[a].owner)
04158       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04159    if (p->subs[b].owner)
04160       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04161    wakeup_sub(p, a);
04162    wakeup_sub(p, b);
04163 }

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

Definition at line 4283 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), my_unallocate_sub(), and unistim_hangup().

04284 {
04285    if (!x) {
04286       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04287       return -1;
04288    }
04289    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04290    dahdi_close_sub(p, x);
04291    p->subs[x].linear = 0;
04292    p->subs[x].chan = 0;
04293    p->subs[x].owner = NULL;
04294    p->subs[x].inthreeway = 0;
04295    p->polarity = POLARITY_IDLE;
04296    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04297    return 0;
04298 }

static int unload_module ( void   )  [static]

Definition at line 16269 of file chan_dahdi.c.

References __unload_module(), ast_mutex_destroy, sig_ss7_linkset::lock, sig_pri_span::lock, dahdi_pvt::pri, and dahdi_pvt::ss7.

16270 {
16271 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16272    int y;
16273 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16274 #ifdef HAVE_PRI
16275    for (y = 0; y < NUM_SPANS; y++)
16276       ast_mutex_destroy(&pris[y].pri.lock);
16277 #endif
16278 #if defined(HAVE_SS7)
16279    for (y = 0; y < NUM_SPANS; y++)
16280       ast_mutex_destroy(&linksets[y].ss7.lock);
16281 #endif   /* defined(HAVE_SS7) */
16282    return __unload_module();
16283 }

static int update_conf ( struct dahdi_pvt p  )  [static]

Definition at line 4692 of file chan_dahdi.c.

References conf_add(), conf_del(), dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, isslavenative(), and dahdi_pvt::subs.

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

04693 {
04694    int needconf = 0;
04695    int x;
04696    int useslavenative;
04697    struct dahdi_pvt *slave = NULL;
04698 
04699    useslavenative = isslavenative(p, &slave);
04700    /* Start with the obvious, general stuff */
04701    for (x = 0; x < 3; x++) {
04702       /* Look for three way calls */
04703       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04704          conf_add(p, &p->subs[x], x, 0);
04705          needconf++;
04706       } else {
04707          conf_del(p, &p->subs[x], x);
04708       }
04709    }
04710    /* If we have a slave, add him to our conference now. or DAX
04711       if this is slave native */
04712    for (x = 0; x < MAX_SLAVES; x++) {
04713       if (p->slaves[x]) {
04714          if (useslavenative)
04715             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04716          else {
04717             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04718             needconf++;
04719          }
04720       }
04721    }
04722    /* If we're supposed to be in there, do so now */
04723    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04724       if (useslavenative)
04725          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04726       else {
04727          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04728          needconf++;
04729       }
04730    }
04731    /* If we have a master, add ourselves to his conference */
04732    if (p->master) {
04733       if (isslavenative(p->master, NULL)) {
04734          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04735       } else {
04736          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04737       }
04738    }
04739    if (!needconf) {
04740       /* Nobody is left (or should be left) in our conference.
04741          Kill it. */
04742       p->confno = -1;
04743    }
04744    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04745    return 0;
04746 }

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

Definition at line 3650 of file chan_dahdi.c.

References ast_channel_unlock, ast_null_frame, ast_queue_frame(), dahdi_lock_sub_owner(), dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by my_swap_subchannels(), and swap_subs().

03651 {
03652    dahdi_lock_sub_owner(p, a);
03653    if (p->subs[a].owner) {
03654       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03655       ast_channel_unlock(p->subs[a].owner);
03656    }
03657 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", } [static]

Definition at line 18173 of file chan_dahdi.c.

int alarm

Definition at line 4430 of file chan_dahdi.c.

Referenced by alarm2str().

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

Referenced by alarm2str().

struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static]

Definition at line 384 of file chan_dahdi.c.

Referenced by mwi_send_process_buffer().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 18173 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 365 of file chan_dahdi.c.

Referenced by handle_dahdi_show_cadences(), and my_set_cadence().

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

Referenced by handle_dahdi_show_cadences().

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

Definition at line 319 of file chan_dahdi.c.

int cur_adjpointcode = -1 [static]

Definition at line 522 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_cicbeginswith = -1 [static]

Definition at line 521 of file chan_dahdi.c.

int cur_defaultdpc = -1 [static]

Definition at line 524 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_linkset = -1 [static]

Definition at line 519 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_networkindicator = -1 [static]

Definition at line 523 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_pointcode = -1 [static]

Definition at line 520 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_ss7type = -1 [static]

Definition at line 518 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

const char* const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static]

Definition at line 5839 of file chan_dahdi.c.

struct analog_callback dahdi_analog_callbacks [static]

Definition at line 3528 of file chan_dahdi.c.

struct ast_data_handler dahdi_channels_data_provider [static]

Initial value:

Definition at line 17954 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 15406 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_data_entry dahdi_data_providers[] [static]

Initial value:

 {
   AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
   AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),

}

Definition at line 17964 of file chan_dahdi.c.

Referenced by load_module().

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 14563 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct sig_pri_callback dahdi_pri_callbacks [static]

Definition at line 3268 of file chan_dahdi.c.

Referenced by prepare_pri().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 14228 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct dahdi_parms_pseudo dahdi_pseudo_parms [static]

openr2_event_interface_t dahdi_r2_event_iface [static]

Definition at line 4099 of file chan_dahdi.c.

openr2_transcoder_interface_t dahdi_r2_transcode_iface [static]

Initial value:

Definition at line 4130 of file chan_dahdi.c.

char* dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility" [static]

Definition at line 5776 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 5749 of file chan_dahdi.c.

struct sig_ss7_callback dahdi_ss7_callbacks [static]

Definition at line 3434 of file chan_dahdi.c.

struct ast_cli_entry dahdi_ss7_cli[] [static]

Definition at line 16064 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_data_handler dahdi_status_data_provider [static]

Initial value:

Definition at line 17949 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1492 of file chan_dahdi.c.

Referenced by __unload_module(), analog_ss_thread(), dahdi_accept_r2_call_exec(), dahdi_new(), dahdi_send_callrerouting_facility_exec(), and load_module().

struct ast_data_handler dahdi_version_data_provider [static]

Initial value:

Definition at line 17959 of file chan_dahdi.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 268 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 392 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 393 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 406 of file chan_dahdi.c.

int dtmfcid_level = 256 [static]

Definition at line 411 of file chan_dahdi.c.

const char* const events[] [static]

Definition at line 4407 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

Definition at line 423 of file chan_dahdi.c.

Referenced by analog_ss_thread(), disa_exec(), and mgcp_ss().

int gendigittimeout = 8000 [static]

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

Definition at line 426 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and mgcp_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 276 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 435 of file chan_dahdi.c.

Referenced by destroy_all_channels(), and do_monitor().

struct dahdi_pvt* ifend = NULL [static]

Main interface list end

Definition at line 1296 of file chan_dahdi.c.

Referenced by dahdi_iflist_extract(), dahdi_request(), and determine_starting_point().

struct dahdi_pvt* iflist = NULL [static]

Main interface list start

Definition at line 1295 of file chan_dahdi.c.

Referenced by __oh323_destroy(), __unload_module(), action_dahdishowchannels(), dahdi_channels_data_provider_get(), dahdi_destroy_channel_bynum(), dahdi_iflist_extract(), dahdi_iflist_insert(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), determine_starting_point(), do_monitor(), find_call_locked(), find_channel(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), load_module(), mkintf(), oh323_alloc(), phone_request(), and unload_module().

ast_mutex_t iflock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Protect the interface list (of dahdi_pvt's).

Definition at line 432 of file chan_dahdi.c.

Referenced by __unload_module(), dahdi_cc_callback(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), destroy_all_channels(), do_monitor(), find_call_locked(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), and unload_module().

const char* const lbostr[] [static]

Definition at line 256 of file chan_dahdi.c.

Referenced by dahdi_show_status(), and dahdi_status_data_provider_get().

struct dahdi_ss7 linksets[NUM_SPANS] [static]

Definition at line 516 of file chan_dahdi.c.

Referenced by dahdi_ss7_error(), dahdi_ss7_message(), and ss7_resolve_linkset().

int matchdigittimeout = 3000 [static]

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

Definition at line 429 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and mgcp_ss().

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

Referenced by __sip_reliable_xmit(), __unload_module(), restart_monitor(), and unload_module().

ast_mutex_t monlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [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 443 of file chan_dahdi.c.

Referenced by __unload_module(), do_monitor(), restart_monitor(), and unload_module().

int mwilevel = 512 [static]

Definition at line 410 of file chan_dahdi.c.

Referenced by mwi_thread().

char mwimonitornotify[PATH_MAX] = "" [static]

Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled

Definition at line 398 of file chan_dahdi.c.

Referenced by notify_message(), and setup_dahdi_int().

char* name

Definition at line 4431 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 362 of file chan_dahdi.c.

Referenced by handle_dahdi_show_cadences(), and my_set_cadence().

int num_restart_pending = 0 [static]

Definition at line 452 of file chan_dahdi.c.

Referenced by dahdi_hangup(), dahdi_softhangup_all(), destroy_all_channels(), and my_all_subchannels_hungup().

int numbufs = 4 [static]

Definition at line 408 of file chan_dahdi.c.

char parkinglot[AST_MAX_EXTENSION] = "" [static]

Default parking lot for this channel

Definition at line 395 of file chan_dahdi.c.

Referenced by __find_callno(), ast_iax2_new(), build_parkinglot(), build_peer(), build_user(), builtin_atxfer(), check_access(), check_peer_ok(), copy_parkinglot(), create_addr_from_peer(), dahdi_new(), find_parkinglot(), find_parkinglot_by_exten_cb(), find_parkinglot_by_position_cb(), findparkinglotname(), func_channel_write_real(), gtalk_load_config(), gtalk_new(), park_exec_full(), park_space_reserve(), parkinglot_addref(), parkinglot_cmp_cb(), parkinglot_hash_cb(), parkinglot_is_marked_cb(), parkinglot_markall_cb(), parkinglot_unref(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), skinny_new(), and store_config_core().

int pridebugfd = -1 [static]

Definition at line 418 of file chan_dahdi.c.

Referenced by dahdi_pri_error(), dahdi_pri_message(), and handle_pri_set_debug_file().

ast_mutex_t pridebugfdlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Definition at line 438 of file chan_dahdi.c.

Referenced by dahdi_pri_error(), dahdi_pri_message(), and handle_pri_set_debug_file().

char pridebugfilename[1024] = "" [static]

Definition at line 419 of file chan_dahdi.c.

Referenced by handle_pri_set_debug_file().

struct dahdi_pri pris[NUM_SPANS] [static]

Definition at line 575 of file chan_dahdi.c.

Referenced by complete_span_helper(), dahdi_devicestate(), dahdi_pri_error(), dahdi_pri_message(), dahdi_restart(), destroy_all_channels(), handle_pri_debug(), handle_pri_service_generic(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), prepare_pri(), pri_create_spanmap(), pri_create_trunkgroup(), and pri_resolve_span().

char progzone[10] = "" [static]

Definition at line 403 of file chan_dahdi.c.

Referenced by dahdi_new().

struct dahdi_mfcr2** r2links [static]

Definition at line 560 of file chan_dahdi.c.

Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().

int r2links_count = 0 [static]

Definition at line 562 of file chan_dahdi.c.

Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().

int report_alarms = REPORT_CHANNEL_ALARMS [static]

Definition at line 415 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

ast_mutex_t restart_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

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

struct dahdi_pvt* round_robin[32] [static]

Round robin search locations.

Definition at line 3597 of file chan_dahdi.c.

Referenced by dahdi_request(), determine_starting_point(), and load_module().

ast_cond_t ss_thread_complete [static]

Definition at line 448 of file chan_dahdi.c.

Referenced by __unload_module(), load_module(), and my_decrease_ss_count().

int ss_thread_count = 0 [static]

Definition at line 451 of file chan_dahdi.c.

Referenced by analog_ss_thread(), my_decrease_ss_count(), and my_increase_ss_count().

ast_mutex_t ss_thread_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Definition at line 449 of file chan_dahdi.c.

Referenced by analog_ss_thread(), my_decrease_ss_count(), and my_increase_ss_count().

const char* const subnames[] [static]

Initial value:

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

Definition at line 608 of file chan_dahdi.c.

Referenced by alloc_sub(), dahdi_bridge(), and dahdi_new().

const char tdesc[] [static]

Definition at line 298 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 405 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 363 of file chan_dahdi.c.


Generated on Wed Apr 6 11:29:55 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7