Mon Oct 8 12:39:12 2012

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 <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_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 canmatch_featurecode (const char *exten)
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 void dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan)
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_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_cc_agent_destructor (struct ast_cc_agent *agent)
static int dahdi_pri_cc_agent_init (struct ast_cc_agent *agent, struct ast_channel *chan)
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 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 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_channel_from_str (const char *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_channels (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 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 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_ami_channel_event (void *pvt, struct ast_channel *chan)
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_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 int my_have_progressdetect (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 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_dial_digits (void *p, const char *dial_string)
static void my_pri_fixup_chans (void *chan_old, void *chan_new)
static void my_pri_init_config (void *priv, struct sig_pri_span *pri)
static void my_pri_make_cc_dialstring (void *priv, char *buf, size_t buf_size)
static int my_pri_play_tone (void *pvt, enum sig_pri_tone tone)
static void my_pri_ss7_open_media (void *p)
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 *cid_rings, 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_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_needringing (void *pvt, int value)
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
static void my_set_outgoing (void *pvt, int is_outgoing)
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_ringtimeout (void *pvt, int ringt)
static void my_set_waitingfordt (void *pvt, struct ast_channel *ast)
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 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 *default_conf, 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 sigtype_to_signalling (int sigtype)
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 = "ac1f6a56484a8820659555499174e588" , .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 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_cc_agent_callbacks dahdi_pri_cc_agent_callbacks
static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks
static const char dahdi_pri_cc_type [] = "DAHDI/PRI"
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 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 Protect the interface list (of dahdi_pvt's).
static const char *const lbostr []
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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 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 int pridebugfd = -1
static ast_mutex_t pridebugfdlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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 314 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 381 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmf(), and my_handle_dtmf().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 380 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 379 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_PROGRESS   1

Definition at line 378 of file chan_dahdi.c.

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

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

10,000 ms

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

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

100 ms

Definition at line 517 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 411 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 412 of file chan_dahdi.c.

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

#define CHAN_PSEUDO   -2

Definition at line 376 of file chan_dahdi.c.

Referenced by build_channels(), create_channel_name(), dahdi_ami_channel_event(), 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 518 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 652 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 653 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 3740 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 1244 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

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

Definition at line 312 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 520 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(), 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 1537 of file chan_dahdi.c.

Referenced by my_complete_conference_update().

#define HANGUP   1

Definition at line 15879 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_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_retrieve_acknowledge(), build_setup(), build_setup_acknowledge(), 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 408 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 512 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

#define MAX_SLAVES   4

Definition at line 655 of file chan_dahdi.c.

Referenced by isslavenative(), and my_complete_conference_update().

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

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

Referenced by analog_ss_thread(), and dahdi_new().

#define NUM_CADENCE_MAX   25

Definition at line 383 of file chan_dahdi.c.

#define NUM_SPANS   32

Definition at line 373 of file chan_dahdi.c.

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

#define POLARITY_IDLE   0

Definition at line 612 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 613 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 16955 of file chan_dahdi.c.

Referenced by process_dahdi().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 16957 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

#define R2_LINK_CAPACITY   10

Definition at line 12157 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 510 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 433 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

#define REPORT_SPAN_ALARMS   2

Definition at line 434 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

#define sig2str   dahdi_sig2str

Definition at line 4675 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 359 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 360 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 348 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 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_EM_E1   DAHDI_SIG_EM_E1

Definition at line 368 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 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_FEATB   (0x0800000 | DAHDI_SIG_EM)

Definition at line 347 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 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_FEATDMF   (0x0400000 | DAHDI_SIG_EM)

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_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)

Definition at line 349 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 350 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 351 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 356 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 357 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 355 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 353 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 354 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 352 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 362 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_func_read(), 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 84 of file chan_dahdi.c.

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 358 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 1539 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 363 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 367 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 365 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 366 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 364 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 361 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_func_read(), 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 275 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 608 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 607 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_off_hook(), my_pri_dial_digits(), my_pri_fixup_chans(), my_pri_play_tone(), my_pri_ss7_open_media(), my_set_cadence(), my_set_needringing(), my_set_polarity(), 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 609 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 15878 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 676 of file chan_dahdi.c.

00676                   {
00677    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00678    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00679 #if defined(HAVE_PRI)
00680    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00681 #endif   /* defined(HAVE_PRI) */
00682 };

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

00660              {
00661    MWI_SEND_NULL = 0,
00662    MWI_SEND_SA,
00663    MWI_SEND_SA_WAIT,
00664    MWI_SEND_PAUSE,
00665    MWI_SEND_SPILL,
00666    MWI_SEND_CLEANUP,
00667    MWI_SEND_DONE,
00668 } mwisend_states;


Function Documentation

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

Definition at line 8786 of file chan_dahdi.c.

References ast_bridged_channel(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, 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, dahdi_pvt::lock, ast_frame::mallocd, name, 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().

08787 {
08788    int res;
08789    int idx;
08790    struct ast_frame *f;
08791    int usedindex = -1;
08792    struct dahdi_pvt *p = ast->tech_pvt;
08793 
08794    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08795       idx = SUB_REAL;
08796    }
08797 
08798    p->subs[idx].f.frametype = AST_FRAME_NULL;
08799    p->subs[idx].f.datalen = 0;
08800    p->subs[idx].f.samples = 0;
08801    p->subs[idx].f.mallocd = 0;
08802    p->subs[idx].f.offset = 0;
08803    p->subs[idx].f.subclass.integer = 0;
08804    p->subs[idx].f.delivery = ast_tv(0,0);
08805    p->subs[idx].f.src = "dahdi_exception";
08806    p->subs[idx].f.data.ptr = NULL;
08807 
08808 
08809    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08810       /* If nobody owns us, absorb the event appropriately, otherwise
08811          we loop indefinitely.  This occurs when, during call waiting, the
08812          other end hangs up our channel so that it no longer exists, but we
08813          have neither FLASH'd nor ONHOOK'd to signify our desire to
08814          change to the other channel. */
08815       if (p->fake_event) {
08816          res = p->fake_event;
08817          p->fake_event = 0;
08818       } else
08819          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08820       /* Switch to real if there is one and this isn't something really silly... */
08821       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08822          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08823          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08824          p->owner = p->subs[SUB_REAL].owner;
08825          if (p->owner && ast_bridged_channel(p->owner))
08826             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08827          p->subs[SUB_REAL].needunhold = 1;
08828       }
08829       switch (res) {
08830       case DAHDI_EVENT_ONHOOK:
08831          dahdi_disable_ec(p);
08832          if (p->owner) {
08833             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08834             dahdi_ring_phone(p);
08835             p->callwaitingrepeat = 0;
08836             p->cidcwexpire = 0;
08837             p->cid_suppress_expire = 0;
08838          } else
08839             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08840          update_conf(p);
08841          break;
08842       case DAHDI_EVENT_RINGOFFHOOK:
08843          dahdi_enable_ec(p);
08844          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08845          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08846             p->subs[SUB_REAL].needanswer = 1;
08847             p->dialing = 0;
08848          }
08849          break;
08850       case DAHDI_EVENT_HOOKCOMPLETE:
08851       case DAHDI_EVENT_RINGERON:
08852       case DAHDI_EVENT_RINGEROFF:
08853          /* Do nothing */
08854          break;
08855       case DAHDI_EVENT_WINKFLASH:
08856          p->flashtime = ast_tvnow();
08857          if (p->owner) {
08858             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08859             if (p->owner->_state != AST_STATE_UP) {
08860                /* Answer if necessary */
08861                usedindex = dahdi_get_index(p->owner, p, 0);
08862                if (usedindex > -1) {
08863                   p->subs[usedindex].needanswer = 1;
08864                }
08865                ast_setstate(p->owner, AST_STATE_UP);
08866             }
08867             p->callwaitingrepeat = 0;
08868             p->cidcwexpire = 0;
08869             p->cid_suppress_expire = 0;
08870             if (ast_bridged_channel(p->owner))
08871                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08872             p->subs[SUB_REAL].needunhold = 1;
08873          } else
08874             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08875          update_conf(p);
08876          break;
08877       default:
08878          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08879       }
08880       f = &p->subs[idx].f;
08881       return f;
08882    }
08883    if (!(p->radio || (p->oprmode < 0)))
08884       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08885    /* If it's not us, return NULL immediately */
08886    if (ast != p->owner) {
08887       if (p->owner) {
08888          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08889       }
08890       f = &p->subs[idx].f;
08891       return f;
08892    }
08893 
08894    f = dahdi_handle_event(ast);
08895    if (!f) {
08896       const char *name = ast_strdupa(ast->name);
08897 
08898       /* Tell the CDR this DAHDI device hung up */
08899       ast_mutex_unlock(&p->lock);
08900       ast_channel_unlock(ast);
08901       ast_set_hangupsource(ast, name, 0);
08902       ast_channel_lock(ast);
08903       ast_mutex_lock(&p->lock);
08904    }
08905    return f;
08906 }

static void __reg_module ( void   )  [static]

Definition at line 18772 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 16701 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_mfcr2_cli, dahdi_pri_cc_agent_callbacks, dahdi_pri_cc_monitor_callbacks, dahdi_pri_cli, dahdi_r2_destroy_links(), 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(), and ss_thread_complete.

Referenced by load_module(), and unload_module().

16702 {
16703    struct dahdi_pvt *p;
16704 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16705    int i, j;
16706 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16707 
16708 #ifdef HAVE_PRI
16709    for (i = 0; i < NUM_SPANS; i++) {
16710       if (pris[i].pri.master != AST_PTHREADT_NULL)
16711          pthread_cancel(pris[i].pri.master);
16712    }
16713    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16714    ast_unregister_application(dahdi_send_keypad_facility_app);
16715 #ifdef HAVE_PRI_PROG_W_CAUSE
16716    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16717 #endif
16718 #endif
16719 #if defined(HAVE_SS7)
16720    for (i = 0; i < NUM_SPANS; i++) {
16721       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16722          pthread_cancel(linksets[i].ss7.master);
16723       }
16724    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16725 #endif   /* defined(HAVE_SS7) */
16726 #if defined(HAVE_OPENR2)
16727    dahdi_r2_destroy_links();
16728    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16729    ast_unregister_application(dahdi_accept_r2_call_app);
16730 #endif
16731 
16732    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16733    ast_manager_unregister("DAHDIDialOffhook");
16734    ast_manager_unregister("DAHDIHangup");
16735    ast_manager_unregister("DAHDITransfer");
16736    ast_manager_unregister("DAHDIDNDoff");
16737    ast_manager_unregister("DAHDIDNDon");
16738    ast_manager_unregister("DAHDIShowChannels");
16739    ast_manager_unregister("DAHDIRestart");
16740    ast_data_unregister(NULL);
16741    ast_channel_unregister(&dahdi_tech);
16742 
16743    /* Hangup all interfaces if they have an owner */
16744    ast_mutex_lock(&iflock);
16745    for (p = iflist; p; p = p->next) {
16746       if (p->owner)
16747          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16748    }
16749    ast_mutex_unlock(&iflock);
16750 
16751    ast_mutex_lock(&monlock);
16752    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16753       pthread_cancel(monitor_thread);
16754       pthread_kill(monitor_thread, SIGURG);
16755       pthread_join(monitor_thread, NULL);
16756    }
16757    monitor_thread = AST_PTHREADT_STOP;
16758    ast_mutex_unlock(&monlock);
16759 
16760    destroy_all_channels();
16761 
16762 #if defined(HAVE_PRI)
16763    for (i = 0; i < NUM_SPANS; i++) {
16764       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16765          pthread_join(pris[i].pri.master, NULL);
16766       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16767          dahdi_close_pri_fd(&(pris[i]), j);
16768       }
16769       sig_pri_stop_pri(&pris[i].pri);
16770    }
16771 #if defined(HAVE_PRI_CCSS)
16772    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16773    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16774 #endif   /* defined(HAVE_PRI_CCSS) */
16775    sig_pri_unload();
16776 #endif
16777 
16778 #if defined(HAVE_SS7)
16779    for (i = 0; i < NUM_SPANS; i++) {
16780       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16781          pthread_join(linksets[i].ss7.master, NULL);
16782       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16783          dahdi_close_ss7_fd(&(linksets[i]), j);
16784       }
16785    }
16786 #endif   /* defined(HAVE_SS7) */
16787    ast_cond_destroy(&ss_thread_complete);
16788    return 0;
16789 }

static void __unreg_module ( void   )  [static]

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

03742 {
03743    int res;
03744    if (p->subs[SUB_REAL].owner == ast)
03745       res = 0;
03746    else if (p->subs[SUB_CALLWAIT].owner == ast)
03747       res = 1;
03748    else if (p->subs[SUB_THREEWAY].owner == ast)
03749       res = 2;
03750    else {
03751       res = -1;
03752       if (!nullok)
03753          ast_log(LOG_WARNING,
03754             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03755             ast ? ast->name : "", p->channel, fname, line);
03756    }
03757    return res;
03758 }

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

Definition at line 16016 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_from_str(), and dahdi_pvt::owner.

Referenced by load_module().

16017 {
16018    struct dahdi_pvt *p;
16019    const char *channel = astman_get_header(m, "DAHDIChannel");
16020    const char *number = astman_get_header(m, "Number");
16021    int i;
16022 
16023    if (ast_strlen_zero(channel)) {
16024       astman_send_error(s, m, "No channel specified");
16025       return 0;
16026    }
16027    if (ast_strlen_zero(number)) {
16028       astman_send_error(s, m, "No number specified");
16029       return 0;
16030    }
16031    p = find_channel_from_str(channel);
16032    if (!p) {
16033       astman_send_error(s, m, "No such channel");
16034       return 0;
16035    }
16036    if (!p->owner) {
16037       astman_send_error(s, m, "Channel does not have it's owner");
16038       return 0;
16039    }
16040    for (i = 0; i < strlen(number); i++) {
16041       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16042       dahdi_queue_frame(p, &f);
16043    }
16044    astman_send_ack(s, m, "DAHDIDialOffhook");
16045    return 0;
16046 }

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

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

Referenced by load_module().

15952 {
15953    struct dahdi_pvt *p;
15954    const char *channel = astman_get_header(m, "DAHDIChannel");
15955 
15956    if (ast_strlen_zero(channel)) {
15957       astman_send_error(s, m, "No channel specified");
15958       return 0;
15959    }
15960    p = find_channel_from_str(channel);
15961    if (!p) {
15962       astman_send_error(s, m, "No such channel");
15963       return 0;
15964    }
15965    dahdi_dnd(p, 0);
15966    astman_send_ack(s, m, "DND Disabled");
15967    return 0;
15968 }

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

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

Referenced by load_module().

15933 {
15934    struct dahdi_pvt *p;
15935    const char *channel = astman_get_header(m, "DAHDIChannel");
15936 
15937    if (ast_strlen_zero(channel)) {
15938       astman_send_error(s, m, "No channel specified");
15939       return 0;
15940    }
15941    p = find_channel_from_str(channel);
15942    if (!p) {
15943       astman_send_error(s, m, "No such channel");
15944       return 0;
15945    }
15946    dahdi_dnd(p, 1);
15947    astman_send_ack(s, m, "DND Enabled");
15948    return 0;
15949 }

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

Definition at line 15215 of file chan_dahdi.c.

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

Referenced by load_module().

15216 {
15217    if (dahdi_restart() != 0) {
15218       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15219       return 1;
15220    }
15221    astman_send_ack(s, m, "DAHDIRestart: Success");
15222    return 0;
15223 }

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

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

16049 {
16050    struct dahdi_pvt *tmp = NULL;
16051    const char *id = astman_get_header(m, "ActionID");
16052    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16053    char idText[256] = "";
16054    int channels = 0;
16055    int dahdichanquery;
16056 
16057    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16058       /* Not numeric string. */
16059       dahdichanquery = -1;
16060    }
16061 
16062    astman_send_ack(s, m, "DAHDI channel status will follow");
16063    if (!ast_strlen_zero(id))
16064       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16065 
16066    ast_mutex_lock(&iflock);
16067 
16068    for (tmp = iflist; tmp; tmp = tmp->next) {
16069       if (tmp->channel > 0) {
16070          int alm;
16071 
16072          /* If a specific channel is queried for, only deliver status for that channel */
16073          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16074             continue;
16075 
16076          alm = get_alarms(tmp);
16077          channels++;
16078          if (tmp->owner) {
16079             /* Add data if we have a current call */
16080             astman_append(s,
16081                "Event: DAHDIShowChannels\r\n"
16082                "DAHDIChannel: %d\r\n"
16083                "Channel: %s\r\n"
16084                "Uniqueid: %s\r\n"
16085                "AccountCode: %s\r\n"
16086                "Signalling: %s\r\n"
16087                "SignallingCode: %d\r\n"
16088                "Context: %s\r\n"
16089                "DND: %s\r\n"
16090                "Alarm: %s\r\n"
16091                "%s"
16092                "\r\n",
16093                tmp->channel,
16094                tmp->owner->name,
16095                tmp->owner->uniqueid,
16096                tmp->owner->accountcode,
16097                sig2str(tmp->sig),
16098                tmp->sig,
16099                tmp->context,
16100                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16101                alarm2str(alm), idText);
16102          } else {
16103             astman_append(s,
16104                "Event: DAHDIShowChannels\r\n"
16105                "DAHDIChannel: %d\r\n"
16106                "Signalling: %s\r\n"
16107                "SignallingCode: %d\r\n"
16108                "Context: %s\r\n"
16109                "DND: %s\r\n"
16110                "Alarm: %s\r\n"
16111                "%s"
16112                "\r\n",
16113                tmp->channel, sig2str(tmp->sig), tmp->sig,
16114                tmp->context,
16115                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16116                alarm2str(alm), idText);
16117          }
16118       }
16119    }
16120 
16121    ast_mutex_unlock(&iflock);
16122 
16123    astman_append(s,
16124       "Event: DAHDIShowChannelsComplete\r\n"
16125       "%s"
16126       "Items: %d\r\n"
16127       "\r\n",
16128       idText,
16129       channels);
16130    return 0;
16131 }

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

Definition at line 15970 of file chan_dahdi.c.

References analog_lib_handles(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel_from_str(), dahdi_pvt::sig, and TRANSFER.

Referenced by load_module().

15971 {
15972    struct dahdi_pvt *p;
15973    const char *channel = astman_get_header(m, "DAHDIChannel");
15974 
15975    if (ast_strlen_zero(channel)) {
15976       astman_send_error(s, m, "No channel specified");
15977       return 0;
15978    }
15979    p = find_channel_from_str(channel);
15980    if (!p) {
15981       astman_send_error(s, m, "No such channel");
15982       return 0;
15983    }
15984    if (!analog_lib_handles(p->sig, 0, 0)) {
15985       astman_send_error(s, m, "Channel signaling is not analog");
15986       return 0;
15987    }
15988    dahdi_fake_event(p,TRANSFER);
15989    astman_send_ack(s, m, "DAHDITransfer");
15990    return 0;
15991 }

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

Definition at line 15993 of file chan_dahdi.c.

References analog_lib_handles(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel_from_str(), HANGUP, and dahdi_pvt::sig.

Referenced by load_module().

15994 {
15995    struct dahdi_pvt *p;
15996    const char *channel = astman_get_header(m, "DAHDIChannel");
15997 
15998    if (ast_strlen_zero(channel)) {
15999       astman_send_error(s, m, "No channel specified");
16000       return 0;
16001    }
16002    p = find_channel_from_str(channel);
16003    if (!p) {
16004       astman_send_error(s, m, "No such channel");
16005       return 0;
16006    }
16007    if (!analog_lib_handles(p->sig, 0, 0)) {
16008       astman_send_error(s, m, "Channel signaling is not analog");
16009       return 0;
16010    }
16011    dahdi_fake_event(p,HANGUP);
16012    astman_send_ack(s, m, "DAHDIHangup");
16013    return 0;
16014 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4592 of file chan_dahdi.c.

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04593 {
04594    int x;
04595    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04596       if (alarms[x].alarm & alm)
04597          return alarms[x].name;
04598    }
04599    return alm ? "Unknown Alarm" : "No Alarm";
04600 }

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

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

04394 {
04395    struct dahdi_bufferinfo bi;
04396    int res;
04397    if (p->subs[x].dfd >= 0) {
04398       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04399       return -1;
04400    }
04401 
04402    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04403    if (p->subs[x].dfd <= -1) {
04404       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04405       return -1;
04406    }
04407 
04408    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04409    if (!res) {
04410       bi.txbufpolicy = p->buf_policy;
04411       bi.rxbufpolicy = p->buf_policy;
04412       bi.numbufs = p->buf_no;
04413       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04414       if (res < 0) {
04415          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04416       }
04417    } else
04418       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04419 
04420    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04421       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04422       dahdi_close_sub(p, x);
04423       p->subs[x].dfd = -1;
04424       return -1;
04425    }
04426    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04427    return 0;
04428 }

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

Definition at line 4677 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 action_transfer(), action_transferhangup(), 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().

04678 {
04679    switch (signalling) {
04680    case SIG_FXOLS:
04681    case SIG_FXOGS:
04682    case SIG_FXOKS:
04683    case SIG_FXSLS:
04684    case SIG_FXSGS:
04685    case SIG_FXSKS:
04686    case SIG_EMWINK:
04687    case SIG_EM:
04688    case SIG_EM_E1:
04689    case SIG_FEATD:
04690    case SIG_FEATDMF:
04691    case SIG_E911:
04692    case SIG_FGC_CAMA:
04693    case SIG_FGC_CAMAMF:
04694    case SIG_FEATB:
04695    case SIG_SFWINK:
04696    case SIG_SF:
04697    case SIG_SF_FEATD:
04698    case SIG_SF_FEATDMF:
04699    case SIG_FEATDMF_TA:
04700    case SIG_SF_FEATB:
04701       break;
04702    default:
04703       /* The rest of the function should cover the remainder of signalling types */
04704       return 0;
04705    }
04706 
04707    if (radio)
04708       return 0;
04709 
04710    if (oprmode)
04711       return 0;
04712 
04713    return 1;
04714 }

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

Definition at line 9927 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_exten(), 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, canmatch_featurecode(), 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, 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().

09928 {
09929    struct ast_channel *chan = data;
09930    struct dahdi_pvt *p = chan->tech_pvt;
09931    char exten[AST_MAX_EXTENSION] = "";
09932    char exten2[AST_MAX_EXTENSION] = "";
09933    unsigned char buf[256];
09934    char dtmfcid[300];
09935    char dtmfbuf[300];
09936    struct callerid_state *cs = NULL;
09937    char *name = NULL, *number = NULL;
09938    int distMatches;
09939    int curRingData[3];
09940    int receivedRingT;
09941    int counter1;
09942    int counter;
09943    int samples = 0;
09944    struct ast_smdi_md_message *smdi_msg = NULL;
09945    int flags = 0;
09946    int i;
09947    int timeout;
09948    int getforward = 0;
09949    char *s1, *s2;
09950    int len = 0;
09951    int res;
09952    int idx;
09953 
09954    ast_mutex_lock(&ss_thread_lock);
09955    ss_thread_count++;
09956    ast_mutex_unlock(&ss_thread_lock);
09957    /* in the bizarre case where the channel has become a zombie before we
09958       even get started here, abort safely
09959    */
09960    if (!p) {
09961       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09962       ast_hangup(chan);
09963       goto quit;
09964    }
09965    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09966    idx = dahdi_get_index(chan, p, 1);
09967    if (idx < 0) {
09968       ast_log(LOG_WARNING, "Huh?\n");
09969       ast_hangup(chan);
09970       goto quit;
09971    }
09972    if (p->dsp)
09973       ast_dsp_digitreset(p->dsp);
09974    switch (p->sig) {
09975    case SIG_FEATD:
09976    case SIG_FEATDMF:
09977    case SIG_FEATDMF_TA:
09978    case SIG_E911:
09979    case SIG_FGC_CAMAMF:
09980    case SIG_FEATB:
09981    case SIG_EMWINK:
09982    case SIG_SF_FEATD:
09983    case SIG_SF_FEATDMF:
09984    case SIG_SF_FEATB:
09985    case SIG_SFWINK:
09986       if (dahdi_wink(p, idx))
09987          goto quit;
09988       /* Fall through */
09989    case SIG_EM:
09990    case SIG_EM_E1:
09991    case SIG_SF:
09992    case SIG_FGC_CAMA:
09993       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09994       if (p->dsp)
09995          ast_dsp_digitreset(p->dsp);
09996       /* set digit mode appropriately */
09997       if (p->dsp) {
09998          if (NEED_MFDETECT(p))
09999             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10000          else
10001             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10002       }
10003       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10004       /* Wait for the first digit only if immediate=no */
10005       if (!p->immediate)
10006          /* Wait for the first digit (up to 5 seconds). */
10007          res = ast_waitfordigit(chan, 5000);
10008       else
10009          res = 0;
10010       if (res > 0) {
10011          /* save first char */
10012          dtmfbuf[0] = res;
10013          switch (p->sig) {
10014          case SIG_FEATD:
10015          case SIG_SF_FEATD:
10016             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10017             if (res > 0)
10018                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10019             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10020             break;
10021          case SIG_FEATDMF_TA:
10022             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10023             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10024             if (dahdi_wink(p, idx)) goto quit;
10025             dtmfbuf[0] = 0;
10026             /* Wait for the first digit (up to 5 seconds). */
10027             res = ast_waitfordigit(chan, 5000);
10028             if (res <= 0) break;
10029             dtmfbuf[0] = res;
10030             /* fall through intentionally */
10031          case SIG_FEATDMF:
10032          case SIG_E911:
10033          case SIG_FGC_CAMAMF:
10034          case SIG_SF_FEATDMF:
10035             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10036             /* if international caca, do it again to get real ANO */
10037             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10038             {
10039                if (dahdi_wink(p, idx)) goto quit;
10040                dtmfbuf[0] = 0;
10041                /* Wait for the first digit (up to 5 seconds). */
10042                res = ast_waitfordigit(chan, 5000);
10043                if (res <= 0) break;
10044                dtmfbuf[0] = res;
10045                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10046             }
10047             if (res > 0) {
10048                /* if E911, take off hook */
10049                if (p->sig == SIG_E911)
10050                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10051                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10052             }
10053             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10054             break;
10055          case SIG_FEATB:
10056          case SIG_SF_FEATB:
10057             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10058             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10059             break;
10060          case SIG_EMWINK:
10061             /* if we received a '*', we are actually receiving Feature Group D
10062                dial syntax, so use that mode; otherwise, fall through to normal
10063                mode
10064             */
10065             if (res == '*') {
10066                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10067                if (res > 0)
10068                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10069                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10070                break;
10071             }
10072          default:
10073             /* If we got the first digit, get the rest */
10074             len = 1;
10075             dtmfbuf[len] = '\0';
10076             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10077                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10078                   timeout = matchdigittimeout;
10079                } else {
10080                   timeout = gendigittimeout;
10081                }
10082                res = ast_waitfordigit(chan, timeout);
10083                if (res < 0) {
10084                   ast_debug(1, "waitfordigit returned < 0...\n");
10085                   ast_hangup(chan);
10086                   goto quit;
10087                } else if (res) {
10088                   dtmfbuf[len++] = res;
10089                   dtmfbuf[len] = '\0';
10090                } else {
10091                   break;
10092                }
10093             }
10094             break;
10095          }
10096       }
10097       if (res == -1) {
10098          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10099          ast_hangup(chan);
10100          goto quit;
10101       } else if (res < 0) {
10102          ast_debug(1, "Got hung up before digits finished\n");
10103          ast_hangup(chan);
10104          goto quit;
10105       }
10106 
10107       if (p->sig == SIG_FGC_CAMA) {
10108          char anibuf[100];
10109 
10110          if (ast_safe_sleep(chan,1000) == -1) {
10111             ast_hangup(chan);
10112             goto quit;
10113          }
10114          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10115          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10116          res = my_getsigstr(chan, anibuf, "#", 10000);
10117          if ((res > 0) && (strlen(anibuf) > 2)) {
10118             if (anibuf[strlen(anibuf) - 1] == '#')
10119                anibuf[strlen(anibuf) - 1] = 0;
10120             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10121          }
10122          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10123       }
10124 
10125       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10126       if (ast_strlen_zero(exten))
10127          ast_copy_string(exten, "s", sizeof(exten));
10128       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10129          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10130          if (exten[0] == '*') {
10131             char *stringp=NULL;
10132             ast_copy_string(exten2, exten, sizeof(exten2));
10133             /* Parse out extension and callerid */
10134             stringp=exten2 +1;
10135             s1 = strsep(&stringp, "*");
10136             s2 = strsep(&stringp, "*");
10137             if (s2) {
10138                if (!ast_strlen_zero(p->cid_num))
10139                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10140                else
10141                   ast_set_callerid(chan, s1, NULL, s1);
10142                ast_copy_string(exten, s2, sizeof(exten));
10143             } else
10144                ast_copy_string(exten, s1, sizeof(exten));
10145          } else if (p->sig == SIG_FEATD)
10146             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10147       }
10148       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10149          if (exten[0] == '*') {
10150             char *stringp=NULL;
10151             ast_copy_string(exten2, exten, sizeof(exten2));
10152             /* Parse out extension and callerid */
10153             stringp=exten2 +1;
10154             s1 = strsep(&stringp, "#");
10155             s2 = strsep(&stringp, "#");
10156             if (s2) {
10157                if (!ast_strlen_zero(p->cid_num))
10158                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10159                else
10160                   if (*(s1 + 2))
10161                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10162                ast_copy_string(exten, s2 + 1, sizeof(exten));
10163             } else
10164                ast_copy_string(exten, s1 + 2, sizeof(exten));
10165          } else
10166             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10167       }
10168       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10169          if (exten[0] == '*') {
10170             char *stringp=NULL;
10171             ast_copy_string(exten2, exten, sizeof(exten2));
10172             /* Parse out extension and callerid */
10173             stringp=exten2 +1;
10174             s1 = strsep(&stringp, "#");
10175             s2 = strsep(&stringp, "#");
10176             if (s2 && (*(s2 + 1) == '0')) {
10177                if (*(s2 + 2))
10178                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10179             }
10180             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10181             else ast_copy_string(exten, "911", sizeof(exten));
10182          } else
10183             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10184       }
10185       if (p->sig == SIG_FEATB) {
10186          if (exten[0] == '*') {
10187             char *stringp=NULL;
10188             ast_copy_string(exten2, exten, sizeof(exten2));
10189             /* Parse out extension and callerid */
10190             stringp=exten2 +1;
10191             s1 = strsep(&stringp, "#");
10192             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10193          } else
10194             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10195       }
10196       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10197          dahdi_wink(p, idx);
10198          /* some switches require a minimum guard time between
10199             the last FGD wink and something that answers
10200             immediately. This ensures it */
10201          if (ast_safe_sleep(chan, 100)) {
10202             ast_hangup(chan);
10203             goto quit;
10204          }
10205       }
10206       dahdi_enable_ec(p);
10207       if (NEED_MFDETECT(p)) {
10208          if (p->dsp) {
10209             if (!p->hardwaredtmf)
10210                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10211             else {
10212                ast_dsp_free(p->dsp);
10213                p->dsp = NULL;
10214             }
10215          }
10216       }
10217 
10218       if (ast_exists_extension(chan, chan->context, exten, 1,
10219          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10220          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10221          if (p->dsp) ast_dsp_digitreset(p->dsp);
10222          res = ast_pbx_run(chan);
10223          if (res) {
10224             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10225             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10226          }
10227          goto quit;
10228       } else {
10229          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10230          sleep(2);
10231          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10232          if (res < 0)
10233             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10234          else
10235             sleep(1);
10236          res = ast_streamfile(chan, "ss-noservice", chan->language);
10237          if (res >= 0)
10238             ast_waitstream(chan, "");
10239          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10240          ast_hangup(chan);
10241          goto quit;
10242       }
10243       break;
10244    case SIG_FXOLS:
10245    case SIG_FXOGS:
10246    case SIG_FXOKS:
10247       /* Read the first digit */
10248       timeout = firstdigittimeout;
10249       /* If starting a threeway call, never timeout on the first digit so someone
10250          can use flash-hook as a "hold" feature */
10251       if (p->subs[SUB_THREEWAY].owner)
10252          timeout = 999999;
10253       while (len < AST_MAX_EXTENSION-1) {
10254          /* Read digit unless it's supposed to be immediate, in which case the
10255             only answer is 's' */
10256          if (p->immediate)
10257             res = 's';
10258          else
10259             res = ast_waitfordigit(chan, timeout);
10260          timeout = 0;
10261          if (res < 0) {
10262             ast_debug(1, "waitfordigit returned < 0...\n");
10263             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10264             ast_hangup(chan);
10265             goto quit;
10266          } else if (res) {
10267             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10268             exten[len++]=res;
10269             exten[len] = '\0';
10270          }
10271          if (!ast_ignore_pattern(chan->context, exten))
10272             tone_zone_play_tone(p->subs[idx].dfd, -1);
10273          else
10274             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10275          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10276             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10277                if (getforward) {
10278                   /* Record this as the forwarding extension */
10279                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10280                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10281                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10282                   if (res)
10283                      break;
10284                   usleep(500000);
10285                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10286                   sleep(1);
10287                   memset(exten, 0, sizeof(exten));
10288                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10289                   len = 0;
10290                   getforward = 0;
10291                } else {
10292                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10293                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10294                   if (!ast_strlen_zero(p->cid_num)) {
10295                      if (!p->hidecallerid)
10296                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10297                      else
10298                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10299                   }
10300                   if (!ast_strlen_zero(p->cid_name)) {
10301                      if (!p->hidecallerid)
10302                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10303                   }
10304                   ast_setstate(chan, AST_STATE_RING);
10305                   dahdi_enable_ec(p);
10306                   res = ast_pbx_run(chan);
10307                   if (res) {
10308                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10309                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10310                   }
10311                   goto quit;
10312                }
10313             } else {
10314                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10315                   so just set the timeout to matchdigittimeout and wait some more */
10316                timeout = matchdigittimeout;
10317             }
10318          } else if (res == 0) {
10319             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10320             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10321             dahdi_wait_event(p->subs[idx].dfd);
10322             ast_hangup(chan);
10323             goto quit;
10324          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10325             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10326             /* Disable call waiting if enabled */
10327             p->callwaiting = 0;
10328             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10329             if (res) {
10330                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10331                   chan->name, strerror(errno));
10332             }
10333             len = 0;
10334             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10335             memset(exten, 0, sizeof(exten));
10336             timeout = firstdigittimeout;
10337 
10338          } else if (!strcmp(exten,ast_pickup_ext())) {
10339             /* Scan all channels and see if there are any
10340              * ringing channels that have call groups
10341              * that equal this channels pickup group
10342              */
10343             if (idx == SUB_REAL) {
10344                /* Switch us from Third call to Call Wait */
10345                if (p->subs[SUB_THREEWAY].owner) {
10346                   /* If you make a threeway call and the *8# a call, it should actually
10347                      look like a callwait */
10348                   alloc_sub(p, SUB_CALLWAIT);
10349                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10350                   unalloc_sub(p, SUB_THREEWAY);
10351                }
10352                dahdi_enable_ec(p);
10353                if (ast_pickup_call(chan)) {
10354                   ast_debug(1, "No call pickup possible...\n");
10355                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10356                   dahdi_wait_event(p->subs[idx].dfd);
10357                }
10358                ast_hangup(chan);
10359                goto quit;
10360             } else {
10361                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10362                ast_hangup(chan);
10363                goto quit;
10364             }
10365 
10366          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10367             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10368             /* Disable Caller*ID if enabled */
10369             p->hidecallerid = 1;
10370             ast_party_number_free(&chan->caller.id.number);
10371             ast_party_number_init(&chan->caller.id.number);
10372             ast_party_name_free(&chan->caller.id.name);
10373             ast_party_name_init(&chan->caller.id.name);
10374             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10375             if (res) {
10376                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10377                   chan->name, strerror(errno));
10378             }
10379             len = 0;
10380             memset(exten, 0, sizeof(exten));
10381             timeout = firstdigittimeout;
10382          } else if (p->callreturn && !strcmp(exten, "*69")) {
10383             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10384             break;
10385          } else if (!strcmp(exten, "*78")) {
10386             dahdi_dnd(p, 1);
10387             /* Do not disturb */
10388             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10389             getforward = 0;
10390             memset(exten, 0, sizeof(exten));
10391             len = 0;
10392          } else if (!strcmp(exten, "*79")) {
10393             dahdi_dnd(p, 0);
10394             /* Do not disturb */
10395             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10396             getforward = 0;
10397             memset(exten, 0, sizeof(exten));
10398             len = 0;
10399          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10400             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401             getforward = 1;
10402             memset(exten, 0, sizeof(exten));
10403             len = 0;
10404          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10405             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10406             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10407             memset(p->call_forward, 0, sizeof(p->call_forward));
10408             getforward = 0;
10409             memset(exten, 0, sizeof(exten));
10410             len = 0;
10411          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10412                   p->subs[SUB_THREEWAY].owner &&
10413                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10414             /* This is a three way call, the main call being a real channel,
10415                and we're parking the first call. */
10416             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10417                chan, exten, chan->context, 0, NULL);
10418             ast_verb(3, "Parking call to '%s'\n", chan->name);
10419             break;
10420          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10421             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10422             /* Enable Caller*ID if enabled */
10423             p->hidecallerid = 0;
10424             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10425             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10426             if (res) {
10427                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10428                   chan->name, strerror(errno));
10429             }
10430             len = 0;
10431             memset(exten, 0, sizeof(exten));
10432             timeout = firstdigittimeout;
10433          } else if (!strcmp(exten, "*0")) {
10434             struct ast_channel *nbridge =
10435                p->subs[SUB_THREEWAY].owner;
10436             struct dahdi_pvt *pbridge = NULL;
10437             /* set up the private struct of the bridged one, if any */
10438             if (nbridge && ast_bridged_channel(nbridge))
10439                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10440             if (nbridge && pbridge &&
10441                (nbridge->tech == &dahdi_tech) &&
10442                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10443                ISTRUNK(pbridge)) {
10444                int func = DAHDI_FLASH;
10445                /* Clear out the dial buffer */
10446                p->dop.dialstr[0] = '\0';
10447                /* flash hookswitch */
10448                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10449                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10450                      nbridge->name, strerror(errno));
10451                }
10452                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10453                unalloc_sub(p, SUB_THREEWAY);
10454                p->owner = p->subs[SUB_REAL].owner;
10455                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10456                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10457                ast_hangup(chan);
10458                goto quit;
10459             } else {
10460                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10461                dahdi_wait_event(p->subs[idx].dfd);
10462                tone_zone_play_tone(p->subs[idx].dfd, -1);
10463                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10464                unalloc_sub(p, SUB_THREEWAY);
10465                p->owner = p->subs[SUB_REAL].owner;
10466                ast_hangup(chan);
10467                goto quit;
10468             }
10469          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10470             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10471             && !canmatch_featurecode(exten)) {
10472             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10473                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10474                chan->context);
10475             break;
10476          }
10477          if (!timeout)
10478             timeout = gendigittimeout;
10479          if (len && !ast_ignore_pattern(chan->context, exten))
10480             tone_zone_play_tone(p->subs[idx].dfd, -1);
10481       }
10482       break;
10483    case SIG_FXSLS:
10484    case SIG_FXSGS:
10485    case SIG_FXSKS:
10486       /* check for SMDI messages */
10487       if (p->use_smdi && p->smdi_iface) {
10488          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10489 
10490          if (smdi_msg != NULL) {
10491             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10492 
10493             if (smdi_msg->type == 'B')
10494                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10495             else if (smdi_msg->type == 'N')
10496                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10497 
10498             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10499          } else {
10500             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10501          }
10502       }
10503 
10504       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10505          number = smdi_msg->calling_st;
10506 
10507       /* If we want caller id, we're in a prering state due to a polarity reversal
10508        * and we're set to use a polarity reversal to trigger the start of caller id,
10509        * grab the caller id and wait for ringing to start... */
10510       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10511                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10512          /* If set to use DTMF CID signalling, listen for DTMF */
10513          if (p->cid_signalling == CID_SIG_DTMF) {
10514             int k = 0;
10515             cs = NULL;
10516             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10517             dahdi_setlinear(p->subs[idx].dfd, 0);
10518             /*
10519              * We are the only party interested in the Rx stream since
10520              * we have not answered yet.  We don't need or even want DTMF
10521              * emulation.  The DTMF digits can come so fast that emulation
10522              * can drop some of them.
10523              */
10524             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10525             res = 4000;/* This is a typical OFF time between rings. */
10526             for (;;) {
10527                struct ast_frame *f;
10528                res = ast_waitfor(chan, res);
10529                if (res <= 0) {
10530                   /*
10531                    * We do not need to restore the dahdi_setlinear()
10532                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10533                    * are hanging up the channel.
10534                    */
10535                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10536                      "Exiting simple switch\n");
10537                   ast_hangup(chan);
10538                   goto quit;
10539                }
10540                f = ast_read(chan);
10541                if (!f)
10542                   break;
10543                if (f->frametype == AST_FRAME_DTMF) {
10544                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10545                      dtmfbuf[k++] = f->subclass.integer;
10546                   }
10547                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10548                   res = 4000;/* This is a typical OFF time between rings. */
10549                }
10550                ast_frfree(f);
10551                if (chan->_state == AST_STATE_RING ||
10552                   chan->_state == AST_STATE_RINGING)
10553                   break; /* Got ring */
10554             }
10555             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10556             dtmfbuf[k] = '\0';
10557             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10558             /* Got cid and ring. */
10559             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10560             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10561             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10562             /* If first byte is NULL, we have no cid */
10563             if (!ast_strlen_zero(dtmfcid))
10564                number = dtmfcid;
10565             else
10566                number = NULL;
10567          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10568          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10569             cs = callerid_new(p->cid_signalling);
10570             if (cs) {
10571                samples = 0;
10572 #if 1
10573                bump_gains(p);
10574 #endif
10575                /* Take out of linear mode for Caller*ID processing */
10576                dahdi_setlinear(p->subs[idx].dfd, 0);
10577 
10578                /* First we wait and listen for the Caller*ID */
10579                for (;;) {
10580                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10581                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10582                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10583                      callerid_free(cs);
10584                      ast_hangup(chan);
10585                      goto quit;
10586                   }
10587                   if (i & DAHDI_IOMUX_SIGEVENT) {
10588                      res = dahdi_get_event(p->subs[idx].dfd);
10589                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10590                      if (res == DAHDI_EVENT_NOALARM) {
10591                         p->inalarm = 0;
10592                      }
10593 
10594                      if (p->cid_signalling == CID_SIG_V23_JP) {
10595                         if (res == DAHDI_EVENT_RINGBEGIN) {
10596                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10597                            usleep(1);
10598                         }
10599                      } else {
10600                         res = 0;
10601                         break;
10602                      }
10603                   } else if (i & DAHDI_IOMUX_READ) {
10604                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10605                      if (res < 0) {
10606                         if (errno != ELAST) {
10607                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10608                            callerid_free(cs);
10609                            ast_hangup(chan);
10610                            goto quit;
10611                         }
10612                         break;
10613                      }
10614                      samples += res;
10615 
10616                      if (p->cid_signalling == CID_SIG_V23_JP) {
10617                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10618                      } else {
10619                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10620                      }
10621                      if (res < 0) {
10622                         /*
10623                          * The previous diagnostic message output likely
10624                          * explains why it failed.
10625                          */
10626                         ast_log(LOG_WARNING,
10627                            "Failed to decode CallerID on channel '%s'\n",
10628                            chan->name);
10629                         break;
10630                      } else if (res)
10631                         break;
10632                      else if (samples > (8000 * 10))
10633                         break;
10634                   }
10635                }
10636                if (res == 1) {
10637                   callerid_get(cs, &name, &number, &flags);
10638                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10639                }
10640 
10641                if (p->cid_signalling == CID_SIG_V23_JP) {
10642                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10643                   usleep(1);
10644                }
10645 
10646                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10647                res = 4000;/* This is a typical OFF time between rings. */
10648                for (;;) {
10649                   struct ast_frame *f;
10650                   res = ast_waitfor(chan, res);
10651                   if (res <= 0) {
10652                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10653                         "Exiting simple switch\n");
10654                      ast_hangup(chan);
10655                      goto quit;
10656                   }
10657                   if (!(f = ast_read(chan))) {
10658                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10659                      ast_hangup(chan);
10660                      goto quit;
10661                   }
10662                   ast_frfree(f);
10663                   if (chan->_state == AST_STATE_RING ||
10664                      chan->_state == AST_STATE_RINGING)
10665                      break; /* Got ring */
10666                }
10667 
10668                /* We must have a ring by now, so, if configured, lets try to listen for
10669                 * distinctive ringing */
10670                if (p->usedistinctiveringdetection) {
10671                   len = 0;
10672                   distMatches = 0;
10673                   /* Clear the current ring data array so we don't have old data in it. */
10674                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10675                      curRingData[receivedRingT] = 0;
10676                   receivedRingT = 0;
10677                   counter = 0;
10678                   counter1 = 0;
10679                   /* Check to see if context is what it should be, if not set to be. */
10680                   if (strcmp(p->context,p->defcontext) != 0) {
10681                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10682                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10683                   }
10684 
10685                   for (;;) {
10686                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10687                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10688                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10689                         callerid_free(cs);
10690                         ast_hangup(chan);
10691                         goto quit;
10692                      }
10693                      if (i & DAHDI_IOMUX_SIGEVENT) {
10694                         res = dahdi_get_event(p->subs[idx].dfd);
10695                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10696                         if (res == DAHDI_EVENT_NOALARM) {
10697                            p->inalarm = 0;
10698                         }
10699                         res = 0;
10700                         /* Let us detect distinctive ring */
10701 
10702                         curRingData[receivedRingT] = p->ringt;
10703 
10704                         if (p->ringt < p->ringt_base/2)
10705                            break;
10706                         /* Increment the ringT counter so we can match it against
10707                            values in chan_dahdi.conf for distinctive ring */
10708                         if (++receivedRingT == ARRAY_LEN(curRingData))
10709                            break;
10710                      } else if (i & DAHDI_IOMUX_READ) {
10711                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10712                         if (res < 0) {
10713                            if (errno != ELAST) {
10714                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10715                               callerid_free(cs);
10716                               ast_hangup(chan);
10717                               goto quit;
10718                            }
10719                            break;
10720                         }
10721                         if (p->ringt > 0) {
10722                            if (!(--p->ringt)) {
10723                               res = -1;
10724                               break;
10725                            }
10726                         }
10727                      }
10728                   }
10729                      /* this only shows up if you have n of the dring patterns filled in */
10730                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10731                   for (counter = 0; counter < 3; counter++) {
10732                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10733                      channel */
10734                      distMatches = 0;
10735                      for (counter1 = 0; counter1 < 3; counter1++) {
10736                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10737                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10738                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10739                            curRingData[counter1]);
10740                            distMatches++;
10741                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10742                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10743                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10744                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10745                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10746                            distMatches++;
10747                         }
10748                      }
10749 
10750                      if (distMatches == 3) {
10751                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10752                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10753                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10754                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10755                         break;
10756                      }
10757                   }
10758                }
10759                /* Restore linear mode (if appropriate) for Caller*ID processing */
10760                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10761 #if 1
10762                restore_gains(p);
10763 #endif
10764             } else
10765                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10766          } else {
10767             ast_log(LOG_WARNING, "Channel %s in prering "
10768                "state, but I have nothing to do. "
10769                "Terminating simple switch, should be "
10770                "restarted by the actual ring.\n",
10771                chan->name);
10772             ast_hangup(chan);
10773             goto quit;
10774          }
10775       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10776          if (p->cid_signalling == CID_SIG_DTMF) {
10777             int k = 0;
10778             cs = NULL;
10779             dahdi_setlinear(p->subs[idx].dfd, 0);
10780             res = 2000;
10781             for (;;) {
10782                struct ast_frame *f;
10783                res = ast_waitfor(chan, res);
10784                if (res <= 0) {
10785                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10786                      "Exiting simple switch\n");
10787                   ast_hangup(chan);
10788                   goto quit;
10789                }
10790                f = ast_read(chan);
10791                if (!f) {
10792                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10793                   ast_hangup(chan);
10794                   goto quit;
10795                }
10796                if (f->frametype == AST_FRAME_DTMF) {
10797                   dtmfbuf[k++] = f->subclass.integer;
10798                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10799                   res = 2000;
10800                }
10801                ast_frfree(f);
10802 
10803                if (p->ringt_base == p->ringt)
10804                   break;
10805             }
10806             dtmfbuf[k] = '\0';
10807             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10808             /* Got cid and ring. */
10809             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10810             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10811                dtmfcid, flags);
10812             /* If first byte is NULL, we have no cid */
10813             if (!ast_strlen_zero(dtmfcid))
10814                number = dtmfcid;
10815             else
10816                number = NULL;
10817             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10818          } else {
10819             /* FSK Bell202 callerID */
10820             cs = callerid_new(p->cid_signalling);
10821             if (cs) {
10822 #if 1
10823                bump_gains(p);
10824 #endif
10825                samples = 0;
10826                len = 0;
10827                distMatches = 0;
10828                /* Clear the current ring data array so we don't have old data in it. */
10829                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10830                   curRingData[receivedRingT] = 0;
10831                receivedRingT = 0;
10832                counter = 0;
10833                counter1 = 0;
10834                /* Check to see if context is what it should be, if not set to be. */
10835                if (strcmp(p->context,p->defcontext) != 0) {
10836                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10837                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10838                }
10839 
10840                /* Take out of linear mode for Caller*ID processing */
10841                dahdi_setlinear(p->subs[idx].dfd, 0);
10842                for (;;) {
10843                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10844                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10845                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10846                      callerid_free(cs);
10847                      ast_hangup(chan);
10848                      goto quit;
10849                   }
10850                   if (i & DAHDI_IOMUX_SIGEVENT) {
10851                      res = dahdi_get_event(p->subs[idx].dfd);
10852                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10853                      if (res == DAHDI_EVENT_NOALARM) {
10854                         p->inalarm = 0;
10855                      }
10856                      /* If we get a PR event, they hung up while processing calerid */
10857                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10858                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10859                         p->polarity = POLARITY_IDLE;
10860                         callerid_free(cs);
10861                         ast_hangup(chan);
10862                         goto quit;
10863                      }
10864                      res = 0;
10865                      /* Let us detect callerid when the telco uses distinctive ring */
10866 
10867                      curRingData[receivedRingT] = p->ringt;
10868 
10869                      if (p->ringt < p->ringt_base/2)
10870                         break;
10871                      /* Increment the ringT counter so we can match it against
10872                         values in chan_dahdi.conf for distinctive ring */
10873                      if (++receivedRingT == ARRAY_LEN(curRingData))
10874                         break;
10875                   } else if (i & DAHDI_IOMUX_READ) {
10876                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10877                      if (res < 0) {
10878                         if (errno != ELAST) {
10879                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10880                            callerid_free(cs);
10881                            ast_hangup(chan);
10882                            goto quit;
10883                         }
10884                         break;
10885                      }
10886                      if (p->ringt > 0) {
10887                         if (!(--p->ringt)) {
10888                            res = -1;
10889                            break;
10890                         }
10891                      }
10892                      samples += res;
10893                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10894                      if (res < 0) {
10895                         /*
10896                          * The previous diagnostic message output likely
10897                          * explains why it failed.
10898                          */
10899                         ast_log(LOG_WARNING,
10900                            "Failed to decode CallerID on channel '%s'\n",
10901                            chan->name);
10902                         break;
10903                      } else if (res)
10904                         break;
10905                      else if (samples > (8000 * 10))
10906                         break;
10907                   }
10908                }
10909                if (res == 1) {
10910                   callerid_get(cs, &name, &number, &flags);
10911                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10912                }
10913                if (distinctiveringaftercid == 1) {
10914                   /* Clear the current ring data array so we don't have old data in it. */
10915                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10916                      curRingData[receivedRingT] = 0;
10917                   }
10918                   receivedRingT = 0;
10919                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10920                   for (;;) {
10921                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10922                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10923                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10924                         callerid_free(cs);
10925                         ast_hangup(chan);
10926                         goto quit;
10927                      }
10928                      if (i & DAHDI_IOMUX_SIGEVENT) {
10929                         res = dahdi_get_event(p->subs[idx].dfd);
10930                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10931                         if (res == DAHDI_EVENT_NOALARM) {
10932                            p->inalarm = 0;
10933                         }
10934                         res = 0;
10935                         /* Let us detect callerid when the telco uses distinctive ring */
10936 
10937                         curRingData[receivedRingT] = p->ringt;
10938 
10939                         if (p->ringt < p->ringt_base/2)
10940                            break;
10941                         /* Increment the ringT counter so we can match it against
10942                            values in chan_dahdi.conf for distinctive ring */
10943                         if (++receivedRingT == ARRAY_LEN(curRingData))
10944                            break;
10945                      } else if (i & DAHDI_IOMUX_READ) {
10946                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10947                         if (res < 0) {
10948                            if (errno != ELAST) {
10949                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10950                               callerid_free(cs);
10951                               ast_hangup(chan);
10952                               goto quit;
10953                            }
10954                            break;
10955                         }
10956                         if (p->ringt > 0) {
10957                            if (!(--p->ringt)) {
10958                               res = -1;
10959                               break;
10960                            }
10961                         }
10962                      }
10963                   }
10964                }
10965                if (p->usedistinctiveringdetection) {
10966                   /* this only shows up if you have n of the dring patterns filled in */
10967                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10968 
10969                   for (counter = 0; counter < 3; counter++) {
10970                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10971                      channel */
10972                      /* this only shows up if you have n of the dring patterns filled in */
10973                      ast_verb(3, "Checking %d,%d,%d\n",
10974                            p->drings.ringnum[counter].ring[0],
10975                            p->drings.ringnum[counter].ring[1],
10976                            p->drings.ringnum[counter].ring[2]);
10977                      distMatches = 0;
10978                      for (counter1 = 0; counter1 < 3; counter1++) {
10979                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10980                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10981                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10982                            curRingData[counter1]);
10983                            distMatches++;
10984                         }
10985                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10986                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10987                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10988                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10989                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10990                            distMatches++;
10991                         }
10992                      }
10993                      if (distMatches == 3) {
10994                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10995                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10996                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10997                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10998                         break;
10999                      }
11000                   }
11001                }
11002                /* Restore linear mode (if appropriate) for Caller*ID processing */
11003                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11004 #if 1
11005                restore_gains(p);
11006 #endif
11007                if (res < 0) {
11008                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11009                }
11010             } else
11011                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11012          }
11013       } else
11014          cs = NULL;
11015 
11016       if (number)
11017          ast_shrink_phone_number(number);
11018       ast_set_callerid(chan, number, name, number);
11019 
11020       if (smdi_msg)
11021          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11022 
11023       if (cs)
11024          callerid_free(cs);
11025 
11026       my_handle_notify_message(chan, p, flags, -1);
11027 
11028       ast_setstate(chan, AST_STATE_RING);
11029       chan->rings = 1;
11030       p->ringt = p->ringt_base;
11031       res = ast_pbx_run(chan);
11032       if (res) {
11033          ast_hangup(chan);
11034          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11035       }
11036       goto quit;
11037    default:
11038       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11039       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11040       if (res < 0)
11041             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11042    }
11043    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11044    if (res < 0)
11045          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11046    ast_hangup(chan);
11047 quit:
11048    ast_mutex_lock(&ss_thread_lock);
11049    ss_thread_count--;
11050    ast_cond_signal(&ss_thread_complete);
11051    ast_mutex_unlock(&ss_thread_lock);
11052    return NULL;
11053 }

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

01621 {
01622    switch (tone) {
01623    case ANALOG_TONE_RINGTONE:
01624       return DAHDI_TONE_RINGTONE;
01625    case ANALOG_TONE_STUTTER:
01626       return DAHDI_TONE_STUTTER;
01627    case ANALOG_TONE_CONGESTION:
01628       return DAHDI_TONE_CONGESTION;
01629    case ANALOG_TONE_DIALTONE:
01630       return DAHDI_TONE_DIALTONE;
01631    case ANALOG_TONE_DIALRECALL:
01632       return DAHDI_TONE_DIALRECALL;
01633    case ANALOG_TONE_INFO:
01634       return DAHDI_TONE_INFO;
01635    default:
01636       return -1;
01637    }
01638 }

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

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

01641 {
01642    int index;
01643 
01644    switch (analogsub) {
01645    case ANALOG_SUB_REAL:
01646       index = SUB_REAL;
01647       break;
01648    case ANALOG_SUB_CALLWAIT:
01649       index = SUB_CALLWAIT;
01650       break;
01651    case ANALOG_SUB_THREEWAY:
01652       index = SUB_THREEWAY;
01653       break;
01654    default:
01655       ast_log(LOG_ERROR, "Unidentified sub!\n");
01656       index = SUB_REAL;
01657    }
01658 
01659    return index;
01660 }

AST_DATA_STRUCTURE ( dahdi_pvt  ,
DATA_EXPORT_DAHDI_PVT   
)

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

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

07653 {
07654    /* In order to transfer, we need at least one of the channels to
07655       actually be in a call bridge.  We can't conference two applications
07656       together (but then, why would we want to?) */
07657    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07658       /* The three-way person we're about to transfer to could still be in MOH, so
07659          stop if now if appropriate */
07660       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07661          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07662       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07663          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07664       }
07665       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07666          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07667       }
07668        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07669          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07670                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07671          return -1;
07672       }
07673       /* Orphan the channel after releasing the lock */
07674       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07675       unalloc_sub(p, SUB_THREEWAY);
07676    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07677       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07678       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07679          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07680       }
07681       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07682          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07683       }
07684       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07685          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07686                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07687          return -1;
07688       }
07689       /* Three-way is now the REAL */
07690       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07691       ast_channel_unlock(p->subs[SUB_REAL].owner);
07692       unalloc_sub(p, SUB_THREEWAY);
07693       /* Tell the caller not to hangup */
07694       return 1;
07695    } else {
07696       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07697          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07698       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07699       return -1;
07700    }
07701    return 0;
07702 }

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

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

13215 {
13216    struct dahdi_pvt *p = *pvt;
13217 
13218    if (p->inalarm)
13219       return 0;
13220 
13221    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13222       return analog_available(p->sig_pvt);
13223 
13224    switch (p->sig) {
13225 #if defined(HAVE_PRI)
13226    case SIG_PRI_LIB_HANDLE_CASES:
13227       {
13228          struct sig_pri_chan *pvt_chan;
13229          int res;
13230 
13231          pvt_chan = p->sig_pvt;
13232          res = sig_pri_available(&pvt_chan, is_specific_channel);
13233          *pvt = pvt_chan->chan_pvt;
13234          return res;
13235       }
13236 #endif   /* defined(HAVE_PRI) */
13237 #if defined(HAVE_SS7)
13238    case SIG_SS7:
13239       return sig_ss7_available(p->sig_pvt);
13240 #endif   /* defined(HAVE_SS7) */
13241    default:
13242       break;
13243    }
13244 
13245    if (p->locallyblocked || p->remotelyblocked) {
13246       return 0;
13247    }
13248 
13249    /* If no owner definitely available */
13250    if (!p->owner) {
13251 #ifdef HAVE_OPENR2
13252       /* Trust MFC/R2 */
13253       if (p->mfcr2) {
13254          if (p->mfcr2call) {
13255             return 0;
13256          } else {
13257             return 1;
13258          }
13259       }
13260 #endif
13261       return 1;
13262    }
13263 
13264    return 0;
13265 }

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

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

16831 {
16832    char *c, *chan;
16833    char *subdir;
16834    int x, start, finish;
16835    struct dahdi_pvt *tmp;
16836 
16837    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16838       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16839       return -1;
16840    }
16841 
16842    c = ast_strdupa(value);
16843    c = parse_spanchan(c, &subdir);
16844 
16845    while ((chan = strsep(&c, ","))) {
16846       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16847          /* Range */
16848       } else if (sscanf(chan, "%30d", &start)) {
16849          /* Just one */
16850          finish = start;
16851       } else if (!strcasecmp(chan, "pseudo")) {
16852          finish = start = CHAN_PSEUDO;
16853          if (found_pseudo)
16854             *found_pseudo = 1;
16855       } else {
16856          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16857          return -1;
16858       }
16859       if (finish < start) {
16860          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16861          x = finish;
16862          finish = start;
16863          start = x;
16864       }
16865 
16866       for (x = start; x <= finish; x++) {
16867          char fn[PATH_MAX];
16868          int real_channel = x;
16869 
16870          if (!ast_strlen_zero(subdir)) {
16871             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16872             if (real_channel < 0) {
16873                if (conf->ignore_failed_channels) {
16874                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16875                         subdir, x, real_channel);
16876                   continue;
16877                } else {
16878                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16879                         subdir, x, real_channel);
16880                   return -1;
16881                }
16882             }
16883          }
16884          tmp = mkintf(real_channel, conf, reload);
16885 
16886          if (tmp) {
16887             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16888          } else {
16889             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16890                   (reload == 1) ? "reconfigure" : "register", value);
16891             return -1;
16892          }
16893       }
16894    }
16895 
16896    return 0;
16897 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

05135 {
05136    int res;
05137 
05138    /* Bump receive gain by value stored in cid_rxgain */
05139    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05140    if (res) {
05141       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05142       return -1;
05143    }
05144 
05145    return 0;
05146 }

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

Definition at line 11061 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by mwi_thread().

11062 {
11063    int x;
11064    int sum = 0;
11065 
11066    if (!len)
11067       return 0;
11068 
11069    for (x = 0; x < len; x++)
11070       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11071 
11072    return sum / len;
11073 }

static int canmatch_featurecode ( const char *  exten  )  [static]

Definition at line 9900 of file chan_dahdi.c.

References ast_pickup_ext(), and pickup_ext.

Referenced by analog_ss_thread().

09901 {
09902    int extlen = strlen(exten);
09903    const char *pickup_ext;
09904    if (!extlen) {
09905       return 1;
09906    }
09907    pickup_ext = ast_pickup_ext();
09908    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09909       return 1;
09910    }
09911    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09912    if (exten[0] == '*' && extlen < 3) {
09913       if (extlen == 1) {
09914          return 1;
09915       }
09916       /* "*0" should be processed before it gets here */
09917       switch (exten[1]) {
09918       case '6':
09919       case '7':
09920       case '8':
09921          return 1;
09922       }
09923    }
09924    return 0;
09925 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

07705 {
07706    struct dahdi_confinfo ci;
07707    /* Fine if we already have a master, etc */
07708    if (p->master || (p->confno > -1))
07709       return 0;
07710    memset(&ci, 0, sizeof(ci));
07711    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07712       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07713       return 0;
07714    }
07715    /* If we have no master and don't have a confno, then
07716       if we're in a conference, it's probably a MeetMe room or
07717       some such, so don't let us 3-way out! */
07718    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07719       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07720       return 1;
07721    }
07722    return 0;
07723 }

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

Definition at line 14266 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

14267 {
14268    return complete_span_helper(line,word,pos,state,3);
14269 }

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

Definition at line 14245 of file chan_dahdi.c.

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

Referenced by complete_span_4().

14246 {
14247    int which, span;
14248    char *ret = NULL;
14249 
14250    if (pos != rpos)
14251       return ret;
14252 
14253    for (which = span = 0; span < NUM_SPANS; span++) {
14254       if (pris[span].pri.pri && ++which > state) {
14255          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14256             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14257          }
14258          break;
14259       }
14260    }
14261    return ret;
14262 }

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

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

04717 {
04718    /* If the conference already exists, and we're already in it
04719       don't bother doing anything */
04720    struct dahdi_confinfo zi;
04721 
04722    memset(&zi, 0, sizeof(zi));
04723    zi.chan = 0;
04724 
04725    if (slavechannel > 0) {
04726       /* If we have only one slave, do a digital mon */
04727       zi.confmode = DAHDI_CONF_DIGITALMON;
04728       zi.confno = slavechannel;
04729    } else {
04730       if (!idx) {
04731          /* Real-side and pseudo-side both participate in conference */
04732          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04733             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04734       } else
04735          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04736       zi.confno = p->confno;
04737    }
04738    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04739       return 0;
04740    if (c->dfd < 0)
04741       return 0;
04742    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04743       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04744       return -1;
04745    }
04746    if (slavechannel < 1) {
04747       p->confno = zi.confno;
04748    }
04749    c->curconf = zi;
04750    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04751    return 0;
04752 }

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

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

04766 {
04767    struct dahdi_confinfo zi;
04768    if (/* Can't delete if there's no dfd */
04769       (c->dfd < 0) ||
04770       /* Don't delete from the conference if it's not our conference */
04771       !isourconf(p, c)
04772       /* Don't delete if we don't think it's conferenced at all (implied) */
04773       ) return 0;
04774    memset(&zi, 0, sizeof(zi));
04775    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04776       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04777       return -1;
04778    }
04779    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04780    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04781    return 0;
04782 }

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

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

09563 {
09564    struct ast_str *chan_name;
09565    int x, y;
09566 
09567    /* Create the new channel name tail. */
09568    if (!(chan_name = ast_str_create(32))) {
09569       return NULL;
09570    }
09571    if (i->channel == CHAN_PSEUDO) {
09572       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09573 #if defined(HAVE_PRI)
09574    } else if (i->pri) {
09575       ast_mutex_lock(&i->pri->lock);
09576       y = ++i->pri->new_chan_seq;
09577       if (is_outgoing) {
09578          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09579          address[0] = '\0';
09580       } else if (ast_strlen_zero(i->cid_subaddr)) {
09581          /* Put in caller-id number only since there is no subaddress. */
09582          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09583       } else {
09584          /* Put in caller-id number and subaddress. */
09585          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09586             i->cid_subaddr, y);
09587       }
09588       ast_mutex_unlock(&i->pri->lock);
09589 #endif   /* defined(HAVE_PRI) */
09590    } else {
09591       y = 1;
09592       do {
09593          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09594          for (x = 0; x < 3; ++x) {
09595             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09596                i->subs[x].owner->name + 6)) {
09597                break;
09598             }
09599          }
09600          ++y;
09601       } while (x < 3);
09602    }
09603    return chan_name;
09604 }

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

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

05999 {
06000    /* data is whether to accept with charge or no charge */
06001    openr2_call_mode_t accept_mode;
06002    int res, timeout, maxloops;
06003    struct ast_frame *f;
06004    struct dahdi_pvt *p;
06005    char *parse;
06006    AST_DECLARE_APP_ARGS(args,
06007          AST_APP_ARG(charge);
06008    );
06009 
06010    if (ast_strlen_zero(data)) {
06011       ast_log(LOG_DEBUG, "No data sent to application!\n");
06012       return -1;
06013    }
06014 
06015    if (chan->tech != &dahdi_tech) {
06016       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06017       return -1;
06018    }
06019 
06020    p = (struct dahdi_pvt *)chan->tech_pvt;
06021    if (!p) {
06022       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06023       return -1;
06024    }
06025 
06026    parse = ast_strdupa(data);
06027    AST_STANDARD_APP_ARGS(args, parse);
06028 
06029    if (ast_strlen_zero(args.charge)) {
06030       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06031       return -1;
06032    }
06033 
06034    ast_mutex_lock(&p->lock);
06035    if (!p->mfcr2 || !p->mfcr2call) {
06036       ast_mutex_unlock(&p->lock);
06037       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06038       return -1;
06039    }
06040 
06041    if (p->mfcr2_call_accepted) {
06042       ast_mutex_unlock(&p->lock);
06043       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06044       return 0;
06045    }
06046    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06047    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06048       ast_mutex_unlock(&p->lock);
06049       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06050       return -1;
06051    }
06052    ast_mutex_unlock(&p->lock);
06053 
06054    res = 0;
06055    timeout = 100;
06056    maxloops = 50; /* wait up to 5 seconds */
06057    /* we need to read() until the call is accepted */
06058    while (maxloops > 0) {
06059       maxloops--;
06060       if (ast_check_hangup(chan)) {
06061          break;
06062       }
06063       res = ast_waitfor(chan, timeout);
06064       if (res < 0) {
06065          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06066          res = -1;
06067          break;
06068       }
06069       if (res == 0) {
06070          continue;
06071       }
06072       f = ast_read(chan);
06073       if (!f) {
06074          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06075          res = -1;
06076          break;
06077       }
06078       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06079          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06080          ast_frfree(f);
06081          res = -1;
06082          break;
06083       }
06084       ast_frfree(f);
06085       ast_mutex_lock(&p->lock);
06086       if (p->mfcr2_call_accepted) {
06087          ast_mutex_unlock(&p->lock);
06088          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06089          break;
06090       }
06091       ast_mutex_unlock(&p->lock);
06092    }
06093    if (res == -1) {
06094       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06095    }
06096    return res;
06097 }

static void dahdi_ami_channel_event ( struct dahdi_pvt p,
struct ast_channel chan 
) [static]

Definition at line 2139 of file chan_dahdi.c.

References ast_manager_event, CHAN_PSEUDO, dahdi_pvt::channel, EVENT_FLAG_CALL, ast_channel::name, dahdi_pvt::span, and ast_channel::uniqueid.

Referenced by dahdi_new(), and my_ami_channel_event().

02140 {
02141    char ch_name[20];
02142 
02143    if (p->channel < CHAN_PSEUDO) {
02144       /* No B channel */
02145       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02146    } else if (p->channel == CHAN_PSEUDO) {
02147       /* Pseudo channel */
02148       strcpy(ch_name, "pseudo");
02149    } else {
02150       /* Real channel */
02151       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02152    }
02153    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02154       "Channel: %s\r\n"
02155       "Uniqueid: %s\r\n"
02156       "DAHDISpan: %d\r\n"
02157       "DAHDIChannel: %s\r\n",
02158       chan->name,
02159       chan->uniqueid,
02160       p->span,
02161       ch_name);
02162 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

06583 {
06584    struct dahdi_pvt *p = ast->tech_pvt;
06585    int res = 0;
06586    int idx;
06587    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06588    ast_mutex_lock(&p->lock);
06589    idx = dahdi_get_index(ast, p, 0);
06590    if (idx < 0)
06591       idx = SUB_REAL;
06592    /* nothing to do if a radio channel */
06593    if ((p->radio || (p->oprmode < 0))) {
06594       ast_mutex_unlock(&p->lock);
06595       return 0;
06596    }
06597 
06598    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06599       res = analog_answer(p->sig_pvt, ast);
06600       ast_mutex_unlock(&p->lock);
06601       return res;
06602    }
06603 
06604    switch (p->sig) {
06605 #if defined(HAVE_PRI)
06606    case SIG_PRI_LIB_HANDLE_CASES:
06607       res = sig_pri_answer(p->sig_pvt, ast);
06608       break;
06609 #endif   /* defined(HAVE_PRI) */
06610 #if defined(HAVE_SS7)
06611    case SIG_SS7:
06612       res = sig_ss7_answer(p->sig_pvt, ast);
06613       break;
06614 #endif   /* defined(HAVE_SS7) */
06615 #ifdef HAVE_OPENR2
06616    case SIG_MFCR2:
06617       if (!p->mfcr2_call_accepted) {
06618          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06619             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06620          p->mfcr2_answer_pending = 1;
06621          if (p->mfcr2_charge_calls) {
06622             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06623             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06624          } else {
06625             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06626             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06627          }
06628       } else {
06629          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06630          dahdi_r2_answer(p);
06631       }
06632       break;
06633 #endif
06634    case 0:
06635       ast_mutex_unlock(&p->lock);
06636       return 0;
06637    default:
06638       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06639       res = -1;
06640       break;
06641    }
06642    ast_mutex_unlock(&p->lock);
06643    return res;
06644 }

static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause ( int  cause  )  [static]

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

06100 {
06101    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06102    switch (cause) {
06103    case AST_CAUSE_USER_BUSY:
06104    case AST_CAUSE_CALL_REJECTED:
06105    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06106       r2cause = OR2_CAUSE_BUSY_NUMBER;
06107       break;
06108 
06109    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06110    case AST_CAUSE_SWITCH_CONGESTION:
06111       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06112       break;
06113 
06114    case AST_CAUSE_UNALLOCATED:
06115       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06116       break;
06117 
06118    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06119    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06120       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06121       break;
06122 
06123    case AST_CAUSE_NO_ANSWER:
06124    case AST_CAUSE_NO_USER_RESPONSE:
06125       r2cause = OR2_CAUSE_NO_ANSWER;
06126       break;
06127 
06128    default:
06129       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06130       break;
06131    }
06132    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06133          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06134    return r2cause;
06135 }

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

07230 {
07231    struct ast_channel *who;
07232    struct dahdi_pvt *p0, *p1, *op0, *op1;
07233    struct dahdi_pvt *master = NULL, *slave = NULL;
07234    struct ast_frame *f;
07235    int inconf = 0;
07236    int nothingok = 1;
07237    int ofd0, ofd1;
07238    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07239    int os0 = -1, os1 = -1;
07240    int priority = 0;
07241    struct ast_channel *oc0, *oc1;
07242    enum ast_bridge_result res;
07243 #ifdef PRI_2BCT
07244    int triedtopribridge = 0;
07245    q931_call *q931c0;
07246    q931_call *q931c1;
07247 #endif
07248 
07249    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07250       There is code below to handle it properly until DTMF is actually seen,
07251       but due to currently unresolved issues it's ignored...
07252    */
07253 
07254    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07255       return AST_BRIDGE_FAILED_NOWARN;
07256 
07257    ast_channel_lock(c0);
07258    while (ast_channel_trylock(c1)) {
07259       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07260    }
07261 
07262    p0 = c0->tech_pvt;
07263    p1 = c1->tech_pvt;
07264    /* cant do pseudo-channels here */
07265    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07266       ast_channel_unlock(c0);
07267       ast_channel_unlock(c1);
07268       return AST_BRIDGE_FAILED_NOWARN;
07269    }
07270 
07271    oi0 = dahdi_get_index(c0, p0, 0);
07272    oi1 = dahdi_get_index(c1, p1, 0);
07273    if ((oi0 < 0) || (oi1 < 0)) {
07274       ast_channel_unlock(c0);
07275       ast_channel_unlock(c1);
07276       return AST_BRIDGE_FAILED;
07277    }
07278 
07279    op0 = p0 = c0->tech_pvt;
07280    op1 = p1 = c1->tech_pvt;
07281    ofd0 = c0->fds[0];
07282    ofd1 = c1->fds[0];
07283    oc0 = p0->owner;
07284    oc1 = p1->owner;
07285 
07286    if (ast_mutex_trylock(&p0->lock)) {
07287       /* Don't block, due to potential for deadlock */
07288       ast_channel_unlock(c0);
07289       ast_channel_unlock(c1);
07290       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07291       return AST_BRIDGE_RETRY;
07292    }
07293    if (ast_mutex_trylock(&p1->lock)) {
07294       /* Don't block, due to potential for deadlock */
07295       ast_mutex_unlock(&p0->lock);
07296       ast_channel_unlock(c0);
07297       ast_channel_unlock(c1);
07298       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07299       return AST_BRIDGE_RETRY;
07300    }
07301 
07302    if ((p0->callwaiting && p0->callwaitingcallerid)
07303       || (p1->callwaiting && p1->callwaitingcallerid)) {
07304       /*
07305        * Call Waiting Caller ID requires DTMF detection to know if it
07306        * can send the CID spill.
07307        *
07308        * For now, don't attempt to native bridge if either channel
07309        * needs DTMF detection.  There is code below to handle it
07310        * properly until DTMF is actually seen, but due to currently
07311        * unresolved issues it's ignored...
07312        */
07313       ast_mutex_unlock(&p0->lock);
07314       ast_mutex_unlock(&p1->lock);
07315       ast_channel_unlock(c0);
07316       ast_channel_unlock(c1);
07317       return AST_BRIDGE_FAILED_NOWARN;
07318    }
07319 
07320 #if defined(HAVE_PRI)
07321    if ((dahdi_sig_pri_lib_handles(p0->sig)
07322          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07323       || (dahdi_sig_pri_lib_handles(p1->sig)
07324          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07325       /*
07326        * PRI nobch channels (hold and call waiting) are equivalent to
07327        * pseudo channels and cannot be done here.
07328        */
07329       ast_mutex_unlock(&p0->lock);
07330       ast_mutex_unlock(&p1->lock);
07331       ast_channel_unlock(c0);
07332       ast_channel_unlock(c1);
07333       return AST_BRIDGE_FAILED_NOWARN;
07334    }
07335 #endif   /* defined(HAVE_PRI) */
07336 
07337    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07338       if (p0->owner && p1->owner) {
07339          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07340          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07341             master = p0;
07342             slave = p1;
07343             inconf = 1;
07344          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07345             master = p1;
07346             slave = p0;
07347             inconf = 1;
07348          } else {
07349             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07350             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07351                p0->channel,
07352                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07353                p0->subs[SUB_REAL].inthreeway, p0->channel,
07354                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07355                p1->subs[SUB_REAL].inthreeway);
07356          }
07357          nothingok = 0;
07358       }
07359    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07360       if (p1->subs[SUB_THREEWAY].inthreeway) {
07361          master = p1;
07362          slave = p0;
07363          nothingok = 0;
07364       }
07365    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07366       if (p0->subs[SUB_THREEWAY].inthreeway) {
07367          master = p0;
07368          slave = p1;
07369          nothingok = 0;
07370       }
07371    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07372       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07373          don't put us in anything */
07374       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07375          master = p1;
07376          slave = p0;
07377          nothingok = 0;
07378       }
07379    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07380       /* Same as previous */
07381       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07382          master = p0;
07383          slave = p1;
07384          nothingok = 0;
07385       }
07386    }
07387    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07388       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07389    if (master && slave) {
07390       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07391          in an active threeway call with a channel that is ringing, we should
07392          indicate ringing. */
07393       if ((oi1 == SUB_THREEWAY) &&
07394          p1->subs[SUB_THREEWAY].inthreeway &&
07395          p1->subs[SUB_REAL].owner &&
07396          p1->subs[SUB_REAL].inthreeway &&
07397          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07398          ast_debug(1,
07399             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07400             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07401          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07402          os1 = p1->subs[SUB_REAL].owner->_state;
07403       } else {
07404          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07405             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07406          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07407       }
07408       if ((oi0 == SUB_THREEWAY) &&
07409          p0->subs[SUB_THREEWAY].inthreeway &&
07410          p0->subs[SUB_REAL].owner &&
07411          p0->subs[SUB_REAL].inthreeway &&
07412          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07413          ast_debug(1,
07414             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07415             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07416          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07417          os0 = p0->subs[SUB_REAL].owner->_state;
07418       } else {
07419          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07420             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07421          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07422       }
07423       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07424          if (!p0->echocanbridged || !p1->echocanbridged) {
07425             /* Disable echo cancellation if appropriate */
07426             dahdi_disable_ec(p0);
07427             dahdi_disable_ec(p1);
07428          }
07429       }
07430       dahdi_link(slave, master);
07431       master->inconference = inconf;
07432    } else if (!nothingok)
07433       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07434 
07435    update_conf(p0);
07436    update_conf(p1);
07437    t0 = p0->subs[SUB_REAL].inthreeway;
07438    t1 = p1->subs[SUB_REAL].inthreeway;
07439 
07440    ast_mutex_unlock(&p0->lock);
07441    ast_mutex_unlock(&p1->lock);
07442 
07443    ast_channel_unlock(c0);
07444    ast_channel_unlock(c1);
07445 
07446    /* Native bridge failed */
07447    if ((!master || !slave) && !nothingok) {
07448       dahdi_enable_ec(p0);
07449       dahdi_enable_ec(p1);
07450       return AST_BRIDGE_FAILED;
07451    }
07452 
07453    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07454 
07455    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07456       disable_dtmf_detect(op0);
07457 
07458    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07459       disable_dtmf_detect(op1);
07460 
07461    for (;;) {
07462       struct ast_channel *c0_priority[2] = {c0, c1};
07463       struct ast_channel *c1_priority[2] = {c1, c0};
07464 
07465       /* Here's our main loop...  Start by locking things, looking for private parts,
07466          and then balking if anything is wrong */
07467 
07468       ast_channel_lock(c0);
07469       while (ast_channel_trylock(c1)) {
07470          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07471       }
07472 
07473       p0 = c0->tech_pvt;
07474       p1 = c1->tech_pvt;
07475 
07476       if (op0 == p0)
07477          i0 = dahdi_get_index(c0, p0, 1);
07478       if (op1 == p1)
07479          i1 = dahdi_get_index(c1, p1, 1);
07480 
07481       ast_channel_unlock(c0);
07482       ast_channel_unlock(c1);
07483 
07484       if (!timeoutms ||
07485          (op0 != p0) ||
07486          (op1 != p1) ||
07487          (ofd0 != c0->fds[0]) ||
07488          (ofd1 != c1->fds[0]) ||
07489          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07490          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07491          (oc0 != p0->owner) ||
07492          (oc1 != p1->owner) ||
07493          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07494          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07495          (oi0 != i0) ||
07496          (oi1 != i1)) {
07497          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07498             op0->channel, oi0, op1->channel, oi1);
07499          res = AST_BRIDGE_RETRY;
07500          goto return_from_bridge;
07501       }
07502 
07503 #ifdef PRI_2BCT
07504       if (!triedtopribridge) {
07505          triedtopribridge = 1;
07506          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07507             ast_mutex_lock(&p0->pri->lock);
07508             switch (p0->sig) {
07509             case SIG_PRI_LIB_HANDLE_CASES:
07510                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07511                break;
07512             default:
07513                q931c0 = NULL;
07514                break;
07515             }
07516             switch (p1->sig) {
07517             case SIG_PRI_LIB_HANDLE_CASES:
07518                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07519                break;
07520             default:
07521                q931c1 = NULL;
07522                break;
07523             }
07524             if (q931c0 && q931c1) {
07525                pri_channel_bridge(q931c0, q931c1);
07526             }
07527             ast_mutex_unlock(&p0->pri->lock);
07528          }
07529       }
07530 #endif
07531 
07532       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07533       if (!who) {
07534          ast_debug(1, "Ooh, empty read...\n");
07535          continue;
07536       }
07537       f = ast_read(who);
07538       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07539          *fo = f;
07540          *rc = who;
07541          res = AST_BRIDGE_COMPLETE;
07542          goto return_from_bridge;
07543       }
07544       if (f->frametype == AST_FRAME_DTMF) {
07545          if ((who == c0) && p0->pulsedial) {
07546             ast_write(c1, f);
07547          } else if ((who == c1) && p1->pulsedial) {
07548             ast_write(c0, f);
07549          } else {
07550             *fo = f;
07551             *rc = who;
07552             res = AST_BRIDGE_COMPLETE;
07553             goto return_from_bridge;
07554          }
07555       }
07556       ast_frfree(f);
07557 
07558       /* Swap who gets priority */
07559       priority = !priority;
07560    }
07561 
07562 return_from_bridge:
07563    if (op0 == p0)
07564       dahdi_enable_ec(p0);
07565 
07566    if (op1 == p1)
07567       dahdi_enable_ec(p1);
07568 
07569    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07570       enable_dtmf_detect(op0);
07571 
07572    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07573       enable_dtmf_detect(op1);
07574 
07575    dahdi_unlink(slave, master, 1);
07576 
07577    return res;
07578 }

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

Definition at line 5368 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, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::connected, 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_connected_line::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.

05369 {
05370    struct dahdi_pvt *p = ast->tech_pvt;
05371    int x, res, mysig;
05372    char dest[256]; /* must be same length as p->dialdest */
05373 
05374    ast_mutex_lock(&p->lock);
05375    ast_copy_string(dest, rdest, sizeof(dest));
05376    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05377    if ((ast->_state == AST_STATE_BUSY)) {
05378       p->subs[SUB_REAL].needbusy = 1;
05379       ast_mutex_unlock(&p->lock);
05380       return 0;
05381    }
05382    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05383       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05384       ast_mutex_unlock(&p->lock);
05385       return -1;
05386    }
05387    p->waitingfordt.tv_sec = 0;
05388    p->dialednone = 0;
05389    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05390    {
05391       /* Special pseudo -- automatically up */
05392       ast_setstate(ast, AST_STATE_UP);
05393       ast_mutex_unlock(&p->lock);
05394       return 0;
05395    }
05396    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05397    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05398    if (res)
05399       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05400    p->outgoing = 1;
05401 
05402    if (IS_DIGITAL(ast->transfercapability)){
05403       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05404    } else {
05405       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05406    }  
05407 
05408 #ifdef HAVE_PRI
05409    if (dahdi_sig_pri_lib_handles(p->sig)) {
05410       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05411          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05412       ast_mutex_unlock(&p->lock);
05413       return res;
05414    }
05415 #endif
05416 
05417 #if defined(HAVE_SS7)
05418    if (p->sig == SIG_SS7) {
05419       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05420       ast_mutex_unlock(&p->lock);
05421       return res;
05422    }
05423 #endif   /* defined(HAVE_SS7) */
05424 
05425    /* If this is analog signalling we can exit here */
05426    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05427       p->callwaitrings = 0;
05428       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05429       ast_mutex_unlock(&p->lock);
05430       return res;
05431    }
05432 
05433    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05434    switch (mysig) {
05435    case 0:
05436       /* Special pseudo -- automatically up*/
05437       ast_setstate(ast, AST_STATE_UP);
05438       break;
05439    case SIG_MFCR2:
05440       break;
05441    default:
05442       ast_debug(1, "not yet implemented\n");
05443       ast_mutex_unlock(&p->lock);
05444       return -1;
05445    }
05446 
05447 #ifdef HAVE_OPENR2
05448    if (p->mfcr2) {
05449       openr2_calling_party_category_t chancat;
05450       int callres = 0;
05451       char *c, *l;
05452 
05453       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05454       p->dialdest[0] = '\0';
05455 
05456       c = strchr(dest, '/');
05457       if (c) {
05458          c++;
05459       } else {
05460          c = "";
05461       }
05462       if (!p->hidecallerid) {
05463          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05464       } else {
05465          l = NULL;
05466       }
05467       if (strlen(c) < p->stripmsd) {
05468          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05469          ast_mutex_unlock(&p->lock);
05470          return -1;
05471       }
05472       p->dialing = 1;
05473       chancat = dahdi_r2_get_channel_category(ast);
05474       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05475       if (-1 == callres) {
05476          ast_mutex_unlock(&p->lock);
05477          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05478          return -1;
05479       }
05480       p->mfcr2_call_accepted = 0;
05481       p->mfcr2_progress = 0;
05482       ast_setstate(ast, AST_STATE_DIALING);
05483    }
05484 #endif /* HAVE_OPENR2 */
05485    ast_mutex_unlock(&p->lock);
05486    return 0;
05487 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

05336 {
05337    struct dahdi_pvt *p = ast->tech_pvt;
05338    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05339    if (p->cidspill) {
05340       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05341       ast_free(p->cidspill);
05342    }
05343 
05344    /*
05345     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05346     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05347     */
05348    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05349       return -1;
05350    save_conference(p);
05351    /* Silence */
05352    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05353    if (!p->callwaitrings && p->callwaitingcallerid) {
05354       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05355       p->callwaitcas = 1;
05356       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05357    } else {
05358       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05359       p->callwaitcas = 0;
05360       p->cidlen = 2400 + READ_SIZE * 4;
05361    }
05362    p->cidpos = 0;
05363    send_callerid(p);
05364 
05365    return 0;
05366 }

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

13880 {
13881    struct dahdi_pvt *p;
13882    struct dahdi_pvt *exitpvt;
13883    struct dahdi_starting_point start;
13884    int groupmatched = 0;
13885    int channelmatched = 0;
13886 
13887    ast_mutex_lock(&iflock);
13888    p = determine_starting_point(dest, &start);
13889    if (!p) {
13890       ast_mutex_unlock(&iflock);
13891       return -1;
13892    }
13893    exitpvt = p;
13894    for (;;) {
13895       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13896          /* We found a potential match. call the callback */
13897          struct ast_str *device_name;
13898          char *dash;
13899          const char *monitor_type;
13900          char dialstring[AST_CHANNEL_NAME];
13901          char full_device_name[AST_CHANNEL_NAME];
13902 
13903          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13904          case AST_CC_MONITOR_NEVER:
13905             break;
13906          case AST_CC_MONITOR_NATIVE:
13907          case AST_CC_MONITOR_ALWAYS:
13908          case AST_CC_MONITOR_GENERIC:
13909 #if defined(HAVE_PRI)
13910             if (dahdi_sig_pri_lib_handles(p->sig)) {
13911                /*
13912                 * ISDN is in a trunk busy condition so we need to monitor
13913                 * the span congestion device state.
13914                 */
13915                snprintf(full_device_name, sizeof(full_device_name),
13916                   "DAHDI/I%d/congestion", p->pri->span);
13917             } else
13918 #endif   /* defined(HAVE_PRI) */
13919             {
13920 #if defined(HAVE_PRI)
13921                device_name = create_channel_name(p, 1, "");
13922 #else
13923                device_name = create_channel_name(p);
13924 #endif   /* defined(HAVE_PRI) */
13925                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13926                   device_name ? ast_str_buffer(device_name) : "");
13927                ast_free(device_name);
13928                /*
13929                 * The portion after the '-' in the channel name is either a random
13930                 * number, a sequence number, or a subchannel number. None are
13931                 * necessary so strip them off.
13932                 */
13933                dash = strrchr(full_device_name, '-');
13934                if (dash) {
13935                   *dash = '\0';
13936                }
13937             }
13938             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13939 
13940             /*
13941              * Analog can only do generic monitoring.
13942              * ISDN is in a trunk busy condition and any "device" is going
13943              * to be busy until a B channel becomes available.  The generic
13944              * monitor can do this task.
13945              */
13946             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13947             callback(inbound,
13948 #if defined(HAVE_PRI)
13949                p->pri ? p->pri->cc_params : p->cc_params,
13950 #else
13951                p->cc_params,
13952 #endif   /* defined(HAVE_PRI) */
13953                monitor_type, full_device_name, dialstring, NULL);
13954             break;
13955          }
13956       }
13957       p = start.backwards ? p->prev : p->next;
13958       if (!p) {
13959          p = start.backwards ? ifend : iflist;
13960       }
13961       if (p == exitpvt) {
13962          break;
13963       }
13964    }
13965    ast_mutex_unlock(&iflock);
13966    return 0;
13967 }

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

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

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

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

18492 {
18493    struct dahdi_pvt *tmp;
18494    struct ast_data *data_channel;
18495 
18496    ast_mutex_lock(&iflock);
18497    for (tmp = iflist; tmp; tmp = tmp->next) {
18498       data_channel = ast_data_add_node(data_root, "channel");
18499       if (!data_channel) {
18500          continue;
18501       }
18502 
18503       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18504 
18505       /* if this channel doesn't match remove it. */
18506       if (!ast_data_search_match(search, data_channel)) {
18507          ast_data_remove_node(data_root, data_channel);
18508       }
18509    }
18510    ast_mutex_unlock(&iflock);
18511 
18512    return 0;
18513 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4359 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().

04360 {
04361    if (fd > 0)
04362       close(fd);
04363 }

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

Definition at line 4372 of file chan_dahdi.c.

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

Referenced by __unload_module(), and prepare_pri().

04373 {
04374    dahdi_close(pri->pri.fds[fd_num]);
04375    pri->pri.fds[fd_num] = -1;
04376 }

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

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

04366 {
04367    dahdi_close(chan_pvt->subs[sub_num].dfd);
04368    chan_pvt->subs[sub_num].dfd = -1;
04369 }

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

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

05179 {
05180    int x, res;
05181 
05182    x = muted;
05183 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05184    switch (p->sig) {
05185 #if defined(HAVE_PRI)
05186    case SIG_PRI_LIB_HANDLE_CASES:
05187       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05188          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05189          break;
05190       }
05191       /* Fall through */
05192 #endif   /* defined(HAVE_PRI) */
05193 #if defined(HAVE_SS7)
05194    case SIG_SS7:
05195 #endif   /* defined(HAVE_SS7) */
05196       {
05197          int y = 1;
05198 
05199          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05200          if (res)
05201             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05202                p->channel, strerror(errno));
05203       }
05204       break;
05205    default:
05206       break;
05207    }
05208 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05209    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05210    if (res < 0)
05211       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05212    return res;
05213 }

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

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

15031 {
15032    int channel;
15033    int ret;
15034    switch (cmd) {
15035    case CLI_INIT:
15036       e->command = "dahdi destroy channel";
15037       e->usage =
15038          "Usage: dahdi destroy channel <chan num>\n"
15039          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15040       return NULL;
15041    case CLI_GENERATE:
15042       return NULL;
15043    }
15044    if (a->argc != 4)
15045       return CLI_SHOWUSAGE;
15046 
15047    channel = atoi(a->argv[3]);
15048    ret = dahdi_destroy_channel_bynum(channel);
15049    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15050 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

11412 {
11413    struct dahdi_pvt *cur;
11414 
11415    ast_mutex_lock(&iflock);
11416    for (cur = iflist; cur; cur = cur->next) {
11417       if (cur->channel == channel) {
11418          int x = DAHDI_FLASH;
11419 
11420          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11421          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11422 
11423          destroy_channel(cur, 1);
11424          ast_mutex_unlock(&iflock);
11425          ast_module_unref(ast_module_info->self);
11426          return RESULT_SUCCESS;
11427       }
11428    }
11429    ast_mutex_unlock(&iflock);
11430    return RESULT_FAILURE;
11431 }

static int dahdi_devicestate ( void *  data  )  [static]

Definition at line 13817 of file chan_dahdi.c.

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

13818 {
13819 #if defined(HAVE_PRI)
13820    char *device;
13821    unsigned span;
13822    int res;
13823 
13824    device = data;
13825 
13826    if (*device != 'I') {
13827       /* The request is not for an ISDN span device. */
13828       return AST_DEVICE_UNKNOWN;
13829    }
13830    res = sscanf(device, "I%30u", &span);
13831    if (res != 1 || !span || NUM_SPANS < span) {
13832       /* Bad format for ISDN span device name. */
13833       return AST_DEVICE_UNKNOWN;
13834    }
13835    device = strchr(device, '/');
13836    if (!device) {
13837       /* Bad format for ISDN span device name. */
13838       return AST_DEVICE_UNKNOWN;
13839    }
13840 
13841    /*
13842     * Since there are currently no other span devstate's defined,
13843     * it must be congestion.
13844     */
13845 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13846    ++device;
13847    if (!strcmp(device, "congestion"))
13848 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13849    {
13850       return pris[span - 1].pri.congestion_devstate;
13851    }
13852 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13853    else if (!strcmp(device, "threshold")) {
13854       return pris[span - 1].pri.threshold_devstate;
13855    }
13856    return AST_DEVICE_UNKNOWN;
13857 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13858 #else
13859    return AST_DEVICE_UNKNOWN;
13860 #endif   /* defined(HAVE_PRI) */
13861 }

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

Definition at line 4463 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, ast_channel::name, 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.

04464 {
04465    struct dahdi_pvt *pvt;
04466    int idx;
04467    int dtmf = -1;
04468    int res;
04469 
04470    pvt = chan->tech_pvt;
04471 
04472    ast_mutex_lock(&pvt->lock);
04473 
04474    idx = dahdi_get_index(chan, pvt, 0);
04475 
04476    if ((idx != SUB_REAL) || !pvt->owner)
04477       goto out;
04478 
04479 #ifdef HAVE_PRI
04480    switch (pvt->sig) {
04481    case SIG_PRI_LIB_HANDLE_CASES:
04482       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04483       if (!res)
04484          goto out;
04485       break;
04486    default:
04487       break;
04488    }
04489 #endif
04490    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04491       goto out;
04492 
04493    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04494       struct dahdi_dialoperation zo = {
04495          .op = DAHDI_DIAL_OP_APPEND,
04496       };
04497 
04498       zo.dialstr[0] = 'T';
04499       zo.dialstr[1] = digit;
04500       zo.dialstr[2] = '\0';
04501       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04502          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04503             chan->name, digit, strerror(errno));
04504       else
04505          pvt->dialing = 1;
04506    } else {
04507       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04508          chan->name, digit);
04509       pvt->dialing = 1;
04510       pvt->begindigit = digit;
04511    }
04512 
04513 out:
04514    ast_mutex_unlock(&pvt->lock);
04515 
04516    return 0;
04517 }

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

Definition at line 4519 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, ast_channel::name, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

04520 {
04521    struct dahdi_pvt *pvt;
04522    int res = 0;
04523    int idx;
04524    int x;
04525 
04526    pvt = chan->tech_pvt;
04527 
04528    ast_mutex_lock(&pvt->lock);
04529 
04530    idx = dahdi_get_index(chan, pvt, 0);
04531 
04532    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04533       goto out;
04534 
04535 #ifdef HAVE_PRI
04536    /* This means that the digit was already sent via PRI signalling */
04537    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04538       goto out;
04539    }
04540 #endif
04541 
04542    if (pvt->begindigit) {
04543       x = -1;
04544       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04545          chan->name, digit);
04546       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04547       pvt->dialing = 0;
04548       pvt->begindigit = 0;
04549    }
04550 
04551 out:
04552    ast_mutex_unlock(&pvt->lock);
04553 
04554    return res;
04555 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

04971 {
04972    int res;
04973 
04974    if (p->echocanon) {
04975       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04976 
04977       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04978 
04979       if (res)
04980          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04981       else
04982          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04983    }
04984 
04985    p->echocanon = 0;
04986 }

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

09878 {
09879    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09880       return analog_dnd(dahdichan->sig_pvt, flag);
09881    }
09882 
09883    if (flag == -1) {
09884       return dahdichan->dnd;
09885    }
09886 
09887    /* Do not disturb */
09888    dahdichan->dnd = flag;
09889    ast_verb(3, "%s DND on channel %d\n",
09890          flag? "Enabled" : "Disabled",
09891          dahdichan->channel);
09892    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09893          "Channel: DAHDI/%d\r\n"
09894          "Status: %s\r\n", dahdichan->channel,
09895          flag? "enabled" : "disabled");
09896 
09897    return 0;
09898 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

04899 {
04900    int res;
04901    if (!p)
04902       return;
04903    if (p->echocanon) {
04904       ast_debug(1, "Echo cancellation already on\n");
04905       return;
04906    }
04907    if (p->digital) {
04908       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04909       return;
04910    }
04911    if (p->echocancel.head.tap_length) {
04912 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04913       switch (p->sig) {
04914 #if defined(HAVE_PRI)
04915       case SIG_PRI_LIB_HANDLE_CASES:
04916          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04917             /*
04918              * PRI nobch pseudo channel.  Does not need ec anyway.
04919              * Does not handle ioctl(DAHDI_AUDIOMODE)
04920              */
04921             return;
04922          }
04923          /* Fall through */
04924 #endif   /* defined(HAVE_PRI) */
04925 #if defined(HAVE_SS7)
04926       case SIG_SS7:
04927 #endif   /* defined(HAVE_SS7) */
04928          {
04929             int x = 1;
04930 
04931             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04932             if (res)
04933                ast_log(LOG_WARNING,
04934                   "Unable to enable audio mode on channel %d (%s)\n",
04935                   p->channel, strerror(errno));
04936          }
04937          break;
04938       default:
04939          break;
04940       }
04941 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04942       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04943       if (res) {
04944          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04945       } else {
04946          p->echocanon = 1;
04947          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04948       }
04949    } else
04950       ast_debug(1, "No echo cancellation requested\n");
04951 }

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

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

08909 {
08910    struct dahdi_pvt *p = ast->tech_pvt;
08911    struct ast_frame *f;
08912    ast_mutex_lock(&p->lock);
08913    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08914       struct analog_pvt *analog_p = p->sig_pvt;
08915       f = analog_exception(analog_p, ast);
08916    } else {
08917       f = __dahdi_exception(ast);
08918    }
08919    ast_mutex_unlock(&p->lock);
08920    return f;
08921 }

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

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

15882 {
15883    if (p) {
15884       switch (mode) {
15885       case TRANSFER:
15886          p->fake_event = DAHDI_EVENT_WINKFLASH;
15887          break;
15888       case HANGUP:
15889          p->fake_event = DAHDI_EVENT_ONHOOK;
15890          break;
15891       default:
15892          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15893       }
15894    }
15895    return 0;
15896 }

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

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

07581 {
07582    struct dahdi_pvt *p = newchan->tech_pvt;
07583    int x;
07584 
07585    ast_mutex_lock(&p->lock);
07586 
07587    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07588    if (p->owner == oldchan) {
07589       p->owner = newchan;
07590    }
07591    for (x = 0; x < 3; x++) {
07592       if (p->subs[x].owner == oldchan) {
07593          if (!x) {
07594             dahdi_unlink(NULL, p, 0);
07595          }
07596          p->subs[x].owner = newchan;
07597       }
07598    }
07599    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07600       analog_fixup(oldchan, newchan, p->sig_pvt);
07601 #if defined(HAVE_PRI)
07602    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07603       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07604 #endif   /* defined(HAVE_PRI) */
07605 #if defined(HAVE_SS7)
07606    } else if (p->sig == SIG_SS7) {
07607       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07608 #endif   /* defined(HAVE_SS7) */
07609    }
07610    update_conf(p);
07611 
07612    ast_mutex_unlock(&p->lock);
07613 
07614    if (newchan->_state == AST_STATE_RINGING) {
07615       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07616    }
07617    return 0;
07618 }

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

Definition at line 6937 of file chan_dahdi.c.

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

06938 {
06939    struct dahdi_pvt *p = chan->tech_pvt;
06940    int res = 0;
06941 
06942    if (!p) {
06943       /* No private structure! */
06944       *buf = '\0';
06945       return -1;
06946    }
06947 
06948    if (!strcasecmp(data, "rxgain")) {
06949       ast_mutex_lock(&p->lock);
06950       snprintf(buf, len, "%f", p->rxgain);
06951       ast_mutex_unlock(&p->lock);
06952    } else if (!strcasecmp(data, "txgain")) {
06953       ast_mutex_lock(&p->lock);
06954       snprintf(buf, len, "%f", p->txgain);
06955       ast_mutex_unlock(&p->lock);
06956    } else if (!strcasecmp(data, "dahdi_channel")) {
06957       ast_mutex_lock(&p->lock);
06958       snprintf(buf, len, "%d", p->channel);
06959       ast_mutex_unlock(&p->lock);
06960    } else if (!strcasecmp(data, "dahdi_span")) {
06961       ast_mutex_lock(&p->lock);
06962       snprintf(buf, len, "%d", p->span);
06963       ast_mutex_unlock(&p->lock);
06964    } else if (!strcasecmp(data, "dahdi_type")) {
06965       ast_mutex_lock(&p->lock);
06966       switch (p->sig) {
06967 #if defined(HAVE_OPENR2)
06968       case SIG_MFCR2:
06969          ast_copy_string(buf, "mfc/r2", len);
06970          break;
06971 #endif   /* defined(HAVE_OPENR2) */
06972 #if defined(HAVE_PRI)
06973       case SIG_PRI_LIB_HANDLE_CASES:
06974          ast_copy_string(buf, "pri", len);
06975          break;
06976 #endif   /* defined(HAVE_PRI) */
06977       case 0:
06978          ast_copy_string(buf, "pseudo", len);
06979          break;
06980 #if defined(HAVE_SS7)
06981       case SIG_SS7:
06982          ast_copy_string(buf, "ss7", len);
06983          break;
06984 #endif   /* defined(HAVE_SS7) */
06985       default:
06986          /* The only thing left is analog ports. */
06987          ast_copy_string(buf, "analog", len);
06988          break;
06989       }
06990       ast_mutex_unlock(&p->lock);
06991 #if defined(HAVE_PRI)
06992 #if defined(HAVE_PRI_REVERSE_CHARGE)
06993    } else if (!strcasecmp(data, "reversecharge")) {
06994       ast_mutex_lock(&p->lock);
06995       switch (p->sig) {
06996       case SIG_PRI_LIB_HANDLE_CASES:
06997          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06998          break;
06999       default:
07000          *buf = '\0';
07001          res = -1;
07002          break;
07003       }
07004       ast_mutex_unlock(&p->lock);
07005 #endif
07006 #if defined(HAVE_PRI_SETUP_KEYPAD)
07007    } else if (!strcasecmp(data, "keypad_digits")) {
07008       ast_mutex_lock(&p->lock);
07009       switch (p->sig) {
07010       case SIG_PRI_LIB_HANDLE_CASES:
07011          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07012             len);
07013          break;
07014       default:
07015          *buf = '\0';
07016          res = -1;
07017          break;
07018       }
07019       ast_mutex_unlock(&p->lock);
07020 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07021    } else if (!strcasecmp(data, "no_media_path")) {
07022       ast_mutex_lock(&p->lock);
07023       switch (p->sig) {
07024       case SIG_PRI_LIB_HANDLE_CASES:
07025          /*
07026           * TRUE if the call is on hold or is call waiting because
07027           * there is no media path available.
07028           */
07029          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07030          break;
07031       default:
07032          *buf = '\0';
07033          res = -1;
07034          break;
07035       }
07036       ast_mutex_unlock(&p->lock);
07037 #endif   /* defined(HAVE_PRI) */
07038    } else {
07039       *buf = '\0';
07040       res = -1;
07041    }
07042 
07043    return res;
07044 }

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

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

07077 {
07078    struct dahdi_pvt *p = chan->tech_pvt;
07079    int res = 0;
07080 
07081    if (!p) {
07082       /* No private structure! */
07083       return -1;
07084    }
07085 
07086    if (!strcasecmp(data, "buffers")) {
07087       int num_bufs, policy;
07088 
07089       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07090          struct dahdi_bufferinfo bi = {
07091             .txbufpolicy = policy,
07092             .rxbufpolicy = policy,
07093             .bufsize = p->bufsize,
07094             .numbufs = num_bufs,
07095          };
07096          int bpres;
07097 
07098          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07099             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07100          } else {
07101             p->bufferoverrideinuse = 1;
07102          }
07103       } else {
07104          res = -1;
07105       }
07106    } else if (!strcasecmp(data, "echocan_mode")) {
07107       if (!strcasecmp(value, "on")) {
07108          ast_mutex_lock(&p->lock);
07109          dahdi_enable_ec(p);
07110          ast_mutex_unlock(&p->lock);
07111       } else if (!strcasecmp(value, "off")) {
07112          ast_mutex_lock(&p->lock);
07113          dahdi_disable_ec(p);
07114          ast_mutex_unlock(&p->lock);
07115 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07116       } else if (!strcasecmp(value, "fax")) {
07117          int blah = 1;
07118 
07119          ast_mutex_lock(&p->lock);
07120          if (!p->echocanon) {
07121             dahdi_enable_ec(p);
07122          }
07123          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07124             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07125          }
07126          ast_mutex_unlock(&p->lock);
07127       } else if (!strcasecmp(value, "voice")) {
07128          int blah = 0;
07129 
07130          ast_mutex_lock(&p->lock);
07131          if (!p->echocanon) {
07132             dahdi_enable_ec(p);
07133          }
07134          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07135             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07136          }
07137          ast_mutex_unlock(&p->lock);
07138 #endif
07139       } else {
07140          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07141          res = -1;
07142       }
07143    } else {
07144       res = -1;
07145    }
07146 
07147    return res;
07148 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

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

00490 {
00491    int j;
00492    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00493       return -1;
00494    return j;
00495 }

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

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

07758 {
07759    struct dahdi_pvt *p = ast->tech_pvt;
07760    struct ast_frame *f = *dest;
07761 
07762    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07763       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07764       f->subclass.integer, f->subclass.integer, ast->name);
07765 
07766    if (p->confirmanswer) {
07767       if (f->frametype == AST_FRAME_DTMF_END) {
07768          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07769          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07770             of a DTMF digit */
07771          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07772          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07773          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07774          p->confirmanswer = 0;
07775       } else {
07776          p->subs[idx].f.frametype = AST_FRAME_NULL;
07777          p->subs[idx].f.subclass.integer = 0;
07778       }
07779       *dest = &p->subs[idx].f;
07780    } else if (p->callwaitcas) {
07781       if (f->frametype == AST_FRAME_DTMF_END) {
07782          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07783             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07784             ast_free(p->cidspill);
07785             p->cidspill = NULL;
07786             send_cwcidspill(p);
07787          }
07788          p->callwaitcas = 0;
07789       }
07790       p->subs[idx].f.frametype = AST_FRAME_NULL;
07791       p->subs[idx].f.subclass.integer = 0;
07792       *dest = &p->subs[idx].f;
07793    } else if (f->subclass.integer == 'f') {
07794       if (f->frametype == AST_FRAME_DTMF_END) {
07795          /* Fax tone -- Handle and return NULL */
07796          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07797             /* If faxbuffers are configured, use them for the fax transmission */
07798             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07799                struct dahdi_bufferinfo bi = {
07800                   .txbufpolicy = p->faxbuf_policy,
07801                   .bufsize = p->bufsize,
07802                   .numbufs = p->faxbuf_no
07803                };
07804                int res;
07805 
07806                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07807                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07808                } else {
07809                   p->bufferoverrideinuse = 1;
07810                }
07811             }
07812             p->faxhandled = 1;
07813             if (p->dsp) {
07814                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07815                ast_dsp_set_features(p->dsp, p->dsp_features);
07816                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07817             }
07818             if (strcmp(ast->exten, "fax")) {
07819                const char *target_context = S_OR(ast->macrocontext, ast->context);
07820 
07821                /* We need to unlock 'ast' here because ast_exists_extension has the
07822                 * potential to start autoservice on the channel. Such action is prone
07823                 * to deadlock.
07824                 */
07825                ast_mutex_unlock(&p->lock);
07826                ast_channel_unlock(ast);
07827                if (ast_exists_extension(ast, target_context, "fax", 1,
07828                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07829                   ast_channel_lock(ast);
07830                   ast_mutex_lock(&p->lock);
07831                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07832                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07833                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07834                   if (ast_async_goto(ast, target_context, "fax", 1))
07835                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07836                } else {
07837                   ast_channel_lock(ast);
07838                   ast_mutex_lock(&p->lock);
07839                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07840                }
07841             } else {
07842                ast_debug(1, "Already in a fax extension, not redirecting\n");
07843             }
07844          } else {
07845             ast_debug(1, "Fax already handled\n");
07846          }
07847          dahdi_confmute(p, 0);
07848       }
07849       p->subs[idx].f.frametype = AST_FRAME_NULL;
07850       p->subs[idx].f.subclass.integer = 0;
07851       *dest = &p->subs[idx].f;
07852    }
07853 }

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

Definition at line 7883 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_lock, 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_mutex_lock, ast_mutex_unlock, ast_null_frame, 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_CALL_LEVEL_PROCEEDING, sig_pri_chan_alarm_notify(), sig_pri_dial_complete(), 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().

07884 {
07885    int res, x;
07886    int idx, mysig;
07887    char *c;
07888    struct dahdi_pvt *p = ast->tech_pvt;
07889    pthread_t threadid;
07890    struct ast_channel *chan;
07891    struct ast_frame *f;
07892 
07893    idx = dahdi_get_index(ast, p, 0);
07894    if (idx < 0) {
07895       return &ast_null_frame;
07896    }
07897    mysig = p->sig;
07898    if (p->outsigmod > -1)
07899       mysig = p->outsigmod;
07900    p->subs[idx].f.frametype = AST_FRAME_NULL;
07901    p->subs[idx].f.subclass.integer = 0;
07902    p->subs[idx].f.datalen = 0;
07903    p->subs[idx].f.samples = 0;
07904    p->subs[idx].f.mallocd = 0;
07905    p->subs[idx].f.offset = 0;
07906    p->subs[idx].f.src = "dahdi_handle_event";
07907    p->subs[idx].f.data.ptr = NULL;
07908    f = &p->subs[idx].f;
07909 
07910    if (p->fake_event) {
07911       res = p->fake_event;
07912       p->fake_event = 0;
07913    } else
07914       res = dahdi_get_event(p->subs[idx].dfd);
07915 
07916    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07917 
07918    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07919       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07920       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07921 #if defined(HAVE_PRI)
07922       if (dahdi_sig_pri_lib_handles(p->sig)
07923          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07924          && p->pri
07925          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07926          /* absorb event */
07927       } else
07928 #endif   /* defined(HAVE_PRI) */
07929       {
07930          /* Unmute conference */
07931          dahdi_confmute(p, 0);
07932          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07933          p->subs[idx].f.subclass.integer = res & 0xff;
07934          dahdi_handle_dtmf(ast, idx, &f);
07935       }
07936       return f;
07937    }
07938 
07939    if (res & DAHDI_EVENT_DTMFDOWN) {
07940       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07941 #if defined(HAVE_PRI)
07942       if (dahdi_sig_pri_lib_handles(p->sig)
07943          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07944          && p->pri
07945          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07946          /* absorb event */
07947       } else
07948 #endif   /* defined(HAVE_PRI) */
07949       {
07950          /* Mute conference */
07951          dahdi_confmute(p, 1);
07952          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07953          p->subs[idx].f.subclass.integer = res & 0xff;
07954          dahdi_handle_dtmf(ast, idx, &f);
07955       }
07956       return &p->subs[idx].f;
07957    }
07958 
07959    switch (res) {
07960    case DAHDI_EVENT_EC_DISABLED:
07961       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07962       p->echocanon = 0;
07963       break;
07964 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07965    case DAHDI_EVENT_TX_CED_DETECTED:
07966       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07967       break;
07968    case DAHDI_EVENT_RX_CED_DETECTED:
07969       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07970       break;
07971    case DAHDI_EVENT_EC_NLP_DISABLED:
07972       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07973       break;
07974    case DAHDI_EVENT_EC_NLP_ENABLED:
07975       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07976       break;
07977 #endif
07978    case DAHDI_EVENT_BITSCHANGED:
07979 #ifdef HAVE_OPENR2
07980       if (p->sig != SIG_MFCR2) {
07981          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07982       } else {
07983          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07984          openr2_chan_handle_cas(p->r2chan);
07985       }
07986 #else
07987       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07988 #endif
07989       break;
07990    case DAHDI_EVENT_PULSE_START:
07991       /* Stop tone if there's a pulse start and the PBX isn't started */
07992       if (!ast->pbx)
07993          tone_zone_play_tone(p->subs[idx].dfd, -1);
07994       break;
07995    case DAHDI_EVENT_DIALCOMPLETE:
07996       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
07997 #if defined(HAVE_PRI)
07998       if (dahdi_sig_pri_lib_handles(p->sig)) {
07999          if (p->inalarm) {
08000             break;
08001          }
08002          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08003             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08004                strerror(errno));
08005             return NULL;
08006          }
08007          if (x) {
08008             /* Still dialing in DAHDI driver */
08009             break;
08010          }
08011          /*
08012           * The ast channel is locked and the private may be locked more
08013           * than once.
08014           */
08015          sig_pri_dial_complete(p->sig_pvt, ast);
08016          break;
08017       }
08018 #endif   /* defined(HAVE_PRI) */
08019 #ifdef HAVE_OPENR2
08020       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08021          /* we don't need to do anything for this event for R2 signaling
08022             if the call is being setup */
08023          break;
08024       }
08025 #endif
08026       if (p->inalarm) break;
08027       if ((p->radio || (p->oprmode < 0))) break;
08028       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08029          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08030          return NULL;
08031       }
08032       if (!x) { /* if not still dialing in driver */
08033          dahdi_enable_ec(p);
08034          if (p->echobreak) {
08035             dahdi_train_ec(p);
08036             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08037             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08038             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08039             p->echobreak = 0;
08040          } else {
08041             p->dialing = 0;
08042             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08043                /* if thru with dialing after offhook */
08044                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08045                   ast_setstate(ast, AST_STATE_UP);
08046                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08047                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08048                   break;
08049                } else { /* if to state wait for offhook to dial rest */
08050                   /* we now wait for off hook */
08051                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08052                }
08053             }
08054             if (ast->_state == AST_STATE_DIALING) {
08055                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08056                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08057                } else if (p->confirmanswer || (!p->dialednone
08058                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08059                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08060                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08061                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08062                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08063                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08064                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08065                      || (mysig == SIG_SF_FEATB)))) {
08066                   ast_setstate(ast, AST_STATE_RINGING);
08067                } else if (!p->answeronpolarityswitch) {
08068                   ast_setstate(ast, AST_STATE_UP);
08069                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08070                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08071                   /* If aops=0 and hops=1, this is necessary */
08072                   p->polarity = POLARITY_REV;
08073                } else {
08074                   /* Start clean, so we can catch the change to REV polarity when party answers */
08075                   p->polarity = POLARITY_IDLE;
08076                }
08077             }
08078          }
08079       }
08080       break;
08081    case DAHDI_EVENT_ALARM:
08082       switch (p->sig) {
08083 #if defined(HAVE_PRI)
08084       case SIG_PRI_LIB_HANDLE_CASES:
08085          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08086          break;
08087 #endif   /* defined(HAVE_PRI) */
08088 #if defined(HAVE_SS7)
08089       case SIG_SS7:
08090          sig_ss7_set_alarm(p->sig_pvt, 1);
08091          break;
08092 #endif   /* defined(HAVE_SS7) */
08093       default:
08094          p->inalarm = 1;
08095          break;
08096       }
08097       res = get_alarms(p);
08098       handle_alarms(p, res);
08099 #ifdef HAVE_PRI
08100       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08101          /* fall through intentionally */
08102       } else {
08103          break;
08104       }
08105 #endif
08106 #if defined(HAVE_SS7)
08107       if (p->sig == SIG_SS7)
08108          break;
08109 #endif   /* defined(HAVE_SS7) */
08110 #ifdef HAVE_OPENR2
08111       if (p->sig == SIG_MFCR2)
08112          break;
08113 #endif
08114    case DAHDI_EVENT_ONHOOK:
08115       if (p->radio) {
08116          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08117          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08118          break;
08119       }
08120       if (p->oprmode < 0)
08121       {
08122          if (p->oprmode != -1) break;
08123          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08124          {
08125             /* Make sure it starts ringing */
08126             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08127             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08128             save_conference(p->oprpeer);
08129             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08130          }
08131          break;
08132       }
08133       switch (p->sig) {
08134       case SIG_FXOLS:
08135       case SIG_FXOGS:
08136       case SIG_FXOKS:
08137          /* Check for some special conditions regarding call waiting */
08138          if (idx == SUB_REAL) {
08139             /* The normal line was hung up */
08140             if (p->subs[SUB_CALLWAIT].owner) {
08141                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08142                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08143                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08144                unalloc_sub(p, SUB_CALLWAIT);
08145 #if 0
08146                p->subs[idx].needanswer = 0;
08147                p->subs[idx].needringing = 0;
08148 #endif
08149                p->callwaitingrepeat = 0;
08150                p->cidcwexpire = 0;
08151                p->cid_suppress_expire = 0;
08152                p->owner = NULL;
08153                /* Don't start streaming audio yet if the incoming call isn't up yet */
08154                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08155                   p->dialing = 1;
08156                dahdi_ring_phone(p);
08157             } else if (p->subs[SUB_THREEWAY].owner) {
08158                unsigned int mssinceflash;
08159                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08160                   the private structure -- not especially easy or clean */
08161                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08162                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08163                   DLA_UNLOCK(&p->lock);
08164                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08165                   /* We can grab ast and p in that order, without worry.  We should make sure
08166                      nothing seriously bad has happened though like some sort of bizarre double
08167                      masquerade! */
08168                   DLA_LOCK(&p->lock);
08169                   if (p->owner != ast) {
08170                      ast_log(LOG_WARNING, "This isn't good...\n");
08171                      return NULL;
08172                   }
08173                }
08174                if (!p->subs[SUB_THREEWAY].owner) {
08175                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08176                   return NULL;
08177                }
08178                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08179                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08180                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08181                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08182                      hanging up.  Hangup both channels now */
08183                   if (p->subs[SUB_THREEWAY].owner)
08184                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08185                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08186                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08187                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08188                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08189                   if (p->transfer) {
08190                      /* In any case this isn't a threeway call anymore */
08191                      p->subs[SUB_REAL].inthreeway = 0;
08192                      p->subs[SUB_THREEWAY].inthreeway = 0;
08193                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08194                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08195                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08196                         /* Swap subs and dis-own channel */
08197                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08198                         p->owner = NULL;
08199                         /* Ring the phone */
08200                         dahdi_ring_phone(p);
08201                      } else {
08202                         if ((res = attempt_transfer(p)) < 0) {
08203                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08204                            if (p->subs[SUB_THREEWAY].owner)
08205                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08206                         } else if (res) {
08207                            /* Don't actually hang up at this point */
08208                            if (p->subs[SUB_THREEWAY].owner)
08209                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08210                            break;
08211                         }
08212                      }
08213                   } else {
08214                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08215                      if (p->subs[SUB_THREEWAY].owner)
08216                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08217                   }
08218                } else {
08219                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08220                   /* Swap subs and dis-own channel */
08221                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08222                   p->owner = NULL;
08223                   /* Ring the phone */
08224                   dahdi_ring_phone(p);
08225                }
08226             }
08227          } else {
08228             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08229          }
08230          /* Fall through */
08231       default:
08232          dahdi_disable_ec(p);
08233          return NULL;
08234       }
08235       break;
08236    case DAHDI_EVENT_RINGOFFHOOK:
08237       if (p->inalarm) break;
08238       if (p->oprmode < 0)
08239       {
08240          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08241          {
08242             /* Make sure it stops ringing */
08243             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08244             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08245             restore_conference(p->oprpeer);
08246          }
08247          break;
08248       }
08249       if (p->radio)
08250       {
08251          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08252          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08253          break;
08254       }
08255       /* for E911, its supposed to wait for offhook then dial
08256          the second half of the dial string */
08257       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08258          c = strchr(p->dialdest, '/');
08259          if (c)
08260             c++;
08261          else
08262             c = p->dialdest;
08263          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08264          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08265          if (strlen(p->dop.dialstr) > 4) {
08266             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08267             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08268             p->echorest[sizeof(p->echorest) - 1] = '\0';
08269             p->echobreak = 1;
08270             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08271          } else
08272             p->echobreak = 0;
08273          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08274             int saveerr = errno;
08275 
08276             x = DAHDI_ONHOOK;
08277             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08278             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08279             return NULL;
08280             }
08281          p->dialing = 1;
08282          return &p->subs[idx].f;
08283       }
08284       switch (p->sig) {
08285       case SIG_FXOLS:
08286       case SIG_FXOGS:
08287       case SIG_FXOKS:
08288          switch (ast->_state) {
08289          case AST_STATE_RINGING:
08290             dahdi_enable_ec(p);
08291             dahdi_train_ec(p);
08292             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08293             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08294             /* Make sure it stops ringing */
08295             p->subs[SUB_REAL].needringing = 0;
08296             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08297             ast_debug(1, "channel %d answered\n", p->channel);
08298 
08299             /* Cancel any running CallerID spill */
08300             ast_free(p->cidspill);
08301             p->cidspill = NULL;
08302             restore_conference(p);
08303 
08304             p->dialing = 0;
08305             p->callwaitcas = 0;
08306             if (p->confirmanswer) {
08307                /* Ignore answer if "confirm answer" is enabled */
08308                p->subs[idx].f.frametype = AST_FRAME_NULL;
08309                p->subs[idx].f.subclass.integer = 0;
08310             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08311                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08312                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08313                if (res < 0) {
08314                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08315                   p->dop.dialstr[0] = '\0';
08316                   return NULL;
08317                } else {
08318                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08319                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08320                   p->subs[idx].f.subclass.integer = 0;
08321                   p->dialing = 1;
08322                }
08323                p->dop.dialstr[0] = '\0';
08324                ast_setstate(ast, AST_STATE_DIALING);
08325             } else
08326                ast_setstate(ast, AST_STATE_UP);
08327             return &p->subs[idx].f;
08328          case AST_STATE_DOWN:
08329             ast_setstate(ast, AST_STATE_RING);
08330             ast->rings = 1;
08331             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08332             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08333             ast_debug(1, "channel %d picked up\n", p->channel);
08334             return &p->subs[idx].f;
08335          case AST_STATE_UP:
08336             /* Make sure it stops ringing */
08337             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08338             /* Okay -- probably call waiting*/
08339             if (ast_bridged_channel(p->owner))
08340                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08341             p->subs[idx].needunhold = 1;
08342             break;
08343          case AST_STATE_RESERVED:
08344             /* Start up dialtone */
08345             if (has_voicemail(p))
08346                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08347             else
08348                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08349             break;
08350          default:
08351             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08352          }
08353          break;
08354       case SIG_FXSLS:
08355       case SIG_FXSGS:
08356       case SIG_FXSKS:
08357          if (ast->_state == AST_STATE_RING) {
08358             p->ringt = p->ringt_base;
08359          }
08360 
08361          /* If we get a ring then we cannot be in
08362           * reversed polarity. So we reset to idle */
08363          ast_debug(1, "Setting IDLE polarity due "
08364             "to ring. Old polarity was %d\n",
08365             p->polarity);
08366          p->polarity = POLARITY_IDLE;
08367 
08368          /* Fall through */
08369       case SIG_EM:
08370       case SIG_EM_E1:
08371       case SIG_EMWINK:
08372       case SIG_FEATD:
08373       case SIG_FEATDMF:
08374       case SIG_FEATDMF_TA:
08375       case SIG_E911:
08376       case SIG_FGC_CAMA:
08377       case SIG_FGC_CAMAMF:
08378       case SIG_FEATB:
08379       case SIG_SF:
08380       case SIG_SFWINK:
08381       case SIG_SF_FEATD:
08382       case SIG_SF_FEATDMF:
08383       case SIG_SF_FEATB:
08384          if (ast->_state == AST_STATE_PRERING)
08385             ast_setstate(ast, AST_STATE_RING);
08386          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08387             ast_debug(1, "Ring detected\n");
08388             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08389             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08390          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08391             ast_debug(1, "Line answered\n");
08392             if (p->confirmanswer) {
08393                p->subs[idx].f.frametype = AST_FRAME_NULL;
08394                p->subs[idx].f.subclass.integer = 0;
08395             } else {
08396                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08397                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08398                ast_setstate(ast, AST_STATE_UP);
08399             }
08400          } else if (ast->_state != AST_STATE_RING)
08401             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08402          break;
08403       default:
08404          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08405       }
08406       break;
08407    case DAHDI_EVENT_RINGBEGIN:
08408       switch (p->sig) {
08409       case SIG_FXSLS:
08410       case SIG_FXSGS:
08411       case SIG_FXSKS:
08412          if (ast->_state == AST_STATE_RING) {
08413             p->ringt = p->ringt_base;
08414          }
08415          break;
08416       }
08417       break;
08418    case DAHDI_EVENT_RINGERON:
08419       break;
08420    case DAHDI_EVENT_NOALARM:
08421       switch (p->sig) {
08422 #if defined(HAVE_PRI)
08423       case SIG_PRI_LIB_HANDLE_CASES:
08424          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08425          break;
08426 #endif   /* defined(HAVE_PRI) */
08427 #if defined(HAVE_SS7)
08428       case SIG_SS7:
08429          sig_ss7_set_alarm(p->sig_pvt, 0);
08430          break;
08431 #endif   /* defined(HAVE_SS7) */
08432       default:
08433          p->inalarm = 0;
08434          break;
08435       }
08436       handle_clear_alarms(p);
08437       break;
08438    case DAHDI_EVENT_WINKFLASH:
08439       if (p->inalarm) break;
08440       if (p->radio) break;
08441       if (p->oprmode < 0) break;
08442       if (p->oprmode > 1)
08443       {
08444          struct dahdi_params par;
08445 
08446          memset(&par, 0, sizeof(par));
08447          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08448          {
08449             if (!par.rxisoffhook)
08450             {
08451                /* Make sure it stops ringing */
08452                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08453                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08454                save_conference(p);
08455                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08456             }
08457          }
08458          break;
08459       }
08460       /* Remember last time we got a flash-hook */
08461       p->flashtime = ast_tvnow();
08462       switch (mysig) {
08463       case SIG_FXOLS:
08464       case SIG_FXOGS:
08465       case SIG_FXOKS:
08466          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08467             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08468 
08469          /* Cancel any running CallerID spill */
08470          ast_free(p->cidspill);
08471          p->cidspill = NULL;
08472          restore_conference(p);
08473          p->callwaitcas = 0;
08474 
08475          if (idx != SUB_REAL) {
08476             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08477             goto winkflashdone;
08478          }
08479 
08480          if (p->subs[SUB_CALLWAIT].owner) {
08481             /* Swap to call-wait */
08482             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08483             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08484             p->owner = p->subs[SUB_REAL].owner;
08485             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08486             if (p->owner->_state == AST_STATE_RINGING) {
08487                ast_setstate(p->owner, AST_STATE_UP);
08488                p->subs[SUB_REAL].needanswer = 1;
08489             }
08490             p->callwaitingrepeat = 0;
08491             p->cidcwexpire = 0;
08492             p->cid_suppress_expire = 0;
08493             /* Start music on hold if appropriate */
08494             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08495                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08496                   S_OR(p->mohsuggest, NULL),
08497                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08498             }
08499             p->subs[SUB_CALLWAIT].needhold = 1;
08500             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08501                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08502                   S_OR(p->mohsuggest, NULL),
08503                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08504             }
08505             p->subs[SUB_REAL].needunhold = 1;
08506          } else if (!p->subs[SUB_THREEWAY].owner) {
08507             if (!p->threewaycalling) {
08508                /* Just send a flash if no 3-way calling */
08509                p->subs[SUB_REAL].needflash = 1;
08510                goto winkflashdone;
08511             } else if (!check_for_conference(p)) {
08512                char cid_num[256];
08513                char cid_name[256];
08514 
08515                cid_num[0] = 0;
08516                cid_name[0] = 0;
08517                if (p->dahditrcallerid && p->owner) {
08518                   if (p->owner->caller.id.number.valid
08519                      && p->owner->caller.id.number.str) {
08520                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08521                         sizeof(cid_num));
08522                   }
08523                   if (p->owner->caller.id.name.valid
08524                      && p->owner->caller.id.name.str) {
08525                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08526                         sizeof(cid_name));
08527                   }
08528                }
08529                /* XXX This section needs much more error checking!!! XXX */
08530                /* Start a 3-way call if feasible */
08531                if (!((ast->pbx) ||
08532                   (ast->_state == AST_STATE_UP) ||
08533                   (ast->_state == AST_STATE_RING))) {
08534                   ast_debug(1, "Flash when call not up or ringing\n");
08535                   goto winkflashdone;
08536                }
08537                if (alloc_sub(p, SUB_THREEWAY)) {
08538                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08539                   goto winkflashdone;
08540                }
08541 
08542                /*
08543                 * Make new channel
08544                 *
08545                 * We cannot hold the p or ast locks while creating a new
08546                 * channel.
08547                 */
08548                ast_mutex_unlock(&p->lock);
08549                ast_channel_unlock(ast);
08550                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08551                ast_channel_lock(ast);
08552                ast_mutex_lock(&p->lock);
08553                if (p->dahditrcallerid) {
08554                   if (!p->origcid_num)
08555                      p->origcid_num = ast_strdup(p->cid_num);
08556                   if (!p->origcid_name)
08557                      p->origcid_name = ast_strdup(p->cid_name);
08558                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08559                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08560                }
08561                /* Swap things around between the three-way and real call */
08562                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08563                /* Disable echo canceller for better dialing */
08564                dahdi_disable_ec(p);
08565                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08566                if (res)
08567                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08568                p->owner = chan;
08569                if (!chan) {
08570                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08571                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08572                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08573                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08574                   dahdi_enable_ec(p);
08575                   ast_hangup(chan);
08576                } else {
08577                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08578 
08579                   /* Start music on hold if appropriate */
08580                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08581                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08582                         S_OR(p->mohsuggest, NULL),
08583                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08584                   }
08585                   p->subs[SUB_THREEWAY].needhold = 1;
08586                }
08587             }
08588          } else {
08589             /* Already have a 3 way call */
08590             if (p->subs[SUB_THREEWAY].inthreeway) {
08591                /* Call is already up, drop the last person */
08592                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08593                /* If the primary call isn't answered yet, use it */
08594                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08595                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08596                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08597                   p->owner = p->subs[SUB_REAL].owner;
08598                }
08599                /* Drop the last call and stop the conference */
08600                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08601                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08602                p->subs[SUB_REAL].inthreeway = 0;
08603                p->subs[SUB_THREEWAY].inthreeway = 0;
08604             } else {
08605                /* Lets see what we're up to */
08606                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08607                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08608                   int otherindex = SUB_THREEWAY;
08609 
08610                   ast_verb(3, "Building conference call with %s and %s\n",
08611                      p->subs[SUB_THREEWAY].owner->name,
08612                      p->subs[SUB_REAL].owner->name);
08613                   /* Put them in the threeway, and flip */
08614                   p->subs[SUB_THREEWAY].inthreeway = 1;
08615                   p->subs[SUB_REAL].inthreeway = 1;
08616                   if (ast->_state == AST_STATE_UP) {
08617                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08618                      otherindex = SUB_REAL;
08619                   }
08620                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08621                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08622                   p->subs[otherindex].needunhold = 1;
08623                   p->owner = p->subs[SUB_REAL].owner;
08624                } else {
08625                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08626                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08627                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08628                   p->owner = p->subs[SUB_REAL].owner;
08629                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08630                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08631                   p->subs[SUB_REAL].needunhold = 1;
08632                   dahdi_enable_ec(p);
08633                }
08634             }
08635          }
08636 winkflashdone:
08637          update_conf(p);
08638          break;
08639       case SIG_EM:
08640       case SIG_EM_E1:
08641       case SIG_FEATD:
08642       case SIG_SF:
08643       case SIG_SFWINK:
08644       case SIG_SF_FEATD:
08645       case SIG_FXSLS:
08646       case SIG_FXSGS:
08647          if (p->dialing)
08648             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08649          else
08650             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08651          break;
08652       case SIG_FEATDMF_TA:
08653          switch (p->whichwink) {
08654          case 0:
08655             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08656                S_COR(p->owner->caller.ani.number.valid,
08657                   p->owner->caller.ani.number.str, ""));
08658             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08659                p->owner->caller.ani2,
08660                S_COR(p->owner->caller.ani.number.valid,
08661                   p->owner->caller.ani.number.str, ""));
08662             break;
08663          case 1:
08664             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08665             break;
08666          case 2:
08667             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08668             return NULL;
08669          }
08670          p->whichwink++;
08671          /* Fall through */
08672       case SIG_FEATDMF:
08673       case SIG_E911:
08674       case SIG_FGC_CAMAMF:
08675       case SIG_FGC_CAMA:
08676       case SIG_FEATB:
08677       case SIG_SF_FEATDMF:
08678       case SIG_SF_FEATB:
08679       case SIG_EMWINK:
08680          /* FGD MF and EMWINK *Must* wait for wink */
08681          if (!ast_strlen_zero(p->dop.dialstr)) {
08682             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08683             if (res < 0) {
08684                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08685                p->dop.dialstr[0] = '\0';
08686                return NULL;
08687             } else
08688                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08689          }
08690          p->dop.dialstr[0] = '\0';
08691          break;
08692       default:
08693          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08694       }
08695       break;
08696    case DAHDI_EVENT_HOOKCOMPLETE:
08697       if (p->inalarm) break;
08698       if ((p->radio || (p->oprmode < 0))) break;
08699       if (p->waitingfordt.tv_sec) break;
08700       switch (mysig) {
08701       case SIG_FXSLS:  /* only interesting for FXS */
08702       case SIG_FXSGS:
08703       case SIG_FXSKS:
08704       case SIG_EM:
08705       case SIG_EM_E1:
08706       case SIG_EMWINK:
08707       case SIG_FEATD:
08708       case SIG_SF:
08709       case SIG_SFWINK:
08710       case SIG_SF_FEATD:
08711          if (!ast_strlen_zero(p->dop.dialstr)) {
08712             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08713             if (res < 0) {
08714                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08715                p->dop.dialstr[0] = '\0';
08716                return NULL;
08717             } else
08718                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08719          }
08720          p->dop.dialstr[0] = '\0';
08721          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08722          break;
08723       case SIG_FEATDMF:
08724       case SIG_FEATDMF_TA:
08725       case SIG_E911:
08726       case SIG_FGC_CAMA:
08727       case SIG_FGC_CAMAMF:
08728       case SIG_FEATB:
08729       case SIG_SF_FEATDMF:
08730       case SIG_SF_FEATB:
08731          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08732          break;
08733       default:
08734          break;
08735       }
08736       break;
08737    case DAHDI_EVENT_POLARITY:
08738       /*
08739        * If we get a Polarity Switch event, check to see
08740        * if we should change the polarity state and
08741        * mark the channel as UP or if this is an indication
08742        * of remote end disconnect.
08743        */
08744       if (p->polarity == POLARITY_IDLE) {
08745          p->polarity = POLARITY_REV;
08746          if (p->answeronpolarityswitch &&
08747             ((ast->_state == AST_STATE_DIALING) ||
08748             (ast->_state == AST_STATE_RINGING))) {
08749             ast_debug(1, "Answering on polarity switch!\n");
08750             ast_setstate(p->owner, AST_STATE_UP);
08751             if (p->hanguponpolarityswitch) {
08752                p->polaritydelaytv = ast_tvnow();
08753             }
08754          } else
08755             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08756       }
08757       /* Removed else statement from here as it was preventing hangups from ever happening*/
08758       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08759       if (p->hanguponpolarityswitch &&
08760          (p->polarityonanswerdelay > 0) &&
08761          (p->polarity == POLARITY_REV) &&
08762          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08763          /* Added log_debug information below to provide a better indication of what is going on */
08764          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) );
08765 
08766          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08767             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08768             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08769             p->polarity = POLARITY_IDLE;
08770          } else
08771             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);
08772 
08773       } else {
08774          p->polarity = POLARITY_IDLE;
08775          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08776       }
08777       /* Added more log_debug information below to provide a better indication of what is going on */
08778       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) );
08779       break;
08780    default:
08781       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08782    }
08783    return &p->subs[idx].f;
08784 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

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

06161 {
06162    int res = 0;
06163    int idx,x;
06164    int law;
06165    /*static int restore_gains(struct dahdi_pvt *p);*/
06166    struct dahdi_pvt *p = ast->tech_pvt;
06167    struct dahdi_params par;
06168 
06169    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06170    if (!ast->tech_pvt) {
06171       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06172       return 0;
06173    }
06174 
06175    ast_mutex_lock(&p->lock);
06176    p->exten[0] = '\0';
06177    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06178       dahdi_confmute(p, 0);
06179       restore_gains(p);
06180       p->ignoredtmf = 0;
06181       p->waitingfordt.tv_sec = 0;
06182 
06183       res = analog_hangup(p->sig_pvt, ast);
06184       revert_fax_buffers(p, ast);
06185 
06186       goto hangup_out;
06187    } else {
06188       p->cid_num[0] = '\0';
06189       p->cid_name[0] = '\0';
06190       p->cid_subaddr[0] = '\0';
06191    }
06192 
06193 #if defined(HAVE_PRI)
06194    if (dahdi_sig_pri_lib_handles(p->sig)) {
06195       x = 1;
06196       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06197 
06198       dahdi_confmute(p, 0);
06199       p->muting = 0;
06200       restore_gains(p);
06201       if (p->dsp) {
06202          ast_dsp_free(p->dsp);
06203          p->dsp = NULL;
06204       }
06205       p->ignoredtmf = 0;
06206 
06207       /* Real channel, do some fixup */
06208       p->subs[SUB_REAL].owner = NULL;
06209       p->subs[SUB_REAL].needbusy = 0;
06210       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06211 
06212       p->owner = NULL;
06213       p->cid_tag[0] = '\0';
06214       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06215       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06216       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06217       p->outgoing = 0;
06218       p->digital = 0;
06219       p->faxhandled = 0;
06220       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06221 
06222       revert_fax_buffers(p, ast);
06223 
06224       p->law = p->law_default;
06225       law = p->law_default;
06226       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06227       if (res < 0) {
06228          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06229             p->channel, strerror(errno));
06230       }
06231 
06232       sig_pri_hangup(p->sig_pvt, ast);
06233 
06234       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06235       dahdi_disable_ec(p);
06236 
06237       x = 0;
06238       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06239       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06240 
06241       p->rdnis[0] = '\0';
06242       update_conf(p);
06243       reset_conf(p);
06244 
06245       /* Restore data mode */
06246       x = 0;
06247       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06248 
06249       if (num_restart_pending == 0) {
06250          restart_monitor();
06251       }
06252       goto hangup_out;
06253    }
06254 #endif   /* defined(HAVE_PRI) */
06255 
06256 #if defined(HAVE_SS7)
06257    if (p->sig == SIG_SS7) {
06258       x = 1;
06259       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06260 
06261       dahdi_confmute(p, 0);
06262       p->muting = 0;
06263       restore_gains(p);
06264       if (p->dsp) {
06265          ast_dsp_free(p->dsp);
06266          p->dsp = NULL;
06267       }
06268       p->ignoredtmf = 0;
06269 
06270       /* Real channel, do some fixup */
06271       p->subs[SUB_REAL].owner = NULL;
06272       p->subs[SUB_REAL].needbusy = 0;
06273       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06274 
06275       p->owner = NULL;
06276       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06277       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06278       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06279       p->outgoing = 0;
06280       p->digital = 0;
06281       p->faxhandled = 0;
06282       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06283 
06284       revert_fax_buffers(p, ast);
06285 
06286       p->law = p->law_default;
06287       law = p->law_default;
06288       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06289       if (res < 0) {
06290          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06291             p->channel, strerror(errno));
06292       }
06293 
06294       sig_ss7_hangup(p->sig_pvt, ast);
06295 
06296       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06297       dahdi_disable_ec(p);
06298 
06299       x = 0;
06300       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06301       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06302 
06303       update_conf(p);
06304       reset_conf(p);
06305 
06306       /* Restore data mode */
06307       x = 0;
06308       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06309 
06310       if (num_restart_pending == 0) {
06311          restart_monitor();
06312       }
06313       goto hangup_out;
06314    }
06315 #endif   /* defined(HAVE_SS7) */
06316 
06317    idx = dahdi_get_index(ast, p, 1);
06318 
06319    dahdi_confmute(p, 0);
06320    p->muting = 0;
06321    restore_gains(p);
06322    if (p->origcid_num) {
06323       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06324       ast_free(p->origcid_num);
06325       p->origcid_num = NULL;
06326    }
06327    if (p->origcid_name) {
06328       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06329       ast_free(p->origcid_name);
06330       p->origcid_name = NULL;
06331    }
06332    if (p->dsp)
06333       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06334 
06335    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06336       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06337    p->ignoredtmf = 0;
06338 
06339    if (idx > -1) {
06340       /* Real channel, do some fixup */
06341       p->subs[idx].owner = NULL;
06342       p->subs[idx].needanswer = 0;
06343       p->subs[idx].needflash = 0;
06344       p->subs[idx].needringing = 0;
06345       p->subs[idx].needbusy = 0;
06346       p->subs[idx].needcongestion = 0;
06347       p->subs[idx].linear = 0;
06348       p->polarity = POLARITY_IDLE;
06349       dahdi_setlinear(p->subs[idx].dfd, 0);
06350       if (idx == SUB_REAL) {
06351          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06352             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06353             if (p->subs[SUB_CALLWAIT].inthreeway) {
06354                /* We had flipped over to answer a callwait and now it's gone */
06355                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06356                /* Move to the call-wait, but un-own us until they flip back. */
06357                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06358                unalloc_sub(p, SUB_CALLWAIT);
06359                p->owner = NULL;
06360             } else {
06361                /* The three way hung up, but we still have a call wait */
06362                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06363                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06364                unalloc_sub(p, SUB_THREEWAY);
06365                if (p->subs[SUB_REAL].inthreeway) {
06366                   /* This was part of a three way call.  Immediately make way for
06367                      another call */
06368                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06369                   p->owner = p->subs[SUB_REAL].owner;
06370                } else {
06371                   /* This call hasn't been completed yet...  Set owner to NULL */
06372                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06373                   p->owner = NULL;
06374                }
06375                p->subs[SUB_REAL].inthreeway = 0;
06376             }
06377          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06378             /* Move to the call-wait and switch back to them. */
06379             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06380             unalloc_sub(p, SUB_CALLWAIT);
06381             p->owner = p->subs[SUB_REAL].owner;
06382             if (p->owner->_state != AST_STATE_UP)
06383                p->subs[SUB_REAL].needanswer = 1;
06384             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06385                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06386          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06387             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06388             unalloc_sub(p, SUB_THREEWAY);
06389             if (p->subs[SUB_REAL].inthreeway) {
06390                /* This was part of a three way call.  Immediately make way for
06391                   another call */
06392                ast_debug(1, "Call was complete, setting owner to former third call\n");
06393                p->owner = p->subs[SUB_REAL].owner;
06394             } else {
06395                /* This call hasn't been completed yet...  Set owner to NULL */
06396                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06397                p->owner = NULL;
06398             }
06399             p->subs[SUB_REAL].inthreeway = 0;
06400          }
06401       } else if (idx == SUB_CALLWAIT) {
06402          /* Ditch the holding callwait call, and immediately make it availabe */
06403          if (p->subs[SUB_CALLWAIT].inthreeway) {
06404             /* This is actually part of a three way, placed on hold.  Place the third part
06405                on music on hold now */
06406             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06407                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06408                   S_OR(p->mohsuggest, NULL),
06409                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06410             }
06411             p->subs[SUB_THREEWAY].inthreeway = 0;
06412             /* Make it the call wait now */
06413             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06414             unalloc_sub(p, SUB_THREEWAY);
06415          } else
06416             unalloc_sub(p, SUB_CALLWAIT);
06417       } else if (idx == SUB_THREEWAY) {
06418          if (p->subs[SUB_CALLWAIT].inthreeway) {
06419             /* The other party of the three way call is currently in a call-wait state.
06420                Start music on hold for them, and take the main guy out of the third call */
06421             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06422                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06423                   S_OR(p->mohsuggest, NULL),
06424                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06425             }
06426             p->subs[SUB_CALLWAIT].inthreeway = 0;
06427          }
06428          p->subs[SUB_REAL].inthreeway = 0;
06429          /* If this was part of a three way call index, let us make
06430             another three way call */
06431          unalloc_sub(p, SUB_THREEWAY);
06432       } else {
06433          /* This wasn't any sort of call, but how are we an index? */
06434          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06435       }
06436    }
06437 
06438    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06439       p->owner = NULL;
06440       p->ringt = 0;
06441       p->distinctivering = 0;
06442       p->confirmanswer = 0;
06443       p->outgoing = 0;
06444       p->digital = 0;
06445       p->faxhandled = 0;
06446       p->pulsedial = 0;
06447       if (p->dsp) {
06448          ast_dsp_free(p->dsp);
06449          p->dsp = NULL;
06450       }
06451 
06452       revert_fax_buffers(p, ast);
06453 
06454       p->law = p->law_default;
06455       law = p->law_default;
06456       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06457       if (res < 0)
06458          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06459       /* Perform low level hangup if no owner left */
06460 #ifdef HAVE_OPENR2
06461       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06462          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06463          /* If it's an incoming call, check the mfcr2_forced_release setting */
06464          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06465             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06466          } else {
06467             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06468             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06469             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06470                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06471             dahdi_r2_disconnect_call(p, r2cause);
06472          }
06473       } else if (p->mfcr2call) {
06474          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06475          /* since ast_request() was called but not ast_call() we have not yet dialed
06476          and the openr2 stack will not call on_call_end callback, we need to unset
06477          the mfcr2call flag and bump the monitor count so the monitor thread can take
06478          care of this channel events from now on */
06479          p->mfcr2call = 0;
06480       }
06481 #endif
06482       switch (p->sig) {
06483       case SIG_SS7:
06484       case SIG_MFCR2:
06485       case SIG_PRI_LIB_HANDLE_CASES:
06486       case 0:
06487          break;
06488       default:
06489          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06490          break;
06491       }
06492       if (res < 0) {
06493          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06494       }
06495       switch (p->sig) {
06496       case SIG_FXOGS:
06497       case SIG_FXOLS:
06498       case SIG_FXOKS:
06499          memset(&par, 0, sizeof(par));
06500          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06501          if (!res) {
06502             struct analog_pvt *analog_p = p->sig_pvt;
06503 #if 0
06504             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06505 #endif
06506             /* If they're off hook, try playing congestion */
06507             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06508                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06509             else
06510                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06511             analog_p->fxsoffhookstate = par.rxisoffhook;
06512          }
06513          break;
06514       case SIG_FXSGS:
06515       case SIG_FXSLS:
06516       case SIG_FXSKS:
06517          /* Make sure we're not made available for at least two seconds assuming
06518          we were actually used for an inbound or outbound call. */
06519          if (ast->_state != AST_STATE_RESERVED) {
06520             time(&p->guardtime);
06521             p->guardtime += 2;
06522          }
06523          break;
06524       default:
06525          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06526          break;
06527       }
06528       if (p->sig)
06529          dahdi_disable_ec(p);
06530       x = 0;
06531       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06532       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06533       p->didtdd = 0;
06534       p->callwaitcas = 0;
06535       p->callwaiting = p->permcallwaiting;
06536       p->hidecallerid = p->permhidecallerid;
06537       p->waitingfordt.tv_sec = 0;
06538       p->dialing = 0;
06539       p->rdnis[0] = '\0';
06540       update_conf(p);
06541       reset_conf(p);
06542       /* Restore data mode */
06543       switch (p->sig) {
06544       case SIG_PRI_LIB_HANDLE_CASES:
06545       case SIG_SS7:
06546          x = 0;
06547          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06548          break;
06549       default:
06550          break;
06551       }
06552       if (num_restart_pending == 0)
06553          restart_monitor();
06554    }
06555 
06556    p->callwaitingrepeat = 0;
06557    p->cidcwexpire = 0;
06558    p->cid_suppress_expire = 0;
06559    p->oprmode = 0;
06560 hangup_out:
06561    ast->tech_pvt = NULL;
06562    ast_free(p->cidspill);
06563    p->cidspill = NULL;
06564 
06565    ast_mutex_unlock(&p->lock);
06566    ast_verb(3, "Hungup '%s'\n", ast->name);
06567 
06568    ast_mutex_lock(&iflock);
06569    if (p->restartpending) {
06570       num_restart_pending--;
06571    }
06572 
06573    if (p->destroy) {
06574       destroy_channel(p, 0);
06575    }
06576    ast_mutex_unlock(&iflock);
06577 
06578    ast_module_unref(ast_module_info->self);
06579    return 0;
06580 }

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

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

05555 {
05556    /* Extract from the forward chain. */
05557    if (pvt->prev) {
05558       pvt->prev->next = pvt->next;
05559    } else if (iflist == pvt) {
05560       /* Node is at the head of the list. */
05561       iflist = pvt->next;
05562    }
05563 
05564    /* Extract from the reverse chain. */
05565    if (pvt->next) {
05566       pvt->next->prev = pvt->prev;
05567    } else if (ifend == pvt) {
05568       /* Node is at the end of the list. */
05569       ifend = pvt->prev;
05570    }
05571 
05572    /* Node is no longer in the list. */
05573    pvt->which_iflist = DAHDI_IFLIST_NONE;
05574    pvt->prev = NULL;
05575    pvt->next = NULL;
05576 }

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

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

05505 {
05506    struct dahdi_pvt *cur;
05507 
05508    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05509 
05510    /* Find place in middle of list for the new interface. */
05511    for (cur = iflist; cur; cur = cur->next) {
05512       if (pvt->channel < cur->channel) {
05513          /* New interface goes before the current interface. */
05514          pvt->prev = cur->prev;
05515          pvt->next = cur;
05516          if (cur->prev) {
05517             /* Insert into the middle of the list. */
05518             cur->prev->next = pvt;
05519          } else {
05520             /* Insert at head of list. */
05521             iflist = pvt;
05522          }
05523          cur->prev = pvt;
05524          return;
05525       }
05526    }
05527 
05528    /* New interface goes onto the end of the list */
05529    pvt->prev = ifend;
05530    pvt->next = NULL;
05531    if (ifend) {
05532       ifend->next = pvt;
05533    }
05534    ifend = pvt;
05535    if (!iflist) {
05536       /* List was empty */
05537       iflist = pvt;
05538    }
05539 }

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

Definition at line 9437 of file chan_dahdi.c.

References ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, 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.

09438 {
09439    struct dahdi_pvt *p = chan->tech_pvt;
09440    int res=-1;
09441    int idx;
09442    int func = DAHDI_FLASH;
09443 
09444    ast_mutex_lock(&p->lock);
09445    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09446    switch (p->sig) {
09447 #if defined(HAVE_PRI)
09448    case SIG_PRI_LIB_HANDLE_CASES:
09449       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09450       ast_mutex_unlock(&p->lock);
09451       return res;
09452 #endif   /* defined(HAVE_PRI) */
09453 #if defined(HAVE_SS7)
09454    case SIG_SS7:
09455       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09456       ast_mutex_unlock(&p->lock);
09457       return res;
09458 #endif   /* defined(HAVE_SS7) */
09459    default:
09460       break;
09461    }
09462 #ifdef HAVE_OPENR2
09463    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09464       ast_mutex_unlock(&p->lock);
09465       /* if this is an R2 call and the call is not yet accepted, we don't want the
09466          tone indications to mess up with the MF tones */
09467       return 0;
09468    }
09469 #endif
09470    idx = dahdi_get_index(chan, p, 0);
09471    if (idx == SUB_REAL) {
09472       switch (condition) {
09473       case AST_CONTROL_BUSY:
09474          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09475          break;
09476       case AST_CONTROL_RINGING:
09477          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09478 
09479          if (chan->_state != AST_STATE_UP) {
09480             if ((chan->_state != AST_STATE_RING) ||
09481                ((p->sig != SIG_FXSKS) &&
09482              (p->sig != SIG_FXSLS) &&
09483              (p->sig != SIG_FXSGS)))
09484             ast_setstate(chan, AST_STATE_RINGING);
09485          }
09486          break;
09487       case AST_CONTROL_INCOMPLETE:
09488          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09489          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09490          res = 0;
09491          break;
09492       case AST_CONTROL_PROCEEDING:
09493          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09494          /* don't continue in ast_indicate */
09495          res = 0;
09496          break;
09497       case AST_CONTROL_PROGRESS:
09498          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09499          /* don't continue in ast_indicate */
09500          res = 0;
09501          break;
09502       case AST_CONTROL_CONGESTION:
09503          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09504          switch (chan->hangupcause) {
09505          case AST_CAUSE_USER_BUSY:
09506          case AST_CAUSE_NORMAL_CLEARING:
09507          case 0:/* Cause has not been set. */
09508             /* Supply a more appropriate cause. */
09509             chan->hangupcause = AST_CAUSE_CONGESTION;
09510             break;
09511          default:
09512             break;
09513          }
09514          break;
09515       case AST_CONTROL_HOLD:
09516          ast_moh_start(chan, data, p->mohinterpret);
09517          break;
09518       case AST_CONTROL_UNHOLD:
09519          ast_moh_stop(chan);
09520          break;
09521       case AST_CONTROL_RADIO_KEY:
09522          if (p->radio)
09523             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09524          res = 0;
09525          break;
09526       case AST_CONTROL_RADIO_UNKEY:
09527          if (p->radio)
09528             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09529          res = 0;
09530          break;
09531       case AST_CONTROL_FLASH:
09532          /* flash hookswitch */
09533          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09534             /* Clear out the dial buffer */
09535             p->dop.dialstr[0] = '\0';
09536             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09537                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09538                   chan->name, strerror(errno));
09539             } else
09540                res = 0;
09541          } else
09542             res = 0;
09543          break;
09544       case AST_CONTROL_SRCUPDATE:
09545          res = 0;
09546          break;
09547       case -1:
09548          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09549          break;
09550       }
09551    } else {
09552       res = 0;
09553    }
09554    ast_mutex_unlock(&p->lock);
09555    return res;
09556 }

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

Definition at line 7206 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

07206                                                                           {
07207    int x;
07208    if (!slave || !master) {
07209       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07210       return;
07211    }
07212    for (x = 0; x < MAX_SLAVES; x++) {
07213       if (!master->slaves[x]) {
07214          master->slaves[x] = slave;
07215          break;
07216       }
07217    }
07218    if (x >= MAX_SLAVES) {
07219       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07220       master->slaves[MAX_SLAVES - 1] = slave;
07221    }
07222    if (slave->master)
07223       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07224    slave->master = master;
07225 
07226    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07227 }

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

Definition at line 3775 of file chan_dahdi.c.

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

Referenced by wakeup_sub().

03776 {
03777    for (;;) {
03778       if (!pvt->subs[sub_idx].owner) {
03779          /* No subchannel owner pointer */
03780          break;
03781       }
03782       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03783          /* Got subchannel owner lock */
03784          break;
03785       }
03786       /* We must unlock the private to avoid the possibility of a deadlock */
03787       DEADLOCK_AVOIDANCE(&pvt->lock);
03788    }
03789 }

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 9606 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_NAME, ast_channel_set_fd(), ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, 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_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_ami_channel_event(), 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(), and register_translator().

09607 {
09608    struct ast_channel *tmp;
09609    format_t deflaw;
09610    int x;
09611    int features;
09612    struct ast_str *chan_name;
09613    struct ast_variable *v;
09614    char *dashptr;
09615    char device_name[AST_CHANNEL_NAME];
09616 
09617    if (i->subs[idx].owner) {
09618       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09619       return NULL;
09620    }
09621 
09622 #if defined(HAVE_PRI)
09623    /*
09624     * The dnid has been stuffed with the called-number[:subaddress]
09625     * by dahdi_request() for outgoing calls.
09626     */
09627    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09628 #else
09629    chan_name = create_channel_name(i);
09630 #endif   /* defined(HAVE_PRI) */
09631    if (!chan_name) {
09632       return NULL;
09633    }
09634 
09635    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));
09636    ast_free(chan_name);
09637    if (!tmp)
09638       return NULL;
09639    tmp->tech = &dahdi_tech;
09640 #if defined(HAVE_PRI)
09641    if (i->pri) {
09642       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09643    }
09644 #endif   /* defined(HAVE_PRI) */
09645    ast_channel_cc_params_init(tmp, i->cc_params);
09646    if (law) {
09647       i->law = law;
09648       if (law == DAHDI_LAW_ALAW) {
09649          deflaw = AST_FORMAT_ALAW;
09650       } else {
09651          deflaw = AST_FORMAT_ULAW;
09652       }
09653    } else {
09654       switch (i->sig) {
09655       case SIG_PRI_LIB_HANDLE_CASES:
09656          /* Make sure companding law is known. */
09657          i->law = (i->law_default == DAHDI_LAW_ALAW)
09658             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09659          break;
09660       default:
09661          i->law = i->law_default;
09662          break;
09663       }
09664       if (i->law_default == DAHDI_LAW_ALAW) {
09665          deflaw = AST_FORMAT_ALAW;
09666       } else {
09667          deflaw = AST_FORMAT_ULAW;
09668       }
09669    }
09670    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09671    tmp->nativeformats = deflaw;
09672    /* Start out assuming ulaw since it's smaller :) */
09673    tmp->rawreadformat = deflaw;
09674    tmp->readformat = deflaw;
09675    tmp->rawwriteformat = deflaw;
09676    tmp->writeformat = deflaw;
09677    i->subs[idx].linear = 0;
09678    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09679    features = 0;
09680    if (idx == SUB_REAL) {
09681       if (i->busydetect && CANBUSYDETECT(i))
09682          features |= DSP_FEATURE_BUSY_DETECT;
09683       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09684          features |= DSP_FEATURE_CALL_PROGRESS;
09685       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09686          features |= DSP_FEATURE_WAITDIALTONE;
09687       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09688          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09689          features |= DSP_FEATURE_FAX_DETECT;
09690       }
09691       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09692       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09693          i->hardwaredtmf = 0;
09694          features |= DSP_FEATURE_DIGIT_DETECT;
09695       } else if (NEED_MFDETECT(i)) {
09696          i->hardwaredtmf = 1;
09697          features |= DSP_FEATURE_DIGIT_DETECT;
09698       }
09699    }
09700    if (features) {
09701       if (i->dsp) {
09702          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09703       } else {
09704          if (i->channel != CHAN_PSEUDO)
09705             i->dsp = ast_dsp_new();
09706          else
09707             i->dsp = NULL;
09708          if (i->dsp) {
09709             i->dsp_features = features;
09710 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09711             /* We cannot do progress detection until receive PROGRESS message */
09712             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09713                /* Remember requested DSP features, don't treat
09714                   talking as ANSWER */
09715                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09716                features = 0;
09717             }
09718 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09719             ast_dsp_set_features(i->dsp, features);
09720             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09721             if (!ast_strlen_zero(progzone))
09722                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09723             if (i->busydetect && CANBUSYDETECT(i)) {
09724                if(i->silencethreshold > 0)
09725                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09726                ast_dsp_set_busy_count(i->dsp, i->busycount);
09727                if(i->busytonelength > 0)
09728                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09729                if((i->busytonelength == i->busyquietlength) && i->busycompare)
09730                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09731             }
09732          }
09733       }
09734    }
09735 
09736    if (state == AST_STATE_RING)
09737       tmp->rings = 1;
09738    tmp->tech_pvt = i;
09739    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09740       /* Only FXO signalled stuff can be picked up */
09741       tmp->callgroup = i->callgroup;
09742       tmp->pickupgroup = i->pickupgroup;
09743    }
09744    if (!ast_strlen_zero(i->parkinglot))
09745       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09746    if (!ast_strlen_zero(i->language))
09747       ast_string_field_set(tmp, language, i->language);
09748    if (!i->owner)
09749       i->owner = tmp;
09750    if (!ast_strlen_zero(i->accountcode))
09751       ast_string_field_set(tmp, accountcode, i->accountcode);
09752    if (i->amaflags)
09753       tmp->amaflags = i->amaflags;
09754    i->subs[idx].owner = tmp;
09755    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09756    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09757       ast_string_field_set(tmp, call_forward, i->call_forward);
09758    }
09759    /* If we've been told "no ADSI" then enforce it */
09760    if (!i->adsi)
09761       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09762    if (!ast_strlen_zero(i->exten))
09763       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09764    if (!ast_strlen_zero(i->rdnis)) {
09765       tmp->redirecting.from.number.valid = 1;
09766       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09767    }
09768    if (!ast_strlen_zero(i->dnid)) {
09769       tmp->dialed.number.str = ast_strdup(i->dnid);
09770    }
09771 
09772    /* Don't use ast_set_callerid() here because it will
09773     * generate a needless NewCallerID event */
09774 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09775    if (!ast_strlen_zero(i->cid_ani)) {
09776       tmp->caller.ani.number.valid = 1;
09777       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09778    } else if (!ast_strlen_zero(i->cid_num)) {
09779       tmp->caller.ani.number.valid = 1;
09780       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09781    }
09782 #else
09783    if (!ast_strlen_zero(i->cid_num)) {
09784       tmp->caller.ani.number.valid = 1;
09785       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09786    }
09787 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09788    tmp->caller.id.name.presentation = i->callingpres;
09789    tmp->caller.id.number.presentation = i->callingpres;
09790    tmp->caller.id.number.plan = i->cid_ton;
09791    tmp->caller.ani2 = i->cid_ani2;
09792    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09793    /* clear the fake event in case we posted one before we had ast_channel */
09794    i->fake_event = 0;
09795    /* Assure there is no confmute on this channel */
09796    dahdi_confmute(i, 0);
09797    i->muting = 0;
09798    /* Configure the new channel jb */
09799    ast_jb_configure(tmp, &global_jbconf);
09800 
09801    /* Set initial device state */
09802    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09803    dashptr = strrchr(device_name, '-');
09804    if (dashptr) {
09805       *dashptr = '\0';
09806    }
09807    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09808 
09809    for (v = i->vars ; v ; v = v->next)
09810       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09811 
09812    ast_module_ref(ast_module_info->self);
09813 
09814    dahdi_ami_channel_event(i, tmp);
09815    if (startpbx) {
09816 #ifdef HAVE_OPENR2
09817       if (i->mfcr2call) {
09818          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09819       }
09820 #endif
09821       if (ast_pbx_start(tmp)) {
09822          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09823          ast_hangup(tmp);
09824          return NULL;
09825       }
09826    }
09827    return tmp;
09828 }

static int dahdi_new_pri_nobch_channel ( struct sig_pri_span pri  )  [static]

Definition at line 13312 of file chan_dahdi.c.

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

13313 {
13314    int pvt_idx;
13315    int res;
13316    unsigned idx;
13317    struct dahdi_pvt *pvt;
13318    struct sig_pri_chan *chan;
13319    struct dahdi_bufferinfo bi;
13320 
13321    static int nobch_channel = CHAN_PSEUDO;
13322 
13323    /* Find spot in the private pointer array for new interface. */
13324    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13325       if (!pri->pvts[pvt_idx]) {
13326          break;
13327       }
13328    }
13329    if (pri->numchans == pvt_idx) {
13330       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13331          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13332          return -1;
13333       }
13334 
13335       /* Add new spot to the private pointer array. */
13336       pri->pvts[pvt_idx] = NULL;
13337       ++pri->numchans;
13338    }
13339 
13340    pvt = ast_calloc(1, sizeof(*pvt));
13341    if (!pvt) {
13342       return -1;
13343    }
13344    pvt->cc_params = ast_cc_config_params_init();
13345    if (!pvt->cc_params) {
13346       ast_free(pvt);
13347       return -1;
13348    }
13349    ast_mutex_init(&pvt->lock);
13350    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13351       pvt->subs[idx].dfd = -1;
13352    }
13353    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13354    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13355    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13356    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13357 
13358    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13359    if (!chan) {
13360       destroy_dahdi_pvt(pvt);
13361       return -1;
13362    }
13363    chan->no_b_channel = 1;
13364 
13365    /*
13366     * Pseudo channel companding law.
13367     * Needed for outgoing call waiting calls.
13368     * XXX May need to make this determined by switchtype or user option.
13369     */
13370    pvt->law_default = DAHDI_LAW_ALAW;
13371 
13372    pvt->sig = pri->sig;
13373    pvt->outsigmod = -1;
13374    pvt->pri = pri;
13375    pvt->sig_pvt = chan;
13376    pri->pvts[pvt_idx] = chan;
13377 
13378    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13379    if (pvt->subs[SUB_REAL].dfd < 0) {
13380       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13381          strerror(errno));
13382       destroy_dahdi_pvt(pvt);
13383       return -1;
13384    }
13385    memset(&bi, 0, sizeof(bi));
13386    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13387    if (!res) {
13388       pvt->bufsize = bi.bufsize;
13389       bi.txbufpolicy = pvt->buf_policy;
13390       bi.rxbufpolicy = pvt->buf_policy;
13391       bi.numbufs = pvt->buf_no;
13392       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13393       if (res < 0) {
13394          ast_log(LOG_WARNING,
13395             "Unable to set buffer policy on no B channel interface: %s\n",
13396             strerror(errno));
13397       }
13398    } else
13399       ast_log(LOG_WARNING,
13400          "Unable to check buffer policy on no B channel interface: %s\n",
13401          strerror(errno));
13402 
13403    --nobch_channel;
13404    if (CHAN_PSEUDO < nobch_channel) {
13405       nobch_channel = CHAN_PSEUDO - 1;
13406    }
13407    pvt->channel = nobch_channel;
13408    pvt->span = pri->span;
13409    chan->channel = pvt->channel;
13410 
13411    dahdi_nobch_insert(pri, pvt);
13412 
13413    return pvt_idx;
13414 }

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

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

05649 {
05650    /* Extract from the forward chain. */
05651    if (pvt->prev) {
05652       pvt->prev->next = pvt->next;
05653    } else if (pri->no_b_chan_iflist == pvt) {
05654       /* Node is at the head of the list. */
05655       pri->no_b_chan_iflist = pvt->next;
05656    }
05657 
05658    /* Extract from the reverse chain. */
05659    if (pvt->next) {
05660       pvt->next->prev = pvt->prev;
05661    } else if (pri->no_b_chan_end == pvt) {
05662       /* Node is at the end of the list. */
05663       pri->no_b_chan_end = pvt->prev;
05664    }
05665 
05666    /* Node is no longer in the list. */
05667    pvt->which_iflist = DAHDI_IFLIST_NONE;
05668    pvt->prev = NULL;
05669    pvt->next = NULL;
05670 }

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

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

05596 {
05597    struct dahdi_pvt *cur;
05598 
05599    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05600 
05601    /* Find place in middle of list for the new interface. */
05602    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05603       if (pvt->channel < cur->channel) {
05604          /* New interface goes before the current interface. */
05605          pvt->prev = cur->prev;
05606          pvt->next = cur;
05607          if (cur->prev) {
05608             /* Insert into the middle of the list. */
05609             cur->prev->next = pvt;
05610          } else {
05611             /* Insert at head of list. */
05612             pri->no_b_chan_iflist = pvt;
05613          }
05614          cur->prev = pvt;
05615          return;
05616       }
05617    }
05618 
05619    /* New interface goes onto the end of the list */
05620    pvt->prev = pri->no_b_chan_end;
05621    pvt->next = NULL;
05622    if (pri->no_b_chan_end) {
05623       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05624    }
05625    pri->no_b_chan_end = pvt;
05626    if (!pri->no_b_chan_iflist) {
05627       /* List was empty */
05628       pri->no_b_chan_iflist = pvt;
05629    }
05630 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4312 of file chan_dahdi.c.

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

Referenced by alloc_sub(), and duplicate_pseudo().

04313 {
04314    int fd;
04315    int isnum;
04316    int chan = 0;
04317    int bs;
04318    int x;
04319    isnum = 1;
04320    for (x = 0; x < strlen(fn); x++) {
04321       if (!isdigit(fn[x])) {
04322          isnum = 0;
04323          break;
04324       }
04325    }
04326    if (isnum) {
04327       chan = atoi(fn);
04328       if (chan < 1) {
04329          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04330          return -1;
04331       }
04332       fn = "/dev/dahdi/channel";
04333    }
04334    fd = open(fn, O_RDWR | O_NONBLOCK);
04335    if (fd < 0) {
04336       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04337       return -1;
04338    }
04339    if (chan) {
04340       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04341          x = errno;
04342          close(fd);
04343          errno = x;
04344          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04345          return -1;
04346       }
04347    }
04348    bs = READ_SIZE;
04349    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04350       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04351       x = errno;
04352       close(fd);
04353       errno = x;
04354       return -1;
04355    }
04356    return fd;
04357 }

static void dahdi_pri_cc_agent_destructor ( struct ast_cc_agent agent  )  [static]

Definition at line 16660 of file chan_dahdi.c.

References ast_module_unref(), and sig_pri_cc_agent_destructor().

16661 {
16662    sig_pri_cc_agent_destructor(agent);
16663 
16664    ast_module_unref(ast_module_info->self);
16665 }

static int dahdi_pri_cc_agent_init ( struct ast_cc_agent agent,
struct ast_channel chan 
) [static]

Definition at line 16616 of file chan_dahdi.c.

References ast_assert, ast_module_ref(), ast_module_unref(), dahdi_sig_pri_lib_handles(), dahdi_pvt::sig, sig_pri_cc_agent_init(), dahdi_pvt::sig_pvt, ast_channel::tech, ast_channel::tech_pvt, and ast_channel_tech::type.

16617 {
16618    struct dahdi_pvt *pvt;
16619    struct sig_pri_chan *pvt_chan;
16620    int res;
16621 
16622    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16623 
16624    pvt = chan->tech_pvt;
16625    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16626       pvt_chan = pvt->sig_pvt;
16627    } else {
16628       pvt_chan = NULL;
16629    }
16630    if (!pvt_chan) {
16631       return -1;
16632    }
16633 
16634    ast_module_ref(ast_module_info->self);
16635 
16636    res = sig_pri_cc_agent_init(agent, pvt_chan);
16637    if (res) {
16638       ast_module_unref(ast_module_info->self);
16639    }
16640    return res;
16641 }

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

Definition at line 14136 of file chan_dahdi.c.

References pris.

Referenced by load_module().

14137 {
14138    int x;
14139    int y;
14140    int dchan = -1;
14141    int span = -1;
14142    int dchancount = 0;
14143 
14144    if (pri) {
14145       for (x = 0; x < NUM_SPANS; x++) {
14146          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14147             if (pris[x].pri.dchans[y]) {
14148                dchancount++;
14149             }
14150 
14151             if (pris[x].pri.dchans[y] == pri) {
14152                dchan = y;
14153             }
14154          }
14155          if (dchan >= 0) {
14156             span = x;
14157             break;
14158          }
14159          dchancount = 0;
14160       }
14161       if (-1 < span) {
14162          if (1 < dchancount) {
14163             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14164          } else {
14165             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14166          }
14167       } else {
14168          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14169       }
14170    } else {
14171       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14172    }
14173 
14174    ast_mutex_lock(&pridebugfdlock);
14175 
14176    if (pridebugfd >= 0) {
14177       if (write(pridebugfd, s, strlen(s)) < 0) {
14178          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14179       }
14180    }
14181 
14182    ast_mutex_unlock(&pridebugfdlock);
14183 }

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

Definition at line 14085 of file chan_dahdi.c.

References pris.

Referenced by load_module().

14086 {
14087    int x;
14088    int y;
14089    int dchan = -1;
14090    int span = -1;
14091    int dchancount = 0;
14092 
14093    if (pri) {
14094       for (x = 0; x < NUM_SPANS; x++) {
14095          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14096             if (pris[x].pri.dchans[y]) {
14097                dchancount++;
14098             }
14099 
14100             if (pris[x].pri.dchans[y] == pri) {
14101                dchan = y;
14102             }
14103          }
14104          if (dchan >= 0) {
14105             span = x;
14106             break;
14107          }
14108          dchancount = 0;
14109       }
14110       if (-1 < span) {
14111          if (1 < dchancount) {
14112             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14113          } else {
14114             ast_verbose("PRI Span: %d %s", span + 1, s);
14115          }
14116       } else {
14117          ast_verbose("PRI Span: ? %s", s);
14118       }
14119    } else {
14120       ast_verbose("PRI Span: ? %s", s);
14121    }
14122 
14123    ast_mutex_lock(&pridebugfdlock);
14124 
14125    if (pridebugfd >= 0) {
14126       if (write(pridebugfd, s, strlen(s)) < 0) {
14127          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14128       }
14129    }
14130 
14131    ast_mutex_unlock(&pridebugfdlock);
14132 }

static void dahdi_pri_update_span_devstate ( struct sig_pri_span pri  )  [static]

Definition at line 3301 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, sig_pri_chan::inalarm, sig_pri_chan::no_b_channel, sig_pri_span::numchans, dahdi_pvt::pri, sig_pri_span::pvts, sig_pri_is_chan_available(), and sig_pri_span::span.

03302 {
03303    unsigned idx;
03304    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03305    unsigned in_use;     /* Number of B channels in use on the span. */
03306    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03307    enum ast_device_state new_state;
03308 
03309    /* Count the number of B channels and the number of B channels in use. */
03310    num_b_chans = 0;
03311    in_use = 0;
03312    in_alarm = 1;
03313    for (idx = pri->numchans; idx--;) {
03314       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03315          /* This is a B channel interface. */
03316          ++num_b_chans;
03317          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03318             ++in_use;
03319          }
03320          if (!pri->pvts[idx]->inalarm) {
03321             /* There is a channel that is not in alarm. */
03322             in_alarm = 0;
03323          }
03324       }
03325    }
03326 
03327    /* Update the span congestion device state and report any change. */
03328    if (in_alarm) {
03329       new_state = AST_DEVICE_UNAVAILABLE;
03330    } else {
03331       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03332    }
03333    if (pri->congestion_devstate != new_state) {
03334       pri->congestion_devstate = new_state;
03335       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03336    }
03337 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03338    /* Update the span threshold device state and report any change. */
03339    if (in_alarm) {
03340       new_state = AST_DEVICE_UNAVAILABLE;
03341    } else if (!in_use) {
03342       new_state = AST_DEVICE_NOT_INUSE;
03343    } else if (!pri->user_busy_threshold) {
03344       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03345    } else {
03346       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03347          : AST_DEVICE_BUSY;
03348    }
03349    if (pri->threshold_devstate != new_state) {
03350       pri->threshold_devstate = new_state;
03351       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03352    }
03353 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03354 }

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

Definition at line 6677 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_pri_cc_type, 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.

06678 {
06679    char *cp;
06680    struct dahdi_pvt *p = chan->tech_pvt;
06681 
06682    /* all supported options require data */
06683    if (!p || !data || (*datalen < 1)) {
06684       errno = EINVAL;
06685       return -1;
06686    }
06687 
06688    switch (option) {
06689    case AST_OPTION_DIGIT_DETECT:
06690       cp = (char *) data;
06691       *cp = p->ignoredtmf ? 0 : 1;
06692       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06693       break;
06694    case AST_OPTION_FAX_DETECT:
06695       cp = (char *) data;
06696       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06697       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06698       break;
06699    case AST_OPTION_CC_AGENT_TYPE:
06700 #if defined(HAVE_PRI)
06701 #if defined(HAVE_PRI_CCSS)
06702       if (dahdi_sig_pri_lib_handles(p->sig)) {
06703          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06704          break;
06705       }
06706 #endif   /* defined(HAVE_PRI_CCSS) */
06707 #endif   /* defined(HAVE_PRI) */
06708       return -1;
06709    default:
06710       return -1;
06711    }
06712 
06713    errno = 0;
06714 
06715    return 0;
06716 }

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

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

03801 {
03802    for (;;) {
03803       if (p->owner) {
03804          if (ast_channel_trylock(p->owner)) {
03805             DEADLOCK_AVOIDANCE(&p->lock);
03806          } else {
03807             ast_queue_frame(p->owner, f);
03808             ast_channel_unlock(p->owner);
03809             break;
03810          }
03811       } else
03812          break;
03813    }
03814 }

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

Definition at line 4267 of file chan_dahdi.c.

References AST_ALAW.

04268 {
04269    return AST_ALAW(sample);
04270 }

static int dahdi_r2_answer ( struct dahdi_pvt p  )  [static]

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

03837 {
03838    int res = 0;
03839    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03840    * and does not has support for openr2_chan_answer_call_with_mode
03841    *  */
03842 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03843    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03844    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03845    if (!double_answer) {
03846       /* this still can result in double answer if the channel context
03847       * was configured that way */
03848       res = openr2_chan_answer_call(p->r2chan);
03849    } else if (wants_double_answer) {
03850       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03851    } else {
03852       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03853    }
03854 #else
03855    res = openr2_chan_answer_call(p->r2chan);
03856 #endif
03857    return res;
03858 }

static int dahdi_r2_cause_to_ast_cause ( openr2_call_disconnect_cause_t  cause  )  [static]

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

04078 {
04079    switch (cause) {
04080    case OR2_CAUSE_BUSY_NUMBER:
04081       return AST_CAUSE_BUSY;
04082    case OR2_CAUSE_NETWORK_CONGESTION:
04083       return AST_CAUSE_CONGESTION;
04084    case OR2_CAUSE_OUT_OF_ORDER:
04085       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04086    case OR2_CAUSE_UNALLOCATED_NUMBER:
04087       return AST_CAUSE_UNREGISTERED;
04088    case OR2_CAUSE_NO_ANSWER:
04089       return AST_CAUSE_NO_ANSWER;
04090    case OR2_CAUSE_NORMAL_CLEARING:
04091       return AST_CAUSE_NORMAL_CLEARING;
04092    case OR2_CAUSE_UNSPECIFIED:
04093    default:
04094       return AST_CAUSE_NOTDEFINED;
04095    }
04096 }

static void dahdi_r2_destroy_links ( void   )  [static]

Definition at line 12138 of file chan_dahdi.c.

References ast_free, AST_PTHREADT_NULL, r2links, and r2links_count.

Referenced by __unload_module(), and dahdi_restart().

12139 {
12140    int i = 0;
12141    if (!r2links) {
12142       return;
12143    }
12144    for (; i < r2links_count; i++) {
12145       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12146          pthread_cancel(r2links[i]->r2master);
12147          pthread_join(r2links[i]->r2master, NULL);
12148          openr2_context_delete(r2links[i]->protocol_context);
12149       }
12150       ast_free(r2links[i]);
12151    }
12152    ast_free(r2links);
12153    r2links = NULL;
12154    r2links_count = 0;
12155 }

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

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

03946 {
03947    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03948       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03949          p->channel, openr2_proto_get_disconnect_string(cause));
03950       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03951       openr2_chan_set_idle(p->r2chan);
03952       ast_mutex_lock(&p->lock);
03953       p->mfcr2call = 0;
03954       ast_mutex_unlock(&p->lock);
03955    }
03956 }

static openr2_calling_party_category_t dahdi_r2_get_channel_category ( struct ast_channel c  )  [static]

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

03864 {
03865    openr2_calling_party_category_t cat;
03866    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03867    struct dahdi_pvt *p = c->tech_pvt;
03868    if (ast_strlen_zero(catstr)) {
03869       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03870             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03871       return p->mfcr2_category;
03872    }
03873    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03874       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03875             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03876       return p->mfcr2_category;
03877    }
03878    ast_debug(1, "Using category %s\n", catstr);
03879    return cat;
03880 }

static struct dahdi_mfcr2* dahdi_r2_get_link ( void   )  [static]

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

12159 {
12160    struct dahdi_mfcr2 *new_r2link = NULL;
12161    struct dahdi_mfcr2 **new_r2links = NULL;
12162    /* this function is called just when starting up and no monitor threads have been launched,
12163       no need to lock monitored_count member */
12164    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12165       new_r2link = ast_calloc(1, sizeof(**r2links));
12166       if (!new_r2link) {
12167          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12168          return NULL;
12169       }
12170       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12171       if (!new_r2links) {
12172          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12173          ast_free(new_r2link);
12174          return NULL;
12175       }
12176       r2links = new_r2links;
12177       new_r2link->r2master = AST_PTHREADT_NULL;
12178       r2links[r2links_count] = new_r2link;
12179       r2links_count++;
12180       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12181    }
12182    return r2links[r2links_count - 1];
12183 }

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

Definition at line 4272 of file chan_dahdi.c.

References AST_LIN2A.

04273 {
04274    return AST_LIN2A(sample);
04275 }

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

Definition at line 4231 of file chan_dahdi.c.

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

04232 {
04233    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04234    p->cid_num[p->mfcr2_ani_index] = digit;
04235    p->cid_name[p->mfcr2_ani_index] = digit;
04236    p->mfcr2_ani_index++;
04237    p->cid_num[p->mfcr2_ani_index] = 0;
04238    p->cid_name[p->mfcr2_ani_index] = 0;
04239 }

static void dahdi_r2_on_billing_pulse_received ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4241 of file chan_dahdi.c.

References ast_verbose.

04242 {
04243    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04244 }

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

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

04024 {
04025    struct dahdi_pvt *p = NULL;
04026    struct ast_channel *c = NULL;
04027    p = openr2_chan_get_client_data(r2chan);
04028    dahdi_enable_ec(p);
04029    p->mfcr2_call_accepted = 1;
04030    /* if it's an incoming call ... */
04031    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04032       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04033       /* If accept on offer is not set, it means at this point the PBX thread is already
04034          launched (was launched in the 'on call offered' handler) and therefore this callback
04035          is being executed already in the PBX thread rather than the monitor thread, don't launch
04036          any other thread, just disable the openr2 reading and answer the call if needed */
04037       if (!p->mfcr2_accept_on_offer) {
04038          openr2_chan_disable_read(r2chan);
04039          if (p->mfcr2_answer_pending) {
04040             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04041             dahdi_r2_answer(p);
04042          }
04043          return;
04044       }
04045       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04046       if (c) {
04047          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04048             library to forget about it */
04049          openr2_chan_disable_read(r2chan);
04050          return;
04051       }
04052       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04053       /* failed to create the channel, bail out and report it as an out of order line */
04054       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04055       return;
04056    }
04057    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04058    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04059    p->subs[SUB_REAL].needringing = 1;
04060    p->dialing = 0;
04061    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04062    openr2_chan_disable_read(r2chan);
04063 }

static void dahdi_r2_on_call_answered ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4065 of file chan_dahdi.c.

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

04066 {
04067    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04068    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04069    p->subs[SUB_REAL].needanswer = 1;
04070 }

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

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

04099 {
04100    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04101    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04102    ast_mutex_lock(&p->lock);
04103    if (!p->owner) {
04104       ast_mutex_unlock(&p->lock);
04105       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04106       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04107       return;
04108    }
04109    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04110       be done in dahdi_hangup */
04111    if (p->owner->_state == AST_STATE_UP) {
04112       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04113       ast_mutex_unlock(&p->lock);
04114    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04115       /* being the forward side we must report what happened to the call to whoever requested it */
04116       switch (cause) {
04117       case OR2_CAUSE_BUSY_NUMBER:
04118          p->subs[SUB_REAL].needbusy = 1;
04119          break;
04120       case OR2_CAUSE_NETWORK_CONGESTION:
04121       case OR2_CAUSE_OUT_OF_ORDER:
04122       case OR2_CAUSE_UNALLOCATED_NUMBER:
04123       case OR2_CAUSE_NO_ANSWER:
04124       case OR2_CAUSE_UNSPECIFIED:
04125       case OR2_CAUSE_NORMAL_CLEARING:
04126          p->subs[SUB_REAL].needcongestion = 1;
04127          break;
04128       default:
04129          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04130       }
04131       ast_mutex_unlock(&p->lock);
04132    } else {
04133       ast_mutex_unlock(&p->lock);
04134       /* being the backward side and not UP yet, we only need to request hangup */
04135       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04136       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04137    }
04138 }

static void dahdi_r2_on_call_end ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4013 of file chan_dahdi.c.

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

04014 {
04015    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04016    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04017    ast_mutex_lock(&p->lock);
04018    p->mfcr2call = 0;
04019    ast_mutex_unlock(&p->lock);
04020 }

static void dahdi_r2_on_call_init ( openr2_chan_t *  r2chan  )  [static]

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

03883 {
03884    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03885    ast_mutex_lock(&p->lock);
03886    if (p->mfcr2call) {
03887       ast_mutex_unlock(&p->lock);
03888       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03889          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03890          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03891          the other end will see our seize as a forced release and drop the call, we will see an invalid
03892          pattern that will be seen and treated as protocol error. */
03893       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03894       return;
03895    }
03896    p->mfcr2call = 1;
03897    /* better safe than sorry ... */
03898    p->cid_name[0] = '\0';
03899    p->cid_num[0] = '\0';
03900    p->cid_subaddr[0] = '\0';
03901    p->rdnis[0] = '\0';
03902    p->exten[0] = '\0';
03903    p->mfcr2_ani_index = '\0';
03904    p->mfcr2_dnis_index = '\0';
03905    p->mfcr2_dnis_matched = 0;
03906    p->mfcr2_answer_pending = 0;
03907    p->mfcr2_call_accepted = 0;
03908    ast_mutex_unlock(&p->lock);
03909    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03910 }

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

03959 {
03960    struct dahdi_pvt *p;
03961    struct ast_channel *c;
03962    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03963          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03964          openr2_proto_get_category_string(category));
03965    p = openr2_chan_get_client_data(r2chan);
03966    /* if collect calls are not allowed and this is a collect call, reject it! */
03967    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03968       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03969       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03970       return;
03971    }
03972    ast_mutex_lock(&p->lock);
03973    p->mfcr2_recvd_category = category;
03974    /* if we're not supposed to use CID, clear whatever we have */
03975    if (!p->use_callerid) {
03976       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03977       p->cid_num[0] = 0;
03978       p->cid_name[0] = 0;
03979    }
03980    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03981    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03982       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03983       p->exten[0] = 's';
03984       p->exten[1] = 0;
03985    }
03986    ast_mutex_unlock(&p->lock);
03987    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03988       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03989             p->channel, p->exten, p->context);
03990       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03991       return;
03992    }
03993    if (!p->mfcr2_accept_on_offer) {
03994       /* The user wants us to start the PBX thread right away without accepting the call first */
03995       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03996       if (c) {
03997          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03998             the call or reject it and detect the tone off condition of the other end, all of this
03999             will be done in the PBX thread now */
04000          return;
04001       }
04002       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04003       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04004    } else if (p->mfcr2_charge_calls) {
04005       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04006       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04007    } else {
04008       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04009       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04010    }
04011 }

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

Definition at line 4072 of file chan_dahdi.c.

04073 {
04074    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04075 }

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

References CHAN_TAG, and dahdi_r2_write_log().

04200 {
04201 #define CHAN_TAG "Chan "
04202    char logmsg[256];
04203    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04204    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04205    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04206    dahdi_r2_write_log(level, completemsg);
04207 }

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

References CONTEXT_TAG, and dahdi_r2_write_log().

04187 {
04188 #define CONTEXT_TAG "Context - "
04189    char logmsg[256];
04190    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04191    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04192    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04193    dahdi_r2_write_log(level, completemsg);
04194 #undef CONTEXT_TAG
04195 }

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

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

04210 {
04211    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04212    /* if 'immediate' is set, let's stop requesting DNIS */
04213    if (p->immediate) {
04214       return 0;
04215    }
04216    p->exten[p->mfcr2_dnis_index] = digit;
04217    p->rdnis[p->mfcr2_dnis_index] = digit;
04218    p->mfcr2_dnis_index++;
04219    p->exten[p->mfcr2_dnis_index] = 0;
04220    p->rdnis[p->mfcr2_dnis_index] = 0;
04221    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04222    if ((p->mfcr2_dnis_matched ||
04223        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04224        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04225       return 0;
04226    }
04227    /* otherwise keep going */
04228    return 1;
04229 }

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

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

03913 {
03914    int res;
03915    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03916    ast_mutex_lock(&p->lock);
03917    p->inalarm = alarm ? 1 : 0;
03918    if (p->inalarm) {
03919       res = get_alarms(p);
03920       handle_alarms(p, res);
03921    } else {
03922       handle_clear_alarms(p);
03923    }
03924    ast_mutex_unlock(&p->lock);
03925 }

static void dahdi_r2_on_line_blocked ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4166 of file chan_dahdi.c.

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

04167 {
04168    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04169    ast_mutex_lock(&p->lock);
04170    p->remotelyblocked = 1;
04171    ast_mutex_unlock(&p->lock);
04172    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04173 }

static void dahdi_r2_on_line_idle ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4175 of file chan_dahdi.c.

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

04176 {
04177    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04178    ast_mutex_lock(&p->lock);
04179    p->remotelyblocked = 0;
04180    ast_mutex_unlock(&p->lock);
04181    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04182 }

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

Definition at line 3927 of file chan_dahdi.c.

References ast_log(), and LOG_ERROR.

03928 {
03929    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03930 }

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

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

03933 {
03934    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03935    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03936    if (p->owner) {
03937       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03938       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03939    }
03940    ast_mutex_lock(&p->lock);
03941    p->mfcr2call = 0;
03942    ast_mutex_unlock(&p->lock);
03943 }

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

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

12186 {
12187    char tmplogdir[] = "/tmp";
12188    char logdir[OR2_MAX_PATH];
12189    int threshold = 0;
12190    int snres = 0;
12191    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12192          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12193          conf->mfcr2.max_dnis);
12194    if (!r2_link->protocol_context) {
12195       return -1;
12196    }
12197    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12198    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12199 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12200    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12201 #endif
12202    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12203    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12204    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12205    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12206    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12207    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12208       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12209          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12210       }
12211    } else {
12212       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12213       if (snres >= sizeof(logdir)) {
12214          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12215          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12216             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12217          }
12218       } else {
12219          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12220             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12221          }
12222       }
12223    }
12224    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12225       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12226          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12227       }
12228    }
12229    r2_link->monitored_count = 0;
12230    return 0;
12231 }

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

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

04141 {
04142    switch (level) {
04143    case OR2_LOG_NOTICE:
04144       ast_verbose("%s", logmessage);
04145       break;
04146    case OR2_LOG_WARNING:
04147       ast_log(LOG_WARNING, "%s", logmessage);
04148       break;
04149    case OR2_LOG_ERROR:
04150       ast_log(LOG_ERROR, "%s", logmessage);
04151       break;
04152    case OR2_LOG_STACK_TRACE:
04153    case OR2_LOG_MF_TRACE:
04154    case OR2_LOG_CAS_TRACE:
04155    case OR2_LOG_DEBUG:
04156    case OR2_LOG_EX_DEBUG:
04157       ast_log(LOG_DEBUG, "%s", logmessage);
04158       break;
04159    default:
04160       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04161       ast_log(LOG_DEBUG, "%s", logmessage);
04162       break;
04163    }
04164 }

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

Definition at line 8923 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_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_frfree, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock, ast_mutex_unlock, ast_null_frame, ast_queue_frame(), 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, SIG_PRI_CALL_LEVEL_PROCEEDING, 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.

08924 {
08925    struct dahdi_pvt *p;
08926    int res;
08927    int idx;
08928    void *readbuf;
08929    struct ast_frame *f;
08930 
08931    /*
08932     * For analog channels, we must do deadlock avoidance because
08933     * analog ports can have more than one Asterisk channel using
08934     * the same private structure.
08935     */
08936    p = ast->tech_pvt;
08937    while (ast_mutex_trylock(&p->lock)) {
08938       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08939 
08940       /*
08941        * For PRI channels, we must refresh the private pointer because
08942        * the call could move to another B channel while the Asterisk
08943        * channel is unlocked.
08944        */
08945       p = ast->tech_pvt;
08946    }
08947 
08948    idx = dahdi_get_index(ast, p, 0);
08949 
08950    /* Hang up if we don't really exist */
08951    if (idx < 0)   {
08952       ast_log(LOG_WARNING, "We don't exist?\n");
08953       ast_mutex_unlock(&p->lock);
08954       return NULL;
08955    }
08956 
08957    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08958       ast_mutex_unlock(&p->lock);
08959       return NULL;
08960    }
08961 
08962    p->subs[idx].f.frametype = AST_FRAME_NULL;
08963    p->subs[idx].f.datalen = 0;
08964    p->subs[idx].f.samples = 0;
08965    p->subs[idx].f.mallocd = 0;
08966    p->subs[idx].f.offset = 0;
08967    p->subs[idx].f.subclass.integer = 0;
08968    p->subs[idx].f.delivery = ast_tv(0,0);
08969    p->subs[idx].f.src = "dahdi_read";
08970    p->subs[idx].f.data.ptr = NULL;
08971 
08972    /* make sure it sends initial key state as first frame */
08973    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08974    {
08975       struct dahdi_params ps;
08976 
08977       memset(&ps, 0, sizeof(ps));
08978       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08979          ast_mutex_unlock(&p->lock);
08980          return NULL;
08981       }
08982       p->firstradio = 1;
08983       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08984       if (ps.rxisoffhook)
08985       {
08986          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08987       }
08988       else
08989       {
08990          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08991       }
08992       ast_mutex_unlock(&p->lock);
08993       return &p->subs[idx].f;
08994    }
08995    if (p->ringt > 0) {
08996       if (!(--p->ringt)) {
08997          ast_mutex_unlock(&p->lock);
08998          return NULL;
08999       }
09000    }
09001 
09002 #ifdef HAVE_OPENR2
09003    if (p->mfcr2) {
09004       openr2_chan_process_event(p->r2chan);
09005       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09006          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09007          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09008           * now enqueue a progress frame to bridge the media up */
09009          if (p->mfcr2_call_accepted &&
09010              !p->mfcr2_progress && 
09011              ast->_state == AST_STATE_RINGING) {
09012             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09013             ast_queue_frame(p->owner, &f);
09014             p->mfcr2_progress = 1;
09015          }
09016       }
09017    }
09018 #endif
09019 
09020    if (p->subs[idx].needringing) {
09021       /* Send ringing frame if requested */
09022       p->subs[idx].needringing = 0;
09023       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09024       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09025       ast_setstate(ast, AST_STATE_RINGING);
09026       ast_mutex_unlock(&p->lock);
09027       return &p->subs[idx].f;
09028    }
09029 
09030    if (p->subs[idx].needbusy) {
09031       /* Send busy frame if requested */
09032       p->subs[idx].needbusy = 0;
09033       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09034       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09035       ast_mutex_unlock(&p->lock);
09036       return &p->subs[idx].f;
09037    }
09038 
09039    if (p->subs[idx].needcongestion) {
09040       /* Send congestion frame if requested */
09041       p->subs[idx].needcongestion = 0;
09042       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09043       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09044       ast_mutex_unlock(&p->lock);
09045       return &p->subs[idx].f;
09046    }
09047 
09048    if (p->subs[idx].needanswer) {
09049       /* Send answer frame if requested */
09050       p->subs[idx].needanswer = 0;
09051       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09052       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09053       ast_mutex_unlock(&p->lock);
09054       return &p->subs[idx].f;
09055    }
09056 #ifdef HAVE_OPENR2
09057    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09058       /* openr2 took care of reading and handling any event
09059         (needanswer, needbusy etc), if we continue we will read()
09060         twice, lets just return a null frame. This should only
09061         happen when openr2 is dialing out */
09062       ast_mutex_unlock(&p->lock);
09063       return &ast_null_frame;
09064    }
09065 #endif
09066 
09067    if (p->subs[idx].needflash) {
09068       /* Send answer frame if requested */
09069       p->subs[idx].needflash = 0;
09070       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09071       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09072       ast_mutex_unlock(&p->lock);
09073       return &p->subs[idx].f;
09074    }
09075 
09076    if (p->subs[idx].needhold) {
09077       /* Send answer frame if requested */
09078       p->subs[idx].needhold = 0;
09079       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09080       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09081       ast_mutex_unlock(&p->lock);
09082       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09083       return &p->subs[idx].f;
09084    }
09085 
09086    if (p->subs[idx].needunhold) {
09087       /* Send answer frame if requested */
09088       p->subs[idx].needunhold = 0;
09089       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09090       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09091       ast_mutex_unlock(&p->lock);
09092       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09093       return &p->subs[idx].f;
09094    }
09095 
09096    /*
09097     * If we have a fake_event, fake an exception to handle it only
09098     * if this channel owns the private.
09099     */
09100    if (p->fake_event && p->owner == ast) {
09101       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09102          struct analog_pvt *analog_p = p->sig_pvt;
09103 
09104          f = analog_exception(analog_p, ast);
09105       } else {
09106          f = __dahdi_exception(ast);
09107       }
09108       ast_mutex_unlock(&p->lock);
09109       return f;
09110    }
09111 
09112    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09113       if (!p->subs[idx].linear) {
09114          p->subs[idx].linear = 1;
09115          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09116          if (res)
09117             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09118       }
09119    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09120       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09121       if (p->subs[idx].linear) {
09122          p->subs[idx].linear = 0;
09123          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09124          if (res)
09125             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09126       }
09127    } else {
09128       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09129       ast_mutex_unlock(&p->lock);
09130       return NULL;
09131    }
09132    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09133    CHECK_BLOCKING(ast);
09134    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09135    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09136    /* Check for hangup */
09137    if (res < 0) {
09138       f = NULL;
09139       if (res == -1) {
09140          if (errno == EAGAIN) {
09141             /* Return "NULL" frame if there is nobody there */
09142             ast_mutex_unlock(&p->lock);
09143             return &p->subs[idx].f;
09144          } else if (errno == ELAST) {
09145             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09146                struct analog_pvt *analog_p = p->sig_pvt;
09147                f = analog_exception(analog_p, ast);
09148             } else {
09149                f = __dahdi_exception(ast);
09150             }
09151          } else
09152             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09153       }
09154       ast_mutex_unlock(&p->lock);
09155       return f;
09156    }
09157    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09158       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09159       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09160          struct analog_pvt *analog_p = p->sig_pvt;
09161          f = analog_exception(analog_p, ast);
09162       } else {
09163          f = __dahdi_exception(ast);
09164       }
09165       ast_mutex_unlock(&p->lock);
09166       return f;
09167    }
09168    if (p->tdd) { /* if in TDD mode, see if we receive that */
09169       int c;
09170 
09171       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09172       if (c < 0) {
09173          ast_debug(1,"tdd_feed failed\n");
09174          ast_mutex_unlock(&p->lock);
09175          return NULL;
09176       }
09177       if (c) { /* if a char to return */
09178          p->subs[idx].f.subclass.integer = 0;
09179          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09180          p->subs[idx].f.mallocd = 0;
09181          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09182          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09183          p->subs[idx].f.datalen = 1;
09184          *((char *) p->subs[idx].f.data.ptr) = c;
09185          ast_mutex_unlock(&p->lock);
09186          return &p->subs[idx].f;
09187       }
09188    }
09189    if (idx == SUB_REAL) {
09190       /* Ensure the CW timers decrement only on a single subchannel */
09191       if (p->cidcwexpire) {
09192          if (!--p->cidcwexpire) {
09193             /* Expired CID/CW */
09194             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09195             restore_conference(p);
09196          }
09197       }
09198       if (p->cid_suppress_expire) {
09199          --p->cid_suppress_expire;
09200       }
09201       if (p->callwaitingrepeat) {
09202          if (!--p->callwaitingrepeat) {
09203             /* Expired, Repeat callwaiting tone */
09204             ++p->callwaitrings;
09205             dahdi_callwait(ast);
09206          }
09207       }
09208    }
09209    if (p->subs[idx].linear) {
09210       p->subs[idx].f.datalen = READ_SIZE * 2;
09211    } else
09212       p->subs[idx].f.datalen = READ_SIZE;
09213 
09214    /* Handle CallerID Transmission */
09215    if ((p->owner == ast) && p->cidspill) {
09216       send_callerid(p);
09217    }
09218 
09219    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09220    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09221    p->subs[idx].f.samples = READ_SIZE;
09222    p->subs[idx].f.mallocd = 0;
09223    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09224    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09225 #if 0
09226    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09227 #endif
09228    if (p->dialing ||  p->radio || /* Transmitting something */
09229       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09230       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09231       ) {
09232       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09233          don't send anything */
09234       p->subs[idx].f.frametype = AST_FRAME_NULL;
09235       p->subs[idx].f.subclass.integer = 0;
09236       p->subs[idx].f.samples = 0;
09237       p->subs[idx].f.mallocd = 0;
09238       p->subs[idx].f.offset = 0;
09239       p->subs[idx].f.data.ptr = NULL;
09240       p->subs[idx].f.datalen= 0;
09241    }
09242    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09243       /* Perform busy detection etc on the dahdi line */
09244       int mute;
09245 
09246       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09247 
09248       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09249       mute = ast_dsp_was_muted(p->dsp);
09250       if (p->muting != mute) {
09251          p->muting = mute;
09252          dahdi_confmute(p, mute);
09253       }
09254 
09255       if (f) {
09256          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09257             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09258                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09259                   a busy */
09260                ast_frfree(f);
09261                f = NULL;
09262             }
09263          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09264             || f->frametype == AST_FRAME_DTMF_END) {
09265 #ifdef HAVE_PRI
09266             if (dahdi_sig_pri_lib_handles(p->sig)
09267                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09268                && p->pri
09269                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09270                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09271                /* Don't accept in-band DTMF when in overlap dial mode */
09272                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09273                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09274                   f->subclass.integer, f->subclass.integer, ast->name);
09275 
09276                f->frametype = AST_FRAME_NULL;
09277                f->subclass.integer = 0;
09278             }
09279 #endif
09280             /* DSP clears us of being pulse */
09281             p->pulsedial = 0;
09282          } else if (p->waitingfordt.tv_sec) {
09283             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09284                p->waitingfordt.tv_sec = 0;
09285                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09286                ast_frfree(f);
09287                f = NULL;
09288             } else if (f->frametype == AST_FRAME_VOICE) {
09289                f->frametype = AST_FRAME_NULL;
09290                f->subclass.integer = 0;
09291                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) {
09292                   p->waitingfordt.tv_sec = 0;
09293                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09294                   ast_dsp_set_features(p->dsp, p->dsp_features);
09295                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09296                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09297                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09298                      if (res < 0) {
09299                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09300                         p->dop.dialstr[0] = '\0';
09301                         ast_mutex_unlock(&p->lock);
09302                         ast_frfree(f);
09303                         return NULL;
09304                      } else {
09305                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09306                         p->dialing = 1;
09307                         p->dop.dialstr[0] = '\0';
09308                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09309                         ast_setstate(ast, AST_STATE_DIALING);
09310                      }
09311                   }
09312                }
09313             }
09314          }
09315       }
09316    } else
09317       f = &p->subs[idx].f;
09318 
09319    if (f) {
09320       switch (f->frametype) {
09321       case AST_FRAME_DTMF_BEGIN:
09322       case AST_FRAME_DTMF_END:
09323          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09324             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09325          } else {
09326             dahdi_handle_dtmf(ast, idx, &f);
09327          }
09328          break;
09329       case AST_FRAME_VOICE:
09330          if (p->cidspill || p->cid_suppress_expire) {
09331             /* We are/were sending a caller id spill.  Suppress any echo. */
09332             p->subs[idx].f.frametype = AST_FRAME_NULL;
09333             p->subs[idx].f.subclass.integer = 0;
09334             p->subs[idx].f.samples = 0;
09335             p->subs[idx].f.mallocd = 0;
09336             p->subs[idx].f.offset = 0;
09337             p->subs[idx].f.data.ptr = NULL;
09338             p->subs[idx].f.datalen= 0;
09339          }
09340          break;
09341       default:
09342          break;
09343       }
09344    }
09345 
09346    ast_mutex_unlock(&p->lock);
09347    return f;
09348 }

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 13647 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, sig_pri_span::num_call_waiting_calls, 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.

13648 {
13649    int callwait = 0;
13650    struct dahdi_pvt *p;
13651    struct ast_channel *tmp = NULL;
13652    struct dahdi_pvt *exitpvt;
13653    int channelmatched = 0;
13654    int groupmatched = 0;
13655 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13656    int transcapdigital = 0;
13657 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13658    struct dahdi_starting_point start;
13659 
13660    ast_mutex_lock(&iflock);
13661    p = determine_starting_point(data, &start);
13662    if (!p) {
13663       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13664       ast_mutex_unlock(&iflock);
13665       return NULL;
13666    }
13667 
13668    /* Search for an unowned channel */
13669    exitpvt = p;
13670    while (p && !tmp) {
13671       if (start.roundrobin)
13672          round_robin[start.rr_starting_point] = p;
13673 
13674       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13675          && available(&p, channelmatched)) {
13676          ast_debug(1, "Using channel %d\n", p->channel);
13677 
13678          callwait = (p->owner != NULL);
13679 #ifdef HAVE_OPENR2
13680          if (p->mfcr2) {
13681             ast_mutex_lock(&p->lock);
13682             if (p->mfcr2call) {
13683                ast_mutex_unlock(&p->lock);
13684                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13685                goto next;
13686             }
13687             p->mfcr2call = 1;
13688             ast_mutex_unlock(&p->lock);
13689          }
13690 #endif
13691          if (p->channel == CHAN_PSEUDO) {
13692             p = duplicate_pseudo(p);
13693             if (!p) {
13694                break;
13695             }
13696          }
13697 
13698          p->distinctivering = 0;
13699          /* Make special notes */
13700          switch (start.opt) {
13701          case '\0':
13702             /* No option present. */
13703             break;
13704          case 'c':
13705             /* Confirm answer */
13706             p->confirmanswer = 1;
13707             break;
13708          case 'r':
13709             /* Distinctive ring */
13710             p->distinctivering = start.cadance;
13711             break;
13712          case 'd':
13713 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13714             /* If this is an ISDN call, make it digital */
13715             transcapdigital = AST_TRANS_CAP_DIGITAL;
13716 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13717             break;
13718          default:
13719             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13720             break;
13721          }
13722 
13723          p->outgoing = 1;
13724          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13725             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13726 #ifdef HAVE_PRI
13727          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13728             /*
13729              * We already have the B channel reserved for this call.  We
13730              * just need to make sure that dahdi_hangup() has completed
13731              * cleaning up before continuing.
13732              */
13733             ast_mutex_lock(&p->lock);
13734             ast_mutex_unlock(&p->lock);
13735 
13736             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13737                sizeof(p->dnid));
13738             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13739 #endif
13740 #if defined(HAVE_SS7)
13741          } else if (p->sig == SIG_SS7) {
13742             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13743 #endif   /* defined(HAVE_SS7) */
13744          } else {
13745             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13746          }
13747          if (!tmp) {
13748             p->outgoing = 0;
13749 #if defined(HAVE_PRI)
13750             switch (p->sig) {
13751             case SIG_PRI_LIB_HANDLE_CASES:
13752 #if defined(HAVE_PRI_CALL_WAITING)
13753                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13754                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13755                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13756                }
13757 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13758                /*
13759                 * This should be the last thing to clear when we are done with
13760                 * the channel.
13761                 */
13762                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13763                break;
13764             default:
13765                break;
13766             }
13767 #endif   /* defined(HAVE_PRI) */
13768          } else {
13769             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13770          }
13771          break;
13772       }
13773 #ifdef HAVE_OPENR2
13774 next:
13775 #endif
13776       if (start.backwards) {
13777          p = p->prev;
13778          if (!p)
13779             p = ifend;
13780       } else {
13781          p = p->next;
13782          if (!p)
13783             p = iflist;
13784       }
13785       /* stop when you roll to the one that we started from */
13786       if (p == exitpvt)
13787          break;
13788    }
13789    ast_mutex_unlock(&iflock);
13790    restart_monitor();
13791    if (cause && !tmp) {
13792       if (callwait || channelmatched) {
13793          *cause = AST_CAUSE_BUSY;
13794       } else if (groupmatched) {
13795          *cause = AST_CAUSE_CONGESTION;
13796       } else {
13797          /*
13798           * We did not match any channel requested.
13799           * Dialplan error requesting non-existant channel?
13800           */
13801       }
13802    }
13803 
13804    return tmp;
13805 }

static int dahdi_restart ( void   )  [static]

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

15082 {
15083 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15084    int i, j;
15085 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15086    int cancel_code;
15087    struct dahdi_pvt *p;
15088 
15089    ast_mutex_lock(&restart_lock);
15090    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15091    dahdi_softhangup_all();
15092    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15093 #ifdef HAVE_OPENR2
15094    dahdi_r2_destroy_links();
15095 #endif
15096 
15097 #if defined(HAVE_PRI)
15098    for (i = 0; i < NUM_SPANS; i++) {
15099       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15100          cancel_code = pthread_cancel(pris[i].pri.master);
15101          pthread_kill(pris[i].pri.master, SIGURG);
15102          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);
15103          pthread_join(pris[i].pri.master, NULL);
15104          ast_debug(4, "Joined thread of span %d\n", i);
15105       }
15106    }
15107 #endif
15108 
15109 #if defined(HAVE_SS7)
15110    for (i = 0; i < NUM_SPANS; i++) {
15111       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15112          cancel_code = pthread_cancel(linksets[i].ss7.master);
15113          pthread_kill(linksets[i].ss7.master, SIGURG);
15114          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);
15115          pthread_join(linksets[i].ss7.master, NULL);
15116          ast_debug(4, "Joined thread of span %d\n", i);
15117       }
15118    }
15119 #endif   /* defined(HAVE_SS7) */
15120 
15121    ast_mutex_lock(&monlock);
15122    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15123       cancel_code = pthread_cancel(monitor_thread);
15124       pthread_kill(monitor_thread, SIGURG);
15125       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15126       pthread_join(monitor_thread, NULL);
15127       ast_debug(4, "Joined monitor thread\n");
15128    }
15129    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15130 
15131    ast_mutex_lock(&ss_thread_lock);
15132    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15133       int x = DAHDI_FLASH;
15134       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15135 
15136       ast_mutex_lock(&iflock);
15137       for (p = iflist; p; p = p->next) {
15138          if (p->owner) {
15139             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15140             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15141          }
15142       }
15143       ast_mutex_unlock(&iflock);
15144       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15145    }
15146 
15147    /* ensure any created channels before monitor threads were stopped are hungup */
15148    dahdi_softhangup_all();
15149    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15150    destroy_all_channels();
15151    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15152 
15153    ast_mutex_unlock(&monlock);
15154 
15155 #ifdef HAVE_PRI
15156    for (i = 0; i < NUM_SPANS; i++) {
15157       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15158          dahdi_close_pri_fd(&(pris[i]), j);
15159    }
15160 
15161    memset(pris, 0, sizeof(pris));
15162    for (i = 0; i < NUM_SPANS; i++) {
15163       sig_pri_init_pri(&pris[i].pri);
15164    }
15165    pri_set_error(dahdi_pri_error);
15166    pri_set_message(dahdi_pri_message);
15167 #endif
15168 #if defined(HAVE_SS7)
15169    for (i = 0; i < NUM_SPANS; i++) {
15170       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15171          dahdi_close_ss7_fd(&(linksets[i]), j);
15172    }
15173 
15174    memset(linksets, 0, sizeof(linksets));
15175    for (i = 0; i < NUM_SPANS; i++) {
15176       sig_ss7_init_linkset(&linksets[i].ss7);
15177    }
15178    ss7_set_error(dahdi_ss7_error);
15179    ss7_set_message(dahdi_ss7_message);
15180 #endif   /* defined(HAVE_SS7) */
15181 
15182    if (setup_dahdi(2) != 0) {
15183       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15184       ast_mutex_unlock(&ss_thread_lock);
15185       return 1;
15186    }
15187    ast_mutex_unlock(&ss_thread_lock);
15188    ast_mutex_unlock(&restart_lock);
15189    return 0;
15190 }

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

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

15193 {
15194    switch (cmd) {
15195    case CLI_INIT:
15196       e->command = "dahdi restart";
15197       e->usage =
15198          "Usage: dahdi restart\n"
15199          "  Restarts the DAHDI channels: destroys them all and then\n"
15200          "  re-reads them from chan_dahdi.conf.\n"
15201          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15202          "";
15203       return NULL;
15204    case CLI_GENERATE:
15205       return NULL;
15206    }
15207    if (a->argc != 2)
15208       return CLI_SHOWUSAGE;
15209 
15210    if (dahdi_restart() != 0)
15211       return CLI_FAILURE;
15212    return CLI_SUCCESS;
15213 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

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

07621 {
07622    int x;
07623    int res;
07624    /* Make sure our transmit state is on hook */
07625    x = 0;
07626    x = DAHDI_ONHOOK;
07627    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07628    do {
07629       x = DAHDI_RING;
07630       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07631       if (res) {
07632          switch (errno) {
07633          case EBUSY:
07634          case EINTR:
07635             /* Wait just in case */
07636             usleep(10000);
07637             continue;
07638          case EINPROGRESS:
07639             res = 0;
07640             break;
07641          default:
07642             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07643             res = 0;
07644          }
07645       }
07646    } while (res);
07647    return res;
07648 }

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

Definition at line 5928 of file chan_dahdi.c.

References ast_channel::_state, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_safe_sleep(), 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().

05929 {
05930    /* Data will be our digit string */
05931    struct dahdi_pvt *pvt;
05932    char *parse;
05933    int res;
05934    AST_DECLARE_APP_ARGS(args,
05935       AST_APP_ARG(destination);
05936       AST_APP_ARG(original);
05937       AST_APP_ARG(reason);
05938    );
05939 
05940    if (ast_strlen_zero(data)) {
05941       ast_log(LOG_DEBUG, "No data sent to application!\n");
05942       return -1;
05943    }
05944    if (chan->tech != &dahdi_tech) {
05945       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05946       return -1;
05947    }
05948    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05949    if (!pvt) {
05950       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05951       return -1;
05952    }
05953    switch (pvt->sig) {
05954    case SIG_PRI_LIB_HANDLE_CASES:
05955       break;
05956    default:
05957       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05958          chan->name);
05959       return -1;
05960    }
05961 
05962    parse = ast_strdupa(data);
05963    AST_STANDARD_APP_ARGS(args, parse);
05964 
05965    if (ast_strlen_zero(args.destination)) {
05966       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05967       return -1;
05968    }
05969 
05970    if (ast_strlen_zero(args.original)) {
05971       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05972       args.original = NULL;
05973    }
05974 
05975    if (ast_strlen_zero(args.reason)) {
05976       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05977       args.reason = NULL;
05978    }
05979 
05980    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05981       args.destination, args.original, args.reason);
05982    if (!res) {
05983       /*
05984        * Wait up to 5 seconds for a reply before hanging up this call
05985        * leg if the peer does not disconnect first.
05986        */
05987       ast_safe_sleep(chan, 5000);
05988    }
05989 
05990    return -1;
05991 }

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

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

05902 {
05903    /* Data will be our digit string */
05904    struct dahdi_pvt *p;
05905 
05906    if (ast_strlen_zero(digits)) {
05907       ast_debug(1, "No digit string sent to application!\n");
05908       return -1;
05909    }
05910 
05911    p = (struct dahdi_pvt *)chan->tech_pvt;
05912 
05913    if (!p) {
05914       ast_debug(1, "Unable to find technology private\n");
05915       return -1;
05916    }
05917 
05918    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05919 
05920    return 0;
05921 }

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

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

18651 {
18652 #define  END_SILENCE_LEN 400
18653 #define  HEADER_MS 50
18654 #define  TRAILER_MS 5
18655 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18656 #define  ASCII_BYTES_PER_CHAR 80
18657 
18658    unsigned char *buf,*mybuf;
18659    struct dahdi_pvt *p = c->tech_pvt;
18660    struct pollfd fds[1];
18661    int size,res,fd,len,x;
18662    int bytes=0;
18663    /* Initial carrier (imaginary) */
18664    float cr = 1.0;
18665    float ci = 0.0;
18666    float scont = 0.0;
18667    int idx;
18668 
18669    idx = dahdi_get_index(c, p, 0);
18670    if (idx < 0) {
18671       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18672       return -1;
18673    }
18674    if (!text[0]) return(0); /* if nothing to send, don't */
18675    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18676    if (p->mate)
18677       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18678    else
18679       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18680    if (!buf)
18681       return -1;
18682    mybuf = buf;
18683    if (p->mate) {
18684       int codec = AST_LAW(p);
18685       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18686          PUT_CLID_MARKMS;
18687       }
18688       /* Put actual message */
18689       for (x = 0; text[x]; x++) {
18690          PUT_CLID(text[x]);
18691       }
18692       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18693          PUT_CLID_MARKMS;
18694       }
18695       len = bytes;
18696       buf = mybuf;
18697    } else {
18698       len = tdd_generate(p->tdd, buf, text);
18699       if (len < 1) {
18700          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18701          ast_free(mybuf);
18702          return -1;
18703       }
18704    }
18705    memset(buf + len, 0x7f, END_SILENCE_LEN);
18706    len += END_SILENCE_LEN;
18707    fd = p->subs[idx].dfd;
18708    while (len) {
18709       if (ast_check_hangup(c)) {
18710          ast_free(mybuf);
18711          return -1;
18712       }
18713       size = len;
18714       if (size > READ_SIZE)
18715          size = READ_SIZE;
18716       fds[0].fd = fd;
18717       fds[0].events = POLLOUT | POLLPRI;
18718       fds[0].revents = 0;
18719       res = poll(fds, 1, -1);
18720       if (!res) {
18721          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18722          continue;
18723       }
18724       /* if got exception */
18725       if (fds[0].revents & POLLPRI) {
18726          ast_free(mybuf);
18727          return -1;
18728       }
18729       if (!(fds[0].revents & POLLOUT)) {
18730          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18731          continue;
18732       }
18733       res = write(fd, buf, size);
18734       if (res != size) {
18735          if (res == -1) {
18736             ast_free(mybuf);
18737             return -1;
18738          }
18739          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18740          break;
18741       }
18742       len -= size;
18743       buf += size;
18744    }
18745    ast_free(mybuf);
18746    return(0);
18747 }

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

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

15809 {
15810    int channel;
15811    int on;
15812    struct dahdi_pvt *dahdi_chan = NULL;
15813 
15814    switch (cmd) {
15815    case CLI_INIT:
15816       e->command = "dahdi set dnd";
15817       e->usage =
15818          "Usage: dahdi set dnd <chan#> <on|off>\n"
15819          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15820          "  Changes take effect immediately.\n"
15821          "  <chan num> is the channel number\n"
15822          "  <on|off> Enable or disable DND mode?\n"
15823          ;
15824       return NULL;
15825    case CLI_GENERATE:
15826       return NULL;
15827    }
15828 
15829    if (a->argc != 5)
15830       return CLI_SHOWUSAGE;
15831 
15832    if ((channel = atoi(a->argv[3])) <= 0) {
15833       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15834       return CLI_SHOWUSAGE;
15835    }
15836 
15837    if (ast_true(a->argv[4]))
15838       on = 1;
15839    else if (ast_false(a->argv[4]))
15840       on = 0;
15841    else {
15842       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15843       return CLI_SHOWUSAGE;
15844    }
15845 
15846    ast_mutex_lock(&iflock);
15847    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15848       if (dahdi_chan->channel != channel)
15849          continue;
15850 
15851       /* Found the channel. Actually set it */
15852       dahdi_dnd(dahdi_chan, on);
15853       break;
15854    }
15855    ast_mutex_unlock(&iflock);
15856 
15857    if (!dahdi_chan) {
15858       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15859       return CLI_FAILURE;
15860    }
15861 
15862    return CLI_SUCCESS;
15863 }

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

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

05162 {
05163    int x, res;
05164 
05165    x = hs;
05166    res = ioctl(fd, DAHDI_HOOK, &x);
05167 
05168    if (res < 0) {
05169       if (errno == EINPROGRESS)
05170          return 0;
05171       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05172       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05173    }
05174 
05175    return res;
05176 }

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

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

15669 {
15670    int channel;
15671    int gain;
15672    int tx;
15673    struct dahdi_hwgain hwgain;
15674    struct dahdi_pvt *tmp = NULL;
15675 
15676    switch (cmd) {
15677    case CLI_INIT:
15678       e->command = "dahdi set hwgain";
15679       e->usage =
15680          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15681          "  Sets the hardware gain on a a given channel, overriding the\n"
15682          "   value provided at module loadtime, whether the channel is in\n"
15683          "   use or not.  Changes take effect immediately.\n"
15684          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15685          "   <chan num> is the channel number relative to the device\n"
15686          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15687       return NULL;
15688    case CLI_GENERATE:
15689       return NULL;
15690    }
15691 
15692    if (a->argc != 6)
15693       return CLI_SHOWUSAGE;
15694 
15695    if (!strcasecmp("rx", a->argv[3]))
15696       tx = 0; /* rx */
15697    else if (!strcasecmp("tx", a->argv[3]))
15698       tx = 1; /* tx */
15699    else
15700       return CLI_SHOWUSAGE;
15701 
15702    channel = atoi(a->argv[4]);
15703    gain = atof(a->argv[5])*10.0;
15704 
15705    ast_mutex_lock(&iflock);
15706 
15707    for (tmp = iflist; tmp; tmp = tmp->next) {
15708 
15709       if (tmp->channel != channel)
15710          continue;
15711 
15712       if (tmp->subs[SUB_REAL].dfd == -1)
15713          break;
15714 
15715       hwgain.newgain = gain;
15716       hwgain.tx = tx;
15717       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15718          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15719          ast_mutex_unlock(&iflock);
15720          return CLI_FAILURE;
15721       }
15722       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15723          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15724       break;
15725    }
15726 
15727    ast_mutex_unlock(&iflock);
15728 
15729    if (tmp)
15730       return CLI_SUCCESS;
15731 
15732    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15733    return CLI_FAILURE;
15734 
15735 }

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

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

15738 {
15739    int channel;
15740    float gain;
15741    int tx;
15742    int res;
15743    struct dahdi_pvt *tmp = NULL;
15744 
15745    switch (cmd) {
15746    case CLI_INIT:
15747       e->command = "dahdi set swgain";
15748       e->usage =
15749          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15750          "  Sets the software gain on a a given channel, overriding the\n"
15751          "   value provided at module loadtime, whether the channel is in\n"
15752          "   use or not.  Changes take effect immediately.\n"
15753          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15754          "   <chan num> is the channel number relative to the device\n"
15755          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15756       return NULL;
15757    case CLI_GENERATE:
15758       return NULL;
15759    }
15760 
15761    if (a->argc != 6)
15762       return CLI_SHOWUSAGE;
15763 
15764    if (!strcasecmp("rx", a->argv[3]))
15765       tx = 0; /* rx */
15766    else if (!strcasecmp("tx", a->argv[3]))
15767       tx = 1; /* tx */
15768    else
15769       return CLI_SHOWUSAGE;
15770 
15771    channel = atoi(a->argv[4]);
15772    gain = atof(a->argv[5]);
15773 
15774    ast_mutex_lock(&iflock);
15775    for (tmp = iflist; tmp; tmp = tmp->next) {
15776 
15777       if (tmp->channel != channel)
15778          continue;
15779 
15780       if (tmp->subs[SUB_REAL].dfd == -1)
15781          break;
15782 
15783       if (tx)
15784          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15785       else
15786          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15787 
15788       if (res) {
15789          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15790          ast_mutex_unlock(&iflock);
15791          return CLI_FAILURE;
15792       }
15793 
15794       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15795          tx ? "tx" : "rx", gain, channel);
15796       break;
15797    }
15798    ast_mutex_unlock(&iflock);
15799 
15800    if (tmp)
15801       return CLI_SUCCESS;
15802 
15803    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15804    return CLI_FAILURE;
15805 
15806 }

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

Definition at line 2566 of file chan_dahdi.c.

Referenced by my_new_pri_ast_channel(), and my_pri_ss7_open_media().

02567 {
02568    int res;
02569    res = ioctl(dfd, DAHDI_SETLAW, &law);
02570    if (res)
02571       return res;
02572    return 0;
02573 }

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

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

04388 {
04389    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04390 }

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

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

06719 {
06720    char *cp;
06721    signed char *scp;
06722    int x;
06723    int idx;
06724    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06725    struct oprmode *oprmode;
06726 
06727 
06728    /* all supported options require data */
06729    if (!p || !data || (datalen < 1)) {
06730       errno = EINVAL;
06731       return -1;
06732    }
06733 
06734    switch (option) {
06735    case AST_OPTION_TXGAIN:
06736       scp = (signed char *) data;
06737       idx = dahdi_get_index(chan, p, 0);
06738       if (idx < 0) {
06739          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06740          return -1;
06741       }
06742       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06743       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06744    case AST_OPTION_RXGAIN:
06745       scp = (signed char *) data;
06746       idx = dahdi_get_index(chan, p, 0);
06747       if (idx < 0) {
06748          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06749          return -1;
06750       }
06751       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06752       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06753    case AST_OPTION_TONE_VERIFY:
06754       if (!p->dsp)
06755          break;
06756       cp = (char *) data;
06757       switch (*cp) {
06758       case 1:
06759          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06760          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06761          break;
06762       case 2:
06763          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06764          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06765          break;
06766       default:
06767          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06768          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06769          break;
06770       }
06771       break;
06772    case AST_OPTION_TDD:
06773       /* turn on or off TDD */
06774       cp = (char *) data;
06775       p->mate = 0;
06776       if (!*cp) { /* turn it off */
06777          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06778          if (p->tdd)
06779             tdd_free(p->tdd);
06780          p->tdd = 0;
06781          break;
06782       }
06783       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06784          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06785       dahdi_disable_ec(p);
06786       /* otherwise, turn it on */
06787       if (!p->didtdd) { /* if havent done it yet */
06788          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06789          unsigned char *buf;
06790          int size, res, fd, len;
06791          struct pollfd fds[1];
06792 
06793          buf = mybuf;
06794          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06795          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06796          len = 40000;
06797          idx = dahdi_get_index(chan, p, 0);
06798          if (idx < 0) {
06799             ast_log(LOG_WARNING, "No index in TDD?\n");
06800             return -1;
06801          }
06802          fd = p->subs[idx].dfd;
06803          while (len) {
06804             if (ast_check_hangup(chan))
06805                return -1;
06806             size = len;
06807             if (size > READ_SIZE)
06808                size = READ_SIZE;
06809             fds[0].fd = fd;
06810             fds[0].events = POLLPRI | POLLOUT;
06811             fds[0].revents = 0;
06812             res = poll(fds, 1, -1);
06813             if (!res) {
06814                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06815                continue;
06816             }
06817             /* if got exception */
06818             if (fds[0].revents & POLLPRI)
06819                return -1;
06820             if (!(fds[0].revents & POLLOUT)) {
06821                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06822                continue;
06823             }
06824             res = write(fd, buf, size);
06825             if (res != size) {
06826                if (res == -1) return -1;
06827                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06828                break;
06829             }
06830             len -= size;
06831             buf += size;
06832          }
06833          p->didtdd = 1; /* set to have done it now */
06834       }
06835       if (*cp == 2) { /* Mate mode */
06836          if (p->tdd)
06837             tdd_free(p->tdd);
06838          p->tdd = 0;
06839          p->mate = 1;
06840          break;
06841       }
06842       if (!p->tdd) { /* if we don't have one yet */
06843          p->tdd = tdd_new(); /* allocate one */
06844       }
06845       break;
06846    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06847       if (!p->dsp)
06848          break;
06849       cp = (char *) data;
06850       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06851          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06852       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06853       break;
06854    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06855 #if defined(HAVE_PRI)
06856       if (dahdi_sig_pri_lib_handles(p->sig)
06857          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06858          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06859          break;
06860       }
06861 #endif   /* defined(HAVE_PRI) */
06862 
06863       cp = (char *) data;
06864       if (!*cp) {
06865          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06866          x = 0;
06867          dahdi_disable_ec(p);
06868       } else {
06869          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06870          x = 1;
06871       }
06872       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06873          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06874       break;
06875    case AST_OPTION_OPRMODE:  /* Operator services mode */
06876       oprmode = (struct oprmode *) data;
06877       /* We don't support operator mode across technologies */
06878       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06879          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06880                chan->tech->type, oprmode->peer->tech->type);
06881          errno = EINVAL;
06882          return -1;
06883       }
06884       pp = oprmode->peer->tech_pvt;
06885       p->oprmode = pp->oprmode = 0;
06886       /* setup peers */
06887       p->oprpeer = pp;
06888       pp->oprpeer = p;
06889       /* setup modes, if any */
06890       if (oprmode->mode)
06891       {
06892          pp->oprmode = oprmode->mode;
06893          p->oprmode = -oprmode->mode;
06894       }
06895       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06896          oprmode->mode, chan->name,oprmode->peer->name);
06897       break;
06898    case AST_OPTION_ECHOCAN:
06899       cp = (char *) data;
06900       if (*cp) {
06901          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06902          dahdi_enable_ec(p);
06903       } else {
06904          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06905          dahdi_disable_ec(p);
06906       }
06907       break;
06908    case AST_OPTION_DIGIT_DETECT:
06909       cp = (char *) data;
06910       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06911       if (*cp) {
06912          enable_dtmf_detect(p);
06913       } else {
06914          disable_dtmf_detect(p);
06915       }
06916       break;
06917    case AST_OPTION_FAX_DETECT:
06918       cp = (char *) data;
06919       if (p->dsp) {
06920          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06921          if (*cp) {
06922             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06923          } else {
06924             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06925          }
06926          ast_dsp_set_features(p->dsp, p->dsp_features);
06927       }
06928       break;
06929    default:
06930       return -1;
06931    }
06932    errno = 0;
06933 
06934    return 0;
06935 }

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

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

15312 {
15313    int channel;
15314    struct dahdi_pvt *tmp = NULL;
15315    struct dahdi_confinfo ci;
15316    struct dahdi_params ps;
15317    int x;
15318 
15319    switch (cmd) {
15320    case CLI_INIT:
15321       e->command = "dahdi show channel";
15322       e->usage =
15323          "Usage: dahdi show channel <chan num>\n"
15324          "  Detailed information about a given channel\n";
15325       return NULL;
15326    case CLI_GENERATE:
15327       return NULL;
15328    }
15329 
15330    if (a->argc != 4)
15331       return CLI_SHOWUSAGE;
15332 
15333    channel = atoi(a->argv[3]);
15334 
15335    ast_mutex_lock(&iflock);
15336    for (tmp = iflist; tmp; tmp = tmp->next) {
15337       if (tmp->channel == channel) {
15338          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15339          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15340          ast_cli(a->fd, "Span: %d\n", tmp->span);
15341          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15342          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15343          ast_cli(a->fd, "Context: %s\n", tmp->context);
15344          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15345          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15346 #if defined(HAVE_PRI)
15347 #if defined(HAVE_PRI_SUBADDR)
15348          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15349 #endif   /* defined(HAVE_PRI_SUBADDR) */
15350 #endif   /* defined(HAVE_PRI) */
15351          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15352          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15353          if (tmp->vars) {
15354             struct ast_variable *v;
15355             ast_cli(a->fd, "Variables:\n");
15356             for (v = tmp->vars ; v ; v = v->next)
15357                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15358          }
15359          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15360          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15361          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15362          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15363          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15364          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)" : "");
15365          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)" : "");
15366          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)" : "");
15367          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15368          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15369          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15370          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15371          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15372          if (tmp->busydetect) {
15373 #if defined(BUSYDETECT_TONEONLY)
15374             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15375 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15376             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15377 #endif
15378 #ifdef BUSYDETECT_DEBUG
15379             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15380 #endif
15381             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15382             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15383          }
15384          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15385          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15386          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15387          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15388          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15389          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15390          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15391          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15392          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15393          ast_cli(a->fd, "Echo Cancellation:\n");
15394 
15395          if (tmp->echocancel.head.tap_length) {
15396             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15397             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15398                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15399             }
15400             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15401          } else {
15402             ast_cli(a->fd, "\tnone\n");
15403          }
15404          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15405          if (tmp->master)
15406             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15407          for (x = 0; x < MAX_SLAVES; x++) {
15408             if (tmp->slaves[x])
15409                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15410          }
15411 #ifdef HAVE_OPENR2
15412          if (tmp->mfcr2) {
15413             char calldir[OR2_MAX_PATH];
15414             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15415             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15416             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15417             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15418             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15419             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15420             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15421             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15422             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15423             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15424             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15425 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15426             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15427 #endif
15428             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15429             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15430             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15431             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15432             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15433             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15434             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15435             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15436             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15437             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15438             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15439             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15440          }
15441 #endif
15442 #if defined(HAVE_SS7)
15443          if (tmp->ss7) {
15444             struct sig_ss7_chan *chan = tmp->sig_pvt;
15445 
15446             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15447          }
15448 #endif   /* defined(HAVE_SS7) */
15449 #ifdef HAVE_PRI
15450          if (tmp->pri) {
15451             struct sig_pri_chan *chan = tmp->sig_pvt;
15452 
15453             ast_cli(a->fd, "PRI Flags: ");
15454             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15455                ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15456             }
15457             if (chan->call)
15458                ast_cli(a->fd, "Call ");
15459             if (chan->allocated) {
15460                ast_cli(a->fd, "Allocated ");
15461             }
15462             ast_cli(a->fd, "\n");
15463             if (tmp->logicalspan)
15464                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15465             else
15466                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15467          }
15468 #endif
15469          memset(&ci, 0, sizeof(ci));
15470          ps.channo = tmp->channel;
15471          if (tmp->subs[SUB_REAL].dfd > -1) {
15472             memset(&ci, 0, sizeof(ci));
15473             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15474                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15475             }
15476             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15477                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15478             }
15479             memset(&ps, 0, sizeof(ps));
15480             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15481                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15482             } else {
15483                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15484             }
15485          }
15486          if (ISTRUNK(tmp)) {
15487             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
15488             if (!ast_strlen_zero(progzone))
15489                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15490             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
15491             if(tmp->busydetect) {
15492                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15493                if(tmp->busytonelength > 0) {
15494                   ast_cli(a->fd, "Busy Pattern:\n");
15495                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15496                   if (tmp->busyquietlength > 0) 
15497                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15498                   else 
15499                      ast_cli(a->fd, " -- Detect Tone Only\n");
15500                   if(tmp->busyfuzziness > 0)
15501                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15502                }
15503             }
15504          }
15505          ast_mutex_unlock(&iflock);
15506          return CLI_SUCCESS;
15507       }
15508    }
15509    ast_mutex_unlock(&iflock);
15510 
15511    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15512    return CLI_FAILURE;
15513 }

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

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

15226 {
15227 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15228 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15229    unsigned int targetnum = 0;
15230    int filtertype = 0;
15231    struct dahdi_pvt *tmp = NULL;
15232    char tmps[20] = "";
15233    char statestr[20] = "";
15234    char blockstr[20] = "";
15235 
15236    switch (cmd) {
15237    case CLI_INIT:
15238       e->command = "dahdi show channels [group|context]";
15239       e->usage =
15240          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15241          "  Shows a list of available channels with optional filtering\n"
15242          "  <group> must be a number between 0 and 63\n";
15243       return NULL;
15244    case CLI_GENERATE:
15245       return NULL;
15246    }
15247 
15248    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15249 
15250    if (!((a->argc == 3) || (a->argc == 5)))
15251       return CLI_SHOWUSAGE;
15252 
15253    if (a->argc == 5) {
15254       if (!strcasecmp(a->argv[3], "group")) {
15255          targetnum = atoi(a->argv[4]);
15256          if ((targetnum < 0) || (targetnum > 63))
15257             return CLI_SHOWUSAGE;
15258          targetnum = 1 << targetnum;
15259          filtertype = 1;
15260       } else if (!strcasecmp(a->argv[3], "context")) {
15261          filtertype = 2;
15262       }
15263    }
15264 
15265    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15266    ast_mutex_lock(&iflock);
15267    for (tmp = iflist; tmp; tmp = tmp->next) {
15268       if (filtertype) {
15269          switch(filtertype) {
15270          case 1: /* dahdi show channels group <group> */
15271             if (!(tmp->group & targetnum)) {
15272                continue;
15273             }
15274             break;
15275          case 2: /* dahdi show channels context <context> */
15276             if (strcasecmp(tmp->context, a->argv[4])) {
15277                continue;
15278             }
15279             break;
15280          default:
15281             break;
15282          }
15283       }
15284       if (tmp->channel > 0) {
15285          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15286       } else
15287          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15288 
15289       if (tmp->locallyblocked)
15290          blockstr[0] = 'L';
15291       else
15292          blockstr[0] = ' ';
15293 
15294       if (tmp->remotelyblocked)
15295          blockstr[1] = 'R';
15296       else
15297          blockstr[1] = ' ';
15298 
15299       blockstr[2] = '\0';
15300 
15301       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15302 
15303       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15304    }
15305    ast_mutex_unlock(&iflock);
15306    return CLI_SUCCESS;
15307 #undef FORMAT
15308 #undef FORMAT2
15309 }

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

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

15553 {
15554    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15555    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15556    int span;
15557    int res;
15558    char alarmstr[50];
15559 
15560    int ctl;
15561    struct dahdi_spaninfo s;
15562 
15563    switch (cmd) {
15564    case CLI_INIT:
15565       e->command = "dahdi show status";
15566       e->usage =
15567          "Usage: dahdi show status\n"
15568          "       Shows a list of DAHDI cards with status\n";
15569       return NULL;
15570    case CLI_GENERATE:
15571       return NULL;
15572    }
15573    ctl = open("/dev/dahdi/ctl", O_RDWR);
15574    if (ctl < 0) {
15575       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15576       return CLI_FAILURE;
15577    }
15578    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15579 
15580    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15581       s.spanno = span;
15582       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15583       if (res) {
15584          continue;
15585       }
15586       alarmstr[0] = '\0';
15587       if (s.alarms > 0) {
15588          if (s.alarms & DAHDI_ALARM_BLUE)
15589             strcat(alarmstr, "BLU/");
15590          if (s.alarms & DAHDI_ALARM_YELLOW)
15591             strcat(alarmstr, "YEL/");
15592          if (s.alarms & DAHDI_ALARM_RED)
15593             strcat(alarmstr, "RED/");
15594          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15595             strcat(alarmstr, "LB/");
15596          if (s.alarms & DAHDI_ALARM_RECOVER)
15597             strcat(alarmstr, "REC/");
15598          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15599             strcat(alarmstr, "NOP/");
15600          if (!strlen(alarmstr))
15601             strcat(alarmstr, "UUU/");
15602          if (strlen(alarmstr)) {
15603             /* Strip trailing / */
15604             alarmstr[strlen(alarmstr) - 1] = '\0';
15605          }
15606       } else {
15607          if (s.numchans)
15608             strcpy(alarmstr, "OK");
15609          else
15610             strcpy(alarmstr, "UNCONFIGURED");
15611       }
15612 
15613       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15614          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15615          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15616          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15617          "CAS",
15618          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15619          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15620          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15621          "Unk",
15622          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15623             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15624             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15625          lbostr[s.lbo]
15626          );
15627    }
15628    close(ctl);
15629 
15630    return CLI_SUCCESS;
15631 #undef FORMAT
15632 #undef FORMAT2
15633 }

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

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

15636 {
15637    int pseudo_fd = -1;
15638    struct dahdi_versioninfo vi;
15639 
15640    switch (cmd) {
15641    case CLI_INIT:
15642       e->command = "dahdi show version";
15643       e->usage =
15644          "Usage: dahdi show version\n"
15645          "       Shows the DAHDI version in use\n";
15646       return NULL;
15647    case CLI_GENERATE:
15648       return NULL;
15649    }
15650    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15651       ast_cli(a->fd, "Failed to open control file to get version.\n");
15652       return CLI_SUCCESS;
15653    }
15654 
15655    strcpy(vi.version, "Unknown");
15656    strcpy(vi.echo_canceller, "Unknown");
15657 
15658    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15659       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15660    else
15661       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15662 
15663    close(pseudo_fd);
15664 
15665    return CLI_SUCCESS;
15666 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

04612 {
04613    static char buf[256];
04614    switch (sig) {
04615    case SIG_EM:
04616       return "E & M Immediate";
04617    case SIG_EMWINK:
04618       return "E & M Wink";
04619    case SIG_EM_E1:
04620       return "E & M E1";
04621    case SIG_FEATD:
04622       return "Feature Group D (DTMF)";
04623    case SIG_FEATDMF:
04624       return "Feature Group D (MF)";
04625    case SIG_FEATDMF_TA:
04626       return "Feature Groud D (MF) Tandem Access";
04627    case SIG_FEATB:
04628       return "Feature Group B (MF)";
04629    case SIG_E911:
04630       return "E911 (MF)";
04631    case SIG_FGC_CAMA:
04632       return "FGC/CAMA (Dialpulse)";
04633    case SIG_FGC_CAMAMF:
04634       return "FGC/CAMA (MF)";
04635    case SIG_FXSLS:
04636       return "FXS Loopstart";
04637    case SIG_FXSGS:
04638       return "FXS Groundstart";
04639    case SIG_FXSKS:
04640       return "FXS Kewlstart";
04641    case SIG_FXOLS:
04642       return "FXO Loopstart";
04643    case SIG_FXOGS:
04644       return "FXO Groundstart";
04645    case SIG_FXOKS:
04646       return "FXO Kewlstart";
04647    case SIG_PRI:
04648       return "ISDN PRI";
04649    case SIG_BRI:
04650       return "ISDN BRI Point to Point";
04651    case SIG_BRI_PTMP:
04652       return "ISDN BRI Point to MultiPoint";
04653    case SIG_SS7:
04654       return "SS7";
04655    case SIG_MFCR2:
04656       return "MFC/R2";
04657    case SIG_SF:
04658       return "SF (Tone) Immediate";
04659    case SIG_SFWINK:
04660       return "SF (Tone) Wink";
04661    case SIG_SF_FEATD:
04662       return "SF (Tone) with Feature Group D (DTMF)";
04663    case SIG_SF_FEATDMF:
04664       return "SF (Tone) with Feature Group D (MF)";
04665    case SIG_SF_FEATB:
04666       return "SF (Tone) with Feature Group B (MF)";
04667    case 0:
04668       return "Pseudo";
04669    default:
04670       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04671       return buf;
04672    }
04673 }

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

Definition at line 1553 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_pri_cc_agent_init(), dahdi_queryoption(), dahdi_read(), dahdi_request(), dahdi_setoption(), handle_alarms(), and handle_clear_alarms().

01554 {
01555    int handles;
01556 
01557    switch (signaling) {
01558    case SIG_PRI_LIB_HANDLE_CASES:
01559       handles = 1;
01560       break;
01561    default:
01562       handles = 0;
01563       break;
01564    }
01565 
01566    return handles;
01567 }

static void dahdi_softhangup_all ( void   )  [static]

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

15053 {
15054    struct dahdi_pvt *p;
15055 retry:
15056    ast_mutex_lock(&iflock);
15057    for (p = iflist; p; p = p->next) {
15058       ast_mutex_lock(&p->lock);
15059       if (p->owner && !p->restartpending) {
15060          if (ast_channel_trylock(p->owner)) {
15061             if (option_debug > 2)
15062                ast_verbose("Avoiding deadlock\n");
15063             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15064             ast_mutex_unlock(&p->lock);
15065             ast_mutex_unlock(&iflock);
15066             goto retry;
15067          }
15068          if (option_debug > 2)
15069             ast_verbose("Softhanging up on %s\n", p->owner->name);
15070          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15071          p->restartpending = 1;
15072          num_restart_pending++;
15073          ast_channel_unlock(p->owner);
15074       }
15075       ast_mutex_unlock(&p->lock);
15076    }
15077    ast_mutex_unlock(&iflock);
15078 }

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

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

18421 {
18422    int ctl, res, span;
18423    struct ast_data *data_span, *data_alarms;
18424    struct dahdi_spaninfo s;
18425 
18426    ctl = open("/dev/dahdi/ctl", O_RDWR);
18427    if (ctl < 0) {
18428       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18429       return -1;
18430    }
18431    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18432       s.spanno = span;
18433       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18434       if (res) {
18435          continue;
18436       }
18437 
18438       data_span = ast_data_add_node(data_root, "span");
18439       if (!data_span) {
18440          continue;
18441       }
18442       ast_data_add_str(data_span, "description", s.desc);
18443 
18444       /* insert the alarms status */
18445       data_alarms = ast_data_add_node(data_span, "alarms");
18446       if (!data_alarms) {
18447          continue;
18448       }
18449 
18450       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18451       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18452       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18453       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18454       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18455       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18456 
18457       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18458       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18459       ast_data_add_int(data_span, "crc4", s.crc4count);
18460       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18461                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18462                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18463                      "CAS");
18464       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18465                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18466                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18467                      "Unknown");
18468       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18469                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18470                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18471       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18472 
18473       /* if this span doesn't match remove it. */
18474       if (!ast_data_search_match(search, data_span)) {
18475          ast_data_remove_node(data_root, data_span);
18476       }
18477    }
18478    close(ctl);
18479 
18480    return 0;
18481 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

04954 {
04955    int x;
04956    int res;
04957 
04958    if (p && p->echocanon && p->echotraining) {
04959       x = p->echotraining;
04960       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04961       if (res)
04962          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04963       else
04964          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04965    } else {
04966       ast_debug(1, "No echo training requested\n");
04967    }
04968 }

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

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

07151 {
07152    /* Unlink a specific slave or all slaves/masters from a given master */
07153    int x;
07154    int hasslaves;
07155    if (!master)
07156       return;
07157    if (needlock) {
07158       ast_mutex_lock(&master->lock);
07159       if (slave) {
07160          while (ast_mutex_trylock(&slave->lock)) {
07161             DEADLOCK_AVOIDANCE(&master->lock);
07162          }
07163       }
07164    }
07165    hasslaves = 0;
07166    for (x = 0; x < MAX_SLAVES; x++) {
07167       if (master->slaves[x]) {
07168          if (!slave || (master->slaves[x] == slave)) {
07169             /* Take slave out of the conference */
07170             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07171             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07172             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07173             master->slaves[x]->master = NULL;
07174             master->slaves[x] = NULL;
07175          } else
07176             hasslaves = 1;
07177       }
07178       if (!hasslaves)
07179          master->inconference = 0;
07180    }
07181    if (!slave) {
07182       if (master->master) {
07183          /* Take master out of the conference */
07184          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07185          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07186          hasslaves = 0;
07187          for (x = 0; x < MAX_SLAVES; x++) {
07188             if (master->master->slaves[x] == master)
07189                master->master->slaves[x] = NULL;
07190             else if (master->master->slaves[x])
07191                hasslaves = 1;
07192          }
07193          if (!hasslaves)
07194             master->master->inconference = 0;
07195       }
07196       master->master = NULL;
07197    }
07198    update_conf(master);
07199    if (needlock) {
07200       if (slave)
07201          ast_mutex_unlock(&slave->lock);
07202       ast_mutex_unlock(&master->lock);
07203    }
07204 }

static void dahdi_unlink_pri_pvt ( struct dahdi_pvt pvt  )  [static]

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

05684 {
05685    unsigned idx;
05686    struct sig_pri_span *pri;
05687 
05688    pri = pvt->pri;
05689    if (!pri) {
05690       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05691       return;
05692    }
05693    ast_mutex_lock(&pri->lock);
05694    for (idx = 0; idx < pri->numchans; ++idx) {
05695       if (pri->pvts[idx] == pvt->sig_pvt) {
05696          pri->pvts[idx] = NULL;
05697          ast_mutex_unlock(&pri->lock);
05698          return;
05699       }
05700    }
05701    ast_mutex_unlock(&pri->lock);
05702 }

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

Definition at line 18522 of file chan_dahdi.c.

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

18524 {
18525    int pseudo_fd = -1;
18526    struct dahdi_versioninfo vi = {
18527       .version = "Unknown",
18528       .echo_canceller = "Unknown"
18529    };
18530 
18531    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18532       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18533       return -1;
18534    }
18535 
18536    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18537       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18538    }
18539 
18540    close(pseudo_fd);
18541 
18542    ast_data_add_str(data_root, "value", vi.version);
18543    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18544 
18545    return 0;
18546 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 498 of file chan_dahdi.c.

00499 {
00500    int i, j = 0;
00501    i = DAHDI_IOMUX_SIGEVENT;
00502    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00503       return -1;
00504    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00505       return -1;
00506    return j;
00507 }

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

Definition at line 9850 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), and my_wink().

09851 {
09852    int j;
09853    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09854    for (;;)
09855    {
09856       /* set bits of interest */
09857       j = DAHDI_IOMUX_SIGEVENT;
09858       /* wait for some happening */
09859       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09860       /* exit loop if we have it */
09861       if (j & DAHDI_IOMUX_SIGEVENT) break;
09862    }
09863    /* get the event info */
09864    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09865    return 0;
09866 }

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

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

09373 {
09374    struct dahdi_pvt *p = ast->tech_pvt;
09375    int res;
09376    int idx;
09377    idx = dahdi_get_index(ast, p, 0);
09378    if (idx < 0) {
09379       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09380       return -1;
09381    }
09382 
09383    /* Write a frame of (presumably voice) data */
09384    if (frame->frametype != AST_FRAME_VOICE) {
09385       if (frame->frametype != AST_FRAME_IMAGE)
09386          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09387       return 0;
09388    }
09389    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09390       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09391       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09392       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09393       return -1;
09394    }
09395    if (p->dialing) {
09396       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09397       return 0;
09398    }
09399    if (!p->owner) {
09400       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09401       return 0;
09402    }
09403    if (p->cidspill) {
09404       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09405          ast->name);
09406       return 0;
09407    }
09408    /* Return if it's not valid data */
09409    if (!frame->data.ptr || !frame->datalen)
09410       return 0;
09411 
09412    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09413       if (!p->subs[idx].linear) {
09414          p->subs[idx].linear = 1;
09415          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09416          if (res)
09417             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09418       }
09419       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09420    } else {
09421       /* x-law already */
09422       if (p->subs[idx].linear) {
09423          p->subs[idx].linear = 0;
09424          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09425          if (res)
09426             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09427       }
09428       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09429    }
09430    if (res < 0) {
09431       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09432       return -1;
09433    }
09434    return 0;
09435 }

static enum analog_event dahdievent_to_analogevent ( int  event  )  [static]

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

02745 {
02746    enum analog_event res;
02747 
02748    switch (event) {
02749    case DAHDI_EVENT_ONHOOK:
02750       res = ANALOG_EVENT_ONHOOK;
02751       break;
02752    case DAHDI_EVENT_RINGOFFHOOK:
02753       res = ANALOG_EVENT_RINGOFFHOOK;
02754       break;
02755    case DAHDI_EVENT_WINKFLASH:
02756       res = ANALOG_EVENT_WINKFLASH;
02757       break;
02758    case DAHDI_EVENT_ALARM:
02759       res = ANALOG_EVENT_ALARM;
02760       break;
02761    case DAHDI_EVENT_NOALARM:
02762       res = ANALOG_EVENT_NOALARM;
02763       break;
02764    case DAHDI_EVENT_DIALCOMPLETE:
02765       res = ANALOG_EVENT_DIALCOMPLETE;
02766       break;
02767    case DAHDI_EVENT_RINGERON:
02768       res = ANALOG_EVENT_RINGERON;
02769       break;
02770    case DAHDI_EVENT_RINGEROFF:
02771       res = ANALOG_EVENT_RINGEROFF;
02772       break;
02773    case DAHDI_EVENT_HOOKCOMPLETE:
02774       res = ANALOG_EVENT_HOOKCOMPLETE;
02775       break;
02776    case DAHDI_EVENT_PULSE_START:
02777       res = ANALOG_EVENT_PULSE_START;
02778       break;
02779    case DAHDI_EVENT_POLARITY:
02780       res = ANALOG_EVENT_POLARITY;
02781       break;
02782    case DAHDI_EVENT_RINGBEGIN:
02783       res = ANALOG_EVENT_RINGBEGIN;
02784       break;
02785    case DAHDI_EVENT_EC_DISABLED:
02786       res = ANALOG_EVENT_EC_DISABLED;
02787       break;
02788    case DAHDI_EVENT_REMOVED:
02789       res = ANALOG_EVENT_REMOVED;
02790       break;
02791    case DAHDI_EVENT_NEONMWI_ACTIVE:
02792       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02793       break;
02794    case DAHDI_EVENT_NEONMWI_INACTIVE:
02795       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02796       break;
02797 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02798    case DAHDI_EVENT_TX_CED_DETECTED:
02799       res = ANALOG_EVENT_TX_CED_DETECTED;
02800       break;
02801    case DAHDI_EVENT_RX_CED_DETECTED:
02802       res = ANALOG_EVENT_RX_CED_DETECTED;
02803       break;
02804    case DAHDI_EVENT_EC_NLP_DISABLED:
02805       res = ANALOG_EVENT_EC_NLP_DISABLED;
02806       break;
02807    case DAHDI_EVENT_EC_NLP_ENABLED:
02808       res = ANALOG_EVENT_EC_NLP_ENABLED;
02809       break;
02810 #endif
02811    case DAHDI_EVENT_PULSEDIGIT:
02812       res = ANALOG_EVENT_PULSEDIGIT;
02813       break;
02814    case DAHDI_EVENT_DTMFDOWN:
02815       res = ANALOG_EVENT_DTMFDOWN;
02816       break;
02817    case DAHDI_EVENT_DTMFUP:
02818       res = ANALOG_EVENT_DTMFUP;
02819       break;
02820    default:
02821       switch(event & 0xFFFF0000) {
02822       case DAHDI_EVENT_PULSEDIGIT:
02823       case DAHDI_EVENT_DTMFDOWN:
02824       case DAHDI_EVENT_DTMFUP:
02825          /* The event includes a digit number in the low word.
02826           * Converting it to a 'enum analog_event' would remove
02827           * that information. Thus it is returned as-is.
02828           */
02829          return event;
02830       }
02831 
02832       res = ANALOG_EVENT_ERROR;
02833       break;
02834    }
02835 
02836    return res;
02837 }

static enum analog_sigtype dahdisig_to_analogsig ( int  sig  )  [static]

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

01570 {
01571    switch (sig) {
01572    case SIG_FXOLS:
01573       return ANALOG_SIG_FXOLS;
01574    case SIG_FXOGS:
01575       return ANALOG_SIG_FXOGS;
01576    case SIG_FXOKS:
01577       return ANALOG_SIG_FXOKS;
01578    case SIG_FXSLS:
01579       return ANALOG_SIG_FXSLS;
01580    case SIG_FXSGS:
01581       return ANALOG_SIG_FXSGS;
01582    case SIG_FXSKS:
01583       return ANALOG_SIG_FXSKS;
01584    case SIG_EMWINK:
01585       return ANALOG_SIG_EMWINK;
01586    case SIG_EM:
01587       return ANALOG_SIG_EM;
01588    case SIG_EM_E1:
01589       return ANALOG_SIG_EM_E1;
01590    case SIG_FEATD:
01591       return ANALOG_SIG_FEATD;
01592    case SIG_FEATDMF:
01593       return ANALOG_SIG_FEATDMF;
01594    case SIG_E911:
01595       return SIG_E911;
01596    case SIG_FGC_CAMA:
01597       return ANALOG_SIG_FGC_CAMA;
01598    case SIG_FGC_CAMAMF:
01599       return ANALOG_SIG_FGC_CAMAMF;
01600    case SIG_FEATB:
01601       return ANALOG_SIG_FEATB;
01602    case SIG_SFWINK:
01603       return ANALOG_SIG_SFWINK;
01604    case SIG_SF:
01605       return ANALOG_SIG_SF;
01606    case SIG_SF_FEATD:
01607       return ANALOG_SIG_SF_FEATD;
01608    case SIG_SF_FEATDMF:
01609       return ANALOG_SIG_SF_FEATDMF;
01610    case SIG_FEATDMF_TA:
01611       return ANALOG_SIG_FEATDMF_TA;
01612    case SIG_SF_FEATB:
01613       return ANALOG_SIG_FEATB;
01614    default:
01615       return -1;
01616    }
01617 }

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

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

18085 {
18086    struct ast_cc_config_params *cc_params;
18087 
18088    cc_params = dest->chan.cc_params;
18089    *dest = *src;
18090    dest->chan.cc_params = cc_params;
18091    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18092 }

static void destroy_all_channels ( void   )  [static]

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

05837 {
05838    int chan;
05839 #if defined(HAVE_PRI)
05840    unsigned span;
05841    struct sig_pri_span *pri;
05842 #endif   /* defined(HAVE_PRI) */
05843    struct dahdi_pvt *p;
05844 
05845    while (num_restart_pending) {
05846       usleep(1);
05847    }
05848 
05849    ast_mutex_lock(&iflock);
05850    /* Destroy all the interfaces and free their memory */
05851    while (iflist) {
05852       p = iflist;
05853 
05854       chan = p->channel;
05855 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05856       {
05857          char db_chan_name[20];
05858          char db_answer[5];
05859          char state;
05860          int why = -1;
05861 
05862          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05863          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05864             sscanf(db_answer, "%1c:%30d", &state, &why);
05865          }
05866          if (!why) {
05867             /* SRVST persistence is not required */
05868             ast_db_del(db_chan_name, SRVST_DBKEY);
05869          }
05870       }
05871 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05872       /* Free associated memory */
05873       destroy_dahdi_pvt(p);
05874       ast_verb(3, "Unregistered channel %d\n", chan);
05875    }
05876    ifcount = 0;
05877    ast_mutex_unlock(&iflock);
05878 
05879 #if defined(HAVE_PRI)
05880    /* Destroy all of the no B channel interface lists */
05881    for (span = 0; span < NUM_SPANS; ++span) {
05882       if (!pris[span].dchannels[0]) {
05883          break;
05884       }
05885       pri = &pris[span].pri;
05886       ast_mutex_lock(&pri->lock);
05887       while (pri->no_b_chan_iflist) {
05888          p = pri->no_b_chan_iflist;
05889 
05890          /* Free associated memory */
05891          destroy_dahdi_pvt(p);
05892       }
05893       ast_mutex_unlock(&pri->lock);
05894    }
05895 #endif   /* defined(HAVE_PRI) */
05896 }

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

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

05819 {
05820    int i;
05821 
05822    if (!now) {
05823       /* Do not destroy the channel now if it is owned by someone. */
05824       if (cur->owner) {
05825          return;
05826       }
05827       for (i = 0; i < 3; i++) {
05828          if (cur->subs[i].owner) {
05829             return;
05830          }
05831       }
05832    }
05833    destroy_dahdi_pvt(cur);
05834 }

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

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

05749 {
05750    struct dahdi_pvt *p = pvt;
05751 
05752    if (p->manages_span_alarms) {
05753       struct dahdi_pvt *next = find_next_iface_in_span(p);
05754       if (next) {
05755          next->manages_span_alarms = 1;
05756       }
05757    }
05758 
05759    /* Remove channel from the list */
05760 #if defined(HAVE_PRI)
05761    dahdi_unlink_pri_pvt(p);
05762 #endif   /* defined(HAVE_PRI) */
05763 #if defined(HAVE_SS7)
05764    dahdi_unlink_ss7_pvt(p);
05765 #endif   /* defined(HAVE_SS7) */
05766    switch (pvt->which_iflist) {
05767    case DAHDI_IFLIST_NONE:
05768       break;
05769    case DAHDI_IFLIST_MAIN:
05770       dahdi_iflist_extract(p);
05771       break;
05772 #if defined(HAVE_PRI)
05773    case DAHDI_IFLIST_NO_B_CHAN:
05774       if (p->pri) {
05775          dahdi_nobch_extract(p->pri, p);
05776       }
05777       break;
05778 #endif   /* defined(HAVE_PRI) */
05779    }
05780 
05781    if (p->sig_pvt) {
05782       if (analog_lib_handles(p->sig, 0, 0)) {
05783          analog_delete(p->sig_pvt);
05784       }
05785       switch (p->sig) {
05786 #if defined(HAVE_PRI)
05787       case SIG_PRI_LIB_HANDLE_CASES:
05788          sig_pri_chan_delete(p->sig_pvt);
05789          break;
05790 #endif   /* defined(HAVE_PRI) */
05791 #if defined(HAVE_SS7)
05792       case SIG_SS7:
05793          sig_ss7_chan_delete(p->sig_pvt);
05794          break;
05795 #endif   /* defined(HAVE_SS7) */
05796       default:
05797          break;
05798       }
05799    }
05800    ast_free(p->cidspill);
05801    if (p->use_smdi)
05802       ast_smdi_interface_unref(p->smdi_iface);
05803    if (p->mwi_event_sub)
05804       ast_event_unsubscribe(p->mwi_event_sub);
05805    if (p->vars) {
05806       ast_variables_destroy(p->vars);
05807    }
05808    if (p->cc_params) {
05809       ast_cc_config_params_destroy(p->cc_params);
05810    }
05811    ast_mutex_destroy(&p->lock);
05812    dahdi_close_sub(p, SUB_REAL);
05813    if (p->owner)
05814       p->owner->tech_pvt = NULL;
05815    ast_free(p);
05816 }

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

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

13487 {
13488    char *dest;
13489    char *s;
13490    int x;
13491    int res = 0;
13492    struct dahdi_pvt *p;
13493    char *subdir = NULL;
13494    AST_DECLARE_APP_ARGS(args,
13495       AST_APP_ARG(group);  /* channel/group token */
13496       //AST_APP_ARG(ext);  /* extension token */
13497       //AST_APP_ARG(opts); /* options token */
13498       AST_APP_ARG(other);  /* Any remining unused arguments */
13499    );
13500 
13501    /*
13502     * data is ---v
13503     * Dial(DAHDI/pseudo[/extension[/options]])
13504     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13505     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13506     * Dial(DAHDI/i<span>[/extension[/options]])
13507     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13508     *
13509     * i - ISDN span channel restriction.
13510     *     Used by CC to ensure that the CC recall goes out the same span.
13511     *     Also to make ISDN channel names dialable when the sequence number
13512     *     is stripped off.  (Used by DTMF attended transfer feature.)
13513     *
13514     * g - channel group allocation search forward
13515     * G - channel group allocation search backward
13516     * r - channel group allocation round robin search forward
13517     * R - channel group allocation round robin search backward
13518     *
13519     * c - Wait for DTMF digit to confirm answer
13520     * r<cadance#> - Set distintive ring cadance number
13521     * d - Force bearer capability for ISDN/SS7 call to digital.
13522     */
13523 
13524    if (data) {
13525       dest = ast_strdupa(data);
13526    } else {
13527       ast_log(LOG_WARNING, "Channel requested with no data\n");
13528       return NULL;
13529    }
13530    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13531    if (!args.argc || ast_strlen_zero(args.group)) {
13532       ast_log(LOG_WARNING, "No channel/group specified\n");
13533       return NULL;
13534    }
13535 
13536    /* Initialize the output parameters */
13537    memset(param, 0, sizeof(*param));
13538    param->channelmatch = -1;
13539 
13540    if (strchr(args.group, '!') != NULL) {
13541       char *prev = args.group;
13542       while ((s = strchr(prev, '!')) != NULL) {
13543          *s++ = '/';
13544          prev = s;
13545       }
13546       *(prev - 1) = '\0';
13547       subdir = args.group;
13548       args.group = prev;
13549    } else if (args.group[0] == 'i') {
13550       /* Extract the ISDN span channel restriction specifier. */
13551       res = sscanf(args.group + 1, "%30d", &x);
13552       if (res < 1) {
13553          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13554          return NULL;
13555       }
13556       param->span = x;
13557 
13558       /* Remove the ISDN span channel restriction specifier. */
13559       s = strchr(args.group, '-');
13560       if (!s) {
13561          /* Search all groups since we are ISDN span restricted. */
13562          return iflist;
13563       }
13564       args.group = s + 1;
13565       res = 0;
13566    }
13567    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13568       /* Retrieve the group number */
13569       s = args.group + 1;
13570       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13571       if (res < 1) {
13572          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13573          return NULL;
13574       }
13575       param->groupmatch = ((ast_group_t) 1 << x);
13576 
13577       if (toupper(args.group[0]) == 'G') {
13578          if (args.group[0] == 'G') {
13579             param->backwards = 1;
13580             p = ifend;
13581          } else
13582             p = iflist;
13583       } else {
13584          if (ARRAY_LEN(round_robin) <= x) {
13585             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13586                x, data);
13587             return NULL;
13588          }
13589          if (args.group[0] == 'R') {
13590             param->backwards = 1;
13591             p = round_robin[x] ? round_robin[x]->prev : ifend;
13592             if (!p)
13593                p = ifend;
13594          } else {
13595             p = round_robin[x] ? round_robin[x]->next : iflist;
13596             if (!p)
13597                p = iflist;
13598          }
13599          param->roundrobin = 1;
13600          param->rr_starting_point = x;
13601       }
13602    } else {
13603       s = args.group;
13604       if (!strcasecmp(s, "pseudo")) {
13605          /* Special case for pseudo */
13606          x = CHAN_PSEUDO;
13607          param->channelmatch = x;
13608       } else {
13609          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13610          if (res < 1) {
13611             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13612             return NULL;
13613          } else {
13614             param->channelmatch = x;
13615          }
13616       }
13617       if (subdir) {
13618          char path[PATH_MAX];
13619          struct stat stbuf;
13620 
13621          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13622                subdir, param->channelmatch);
13623          if (stat(path, &stbuf) < 0) {
13624             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13625                   path, strerror(errno));
13626             return NULL;
13627          }
13628          if (!S_ISCHR(stbuf.st_mode)) {
13629             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13630                   path);
13631             return NULL;
13632          }
13633          param->channelmatch = minor(stbuf.st_rdev);
13634       }
13635 
13636       p = iflist;
13637    }
13638 
13639    if (param->opt == 'r' && res < 3) {
13640       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13641       param->opt = '\0';
13642    }
13643 
13644    return p;
13645 }

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

Definition at line 12256 of file chan_dahdi.c.

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

Referenced by build_channels().

12257 {
12258    struct stat stbuf;
12259    int      num;
12260 
12261    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12262    if (stat(path, &stbuf) < 0) {
12263       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12264       return -errno;
12265    }
12266    if (!S_ISCHR(stbuf.st_mode)) {
12267       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12268       return -EINVAL;
12269    }
12270    num = minor(stbuf.st_rdev);
12271    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12272    return num;
12273 
12274 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 4447 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

04448 {
04449    if (isdigit(digit))
04450       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04451    else if (digit >= 'A' && digit <= 'D')
04452       return DAHDI_TONE_DTMF_A + (digit - 'A');
04453    else if (digit >= 'a' && digit <= 'd')
04454       return DAHDI_TONE_DTMF_A + (digit - 'a');
04455    else if (digit == '*')
04456       return DAHDI_TONE_DTMF_s;
04457    else if (digit == '#')
04458       return DAHDI_TONE_DTMF_p;
04459    else
04460       return -1;
04461 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

06647 {
06648    int val = 0;
06649 
06650    p->ignoredtmf = 1;
06651 
06652    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06653 
06654    if (!p->hardwaredtmf && p->dsp) {
06655       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06656       ast_dsp_set_features(p->dsp, p->dsp_features);
06657    }
06658 }

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

Definition at line 11680 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::owner, 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().

11681 {
11682    int count, res, res2, spoint, pollres=0;
11683    struct dahdi_pvt *i;
11684    struct dahdi_pvt *last = NULL;
11685    struct dahdi_pvt *doomed;
11686    time_t thispass = 0, lastpass = 0;
11687    int found;
11688    char buf[1024];
11689    struct pollfd *pfds=NULL;
11690    int lastalloc = -1;
11691    /* This thread monitors all the frame relay interfaces which are not yet in use
11692       (and thus do not have a separate thread) indefinitely */
11693    /* From here on out, we die whenever asked */
11694 #if 0
11695    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11696       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11697       return NULL;
11698    }
11699    ast_debug(1, "Monitor starting...\n");
11700 #endif
11701    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11702 
11703    for (;;) {
11704       /* Lock the interface list */
11705       ast_mutex_lock(&iflock);
11706       if (!pfds || (lastalloc != ifcount)) {
11707          if (pfds) {
11708             ast_free(pfds);
11709             pfds = NULL;
11710          }
11711          if (ifcount) {
11712             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11713                ast_mutex_unlock(&iflock);
11714                return NULL;
11715             }
11716          }
11717          lastalloc = ifcount;
11718       }
11719       /* Build the stuff we're going to poll on, that is the socket of every
11720          dahdi_pvt that does not have an associated owner channel */
11721       count = 0;
11722       for (i = iflist; i; i = i->next) {
11723          ast_mutex_lock(&i->lock);
11724          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11725             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11726                struct analog_pvt *p = i->sig_pvt;
11727 
11728                if (!p) {
11729                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11730                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11731                   /* This needs to be watched, as it lacks an owner */
11732                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11733                   pfds[count].events = POLLPRI;
11734                   pfds[count].revents = 0;
11735                   /* Message waiting or r2 channels also get watched for reading */
11736                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11737                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11738                      pfds[count].events |= POLLIN;
11739                   }
11740                   count++;
11741                }
11742             } else {
11743                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11744                   /* This needs to be watched, as it lacks an owner */
11745                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11746                   pfds[count].events = POLLPRI;
11747                   pfds[count].revents = 0;
11748                   /* If we are monitoring for VMWI or sending CID, we need to
11749                      read from the channel as well */
11750                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11751                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11752                      pfds[count].events |= POLLIN;
11753                   }
11754                   count++;
11755                }
11756             }
11757          }
11758          ast_mutex_unlock(&i->lock);
11759       }
11760       /* Okay, now that we know what to do, release the interface lock */
11761       ast_mutex_unlock(&iflock);
11762 
11763       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11764       pthread_testcancel();
11765       /* Wait at least a second for something to happen */
11766       res = poll(pfds, count, 1000);
11767       pthread_testcancel();
11768       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11769 
11770       /* Okay, poll has finished.  Let's see what happened.  */
11771       if (res < 0) {
11772          if ((errno != EAGAIN) && (errno != EINTR))
11773             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11774          continue;
11775       }
11776       /* Alright, lock the interface list again, and let's look and see what has
11777          happened */
11778       ast_mutex_lock(&iflock);
11779       found = 0;
11780       spoint = 0;
11781       lastpass = thispass;
11782       thispass = time(NULL);
11783       doomed = NULL;
11784       for (i = iflist;; i = i->next) {
11785          if (doomed) {
11786             int res;
11787             res = dahdi_destroy_channel_bynum(doomed->channel);
11788             if (res != RESULT_SUCCESS) {
11789                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11790             }
11791             doomed = NULL;
11792          }
11793          if (!i) {
11794             break;
11795          }
11796 
11797          if (thispass != lastpass) {
11798             if (!found && ((i == last) || ((i == iflist) && !last))) {
11799                last = i;
11800                if (last) {
11801                   struct analog_pvt *analog_p = last->sig_pvt;
11802                   /* Only allow MWI to be initiated on a quiescent fxs port */
11803                   if (analog_p
11804                      && !last->mwisendactive
11805                      && (last->sig & __DAHDI_SIG_FXO)
11806                      && !analog_p->fxsoffhookstate
11807                      && !last->owner
11808                      && !ast_strlen_zero(last->mailbox)
11809                      && (thispass - analog_p->onhooktime > 3)) {
11810                      res = has_voicemail(last);
11811                      if (analog_p->msgstate != res) {
11812                         /* Set driver resources for signalling VMWI */
11813                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11814                         if (res2) {
11815                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11816                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11817                         }
11818                         /* If enabled for FSK spill then initiate it */
11819                         if (mwi_send_init(last)) {
11820                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11821                         }
11822                         analog_p->msgstate = res;
11823                         found ++;
11824                      }
11825                   }
11826                   last = last->next;
11827                }
11828             }
11829          }
11830          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11831             if (i->radio && !i->owner)
11832             {
11833                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11834                if (res)
11835                {
11836                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11837                   /* Don't hold iflock while handling init events */
11838                   ast_mutex_unlock(&iflock);
11839                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11840                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11841                   else
11842                      doomed = handle_init_event(i, res);
11843                   ast_mutex_lock(&iflock);
11844                }
11845                continue;
11846             }
11847             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11848             if (pollres & POLLIN) {
11849                if (i->owner || i->subs[SUB_REAL].owner) {
11850 #ifdef HAVE_PRI
11851                   if (!i->pri)
11852 #endif
11853                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11854                   continue;
11855                }
11856                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11857                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11858                   continue;
11859                }
11860                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11861                if (res > 0) {
11862                   if (i->mwimonitor_fsk) {
11863                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11864                         pthread_attr_t attr;
11865                         pthread_t threadid;
11866                         struct mwi_thread_data *mtd;
11867 
11868                         pthread_attr_init(&attr);
11869                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11870 
11871                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11872                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11873                            mtd->pvt = i;
11874                            memcpy(mtd->buf, buf, res);
11875                            mtd->len = res;
11876                            i->mwimonitoractive = 1;
11877                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11878                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11879                               i->mwimonitoractive = 0;
11880                               ast_free(mtd);
11881                            }
11882                         }
11883                      }
11884                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11885                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11886                      int energy;
11887                      struct timeval now;
11888                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11889                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11890                      */
11891                      if (1 == i->dtmfcid_holdoff_state) {
11892                         gettimeofday(&i->dtmfcid_delay, NULL);
11893                         i->dtmfcid_holdoff_state = 2;
11894                      } else if (2 == i->dtmfcid_holdoff_state) {
11895                         gettimeofday(&now, NULL);
11896                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11897                            i->dtmfcid_holdoff_state = 0;
11898                         }
11899                      } else {
11900                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11901                         if (!i->mwisendactive && energy > dtmfcid_level) {
11902                            pthread_t threadid;
11903                            struct ast_channel *chan;
11904                            ast_mutex_unlock(&iflock);
11905                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11906                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11907                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11908                               i->dtmfcid_holdoff_state = 1;
11909                            } else {
11910                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11911                               if (!chan) {
11912                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11913                               } else {
11914                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11915                                  if (res) {
11916                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11917                                     ast_hangup(chan);
11918                                  } else {
11919                                     i->dtmfcid_holdoff_state = 1;
11920                                  }
11921                               }
11922                            }
11923                            ast_mutex_lock(&iflock);
11924                         }
11925                      }
11926                   }
11927                   if (i->mwisendactive) {
11928                      mwi_send_process_buffer(i, res);
11929                   }
11930                } else {
11931                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11932                }
11933             }
11934             if (pollres & POLLPRI) {
11935                if (i->owner || i->subs[SUB_REAL].owner) {
11936 #ifdef HAVE_PRI
11937                   if (!i->pri)
11938 #endif
11939                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11940                   continue;
11941                }
11942                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11943                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11944                /* Don't hold iflock while handling init events */
11945                ast_mutex_unlock(&iflock);
11946                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11947                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11948                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11949                   else
11950                      doomed = handle_init_event(i, res);
11951                }
11952                ast_mutex_lock(&iflock);
11953             }
11954          }
11955       }
11956       ast_mutex_unlock(&iflock);
11957    }
11958    /* Never reached */
11959    return NULL;
11960 
11961 }

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

Definition at line 4989 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

04990 {
04991    float neg;
04992    float shallow, steep;
04993    float max = SHRT_MAX;
04994    
04995    neg = (sample < 0 ? -1 : 1);
04996    steep = drc*sample;
04997    shallow = neg*(max-max/drc)+(float)sample/drc;
04998    if (abs(steep) < abs(shallow)) {
04999       sample = steep;
05000    }
05001    else {
05002       sample = shallow;
05003    }
05004 
05005    return sample;
05006 }

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

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

13423 {
13424    struct dahdi_pvt *p;
13425    struct dahdi_bufferinfo bi;
13426    int res;
13427 
13428    p = ast_malloc(sizeof(*p));
13429    if (!p) {
13430       return NULL;
13431    }
13432    *p = *src;
13433 
13434    /* Must deep copy the cc_params. */
13435    p->cc_params = ast_cc_config_params_init();
13436    if (!p->cc_params) {
13437       ast_free(p);
13438       return NULL;
13439    }
13440    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13441 
13442    p->which_iflist = DAHDI_IFLIST_NONE;
13443    p->next = NULL;
13444    p->prev = NULL;
13445    ast_mutex_init(&p->lock);
13446    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13447    if (p->subs[SUB_REAL].dfd < 0) {
13448       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13449       destroy_dahdi_pvt(p);
13450       return NULL;
13451    }
13452    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13453    if (!res) {
13454       bi.txbufpolicy = src->buf_policy;
13455       bi.rxbufpolicy = src->buf_policy;
13456       bi.numbufs = src->buf_no;
13457       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13458       if (res < 0) {
13459          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13460       }
13461    } else
13462       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13463    p->destroy = 1;
13464    dahdi_iflist_insert(p);
13465    return p;
13466 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

06661 {
06662    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06663 
06664    if (p->channel == CHAN_PSEUDO)
06665       return;
06666 
06667    p->ignoredtmf = 0;
06668 
06669    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06670 
06671    if (!p->hardwaredtmf && p->dsp) {
06672       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06673       ast_dsp_set_features(p->dsp, p->dsp_features);
06674    }
06675 }

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

Definition at line 4602 of file chan_dahdi.c.

References ARRAY_LEN.

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

04603 {
04604    static char buf[256];
04605    if ((event < (ARRAY_LEN(events))) && (event > -1))
04606       return events[event];
04607    sprintf(buf, "Event %d", event); /* safe */
04608    return buf;
04609 }

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

Definition at line 5053 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

05054 {
05055    int j;
05056    int k;
05057    float linear_gain = pow(10.0, gain / 20.0);
05058 
05059    switch (law) {
05060    case DAHDI_LAW_ALAW:
05061       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05062          if (gain || drc) {
05063             k = AST_ALAW(j);
05064             if (drc) {
05065                k = drc_sample(k, drc);
05066             }
05067             k = (float)k*linear_gain;
05068             if (k > 32767) k = 32767;
05069             if (k < -32767) k = -32767;
05070             g->rxgain[j] = AST_LIN2A(k);
05071          } else {
05072             g->rxgain[j] = j;
05073          }
05074       }
05075       break;
05076    case DAHDI_LAW_MULAW:
05077       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05078          if (gain || drc) {
05079             k = AST_MULAW(j);
05080             if (drc) {
05081                k = drc_sample(k, drc);
05082             }
05083             k = (float)k*linear_gain;
05084             if (k > 32767) k = 32767;
05085             if (k < -32767) k = -32767;
05086             g->rxgain[j] = AST_LIN2MU(k);
05087          } else {
05088             g->rxgain[j] = j;
05089          }
05090       }
05091       break;
05092    }
05093 }

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

Definition at line 5009 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

05010 {
05011    int j;
05012    int k;
05013 
05014    float linear_gain = pow(10.0, gain / 20.0);
05015 
05016    switch (law) {
05017    case DAHDI_LAW_ALAW:
05018       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05019          if (gain || drc) {
05020             k = AST_ALAW(j);
05021             if (drc) {
05022                k = drc_sample(k, drc);
05023             }
05024             k = (float)k*linear_gain;
05025             if (k > 32767) k = 32767;
05026             if (k < -32767) k = -32767;
05027             g->txgain[j] = AST_LIN2A(k);
05028          } else {
05029             g->txgain[j] = j;
05030          }
05031       }
05032       break;
05033    case DAHDI_LAW_MULAW:
05034       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05035          if (gain || drc) {
05036             k = AST_MULAW(j);
05037             if (drc) {
05038                k = drc_sample(k, drc);
05039             }
05040             k = (float)k*linear_gain;
05041             if (k > 32767) k = 32767;
05042             if (k < -32767) k = -32767;
05043             g->txgain[j] = AST_LIN2MU(k);
05044 
05045          } else {
05046             g->txgain[j] = j;
05047          }
05048       }
05049       break;
05050    }
05051 }

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

Definition at line 15897 of file chan_dahdi.c.

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

Referenced by find_channel_from_str().

15898 {
15899    struct dahdi_pvt *p;
15900 
15901    ast_mutex_lock(&iflock);
15902    for (p = iflist; p; p = p->next) {
15903       if (p->channel == channel) {
15904          break;
15905       }
15906    }
15907    ast_mutex_unlock(&iflock);
15908    return p;
15909 }

static struct dahdi_pvt* find_channel_from_str ( const char *  channel  )  [static]

Definition at line 15920 of file chan_dahdi.c.

References find_channel().

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

15921 {
15922    int chan_num;
15923 
15924    if (sscanf(channel, "%30d", &chan_num) != 1) {
15925       /* Not numeric string. */
15926       return NULL;
15927    }
15928 
15929    return find_channel(chan_num);
15930 }

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

Definition at line 5737 of file chan_dahdi.c.

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

Referenced by destroy_dahdi_pvt().

05738 {
05739    if (cur->next && cur->next->span == cur->span) {
05740       return cur->next;
05741    } else if (cur->prev && cur->prev->span == cur->span) {
05742       return cur->prev;
05743    }
05744 
05745    return NULL;
05746 }

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

07731 {
07732    int res;
07733    struct dahdi_spaninfo zi;
07734    struct dahdi_params params;
07735 
07736    memset(&zi, 0, sizeof(zi));
07737    zi.spanno = p->span;
07738 
07739    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07740       if (zi.alarms != DAHDI_ALARM_NONE)
07741          return zi.alarms;
07742    } else {
07743       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07744       return 0;
07745    }
07746 
07747    /* No alarms on the span. Check for channel alarms. */
07748    memset(&params, 0, sizeof(params));
07749    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07750       return params.chan_alarms;
07751 
07752    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07753 
07754    return DAHDI_ALARM_NONE;
07755 }

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

Definition at line 7855 of file chan_dahdi.c.

References alarm2str(), ast_log(), dahdi_pvt::channel, dahdi_sig_pri_lib_handles(), EVENT_FLAG_SYSTEM, manager_event, dahdi_pvt::manages_span_alarms, dahdi_pvt::pri, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::sig, sig_pri_is_alarm_ignored(), 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().

07856 {
07857    const char *alarm_str;
07858 
07859 #if defined(HAVE_PRI)
07860    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07861       return;
07862    }
07863 #endif   /* defined(HAVE_PRI) */
07864 
07865    alarm_str = alarm2str(alms);
07866    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07867       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07868       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07869                  "Alarm: %s\r\n"
07870                  "Channel: %d\r\n",
07871                  alarm_str, p->channel);
07872    }
07873 
07874    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07875       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07876       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07877                  "Alarm: %s\r\n"
07878                  "Span: %d\r\n",
07879                  alarm_str, p->span);
07880    }
07881 }

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3816 of file chan_dahdi.c.

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

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

03817 {
03818 #if defined(HAVE_PRI)
03819    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03820       return;
03821    }
03822 #endif   /* defined(HAVE_PRI) */
03823 
03824    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03825       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03826       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03827    }
03828    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03829       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03830       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03831    }
03832 }

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

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

15516 {
15517    int i, j;
15518    switch (cmd) {
15519    case CLI_INIT:
15520       e->command = "dahdi show cadences";
15521       e->usage =
15522          "Usage: dahdi show cadences\n"
15523          "       Shows all cadences currently defined\n";
15524       return NULL;
15525    case CLI_GENERATE:
15526       return NULL;
15527    }
15528    for (i = 0; i < num_cadence; i++) {
15529       char output[1024];
15530       char tmp[16], tmp2[64];
15531       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15532       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15533 
15534       for (j = 0; j < 16; j++) {
15535          if (cadences[i].ringcadence[j] == 0)
15536             break;
15537          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15538          if (cidrings[i] * 2 - 1 == j)
15539             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15540          else
15541             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15542          if (j != 0)
15543             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15544          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15545       }
15546       ast_cli(a->fd,"%s\n",output);
15547    }
15548    return CLI_SUCCESS;
15549 }

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

Definition at line 11433 of file chan_dahdi.c.

References analog_ss_thread(), ast_free, ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_unlock, 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, dahdi_pvt::lock, 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.

11434 {
11435    int res;
11436    pthread_t threadid;
11437    struct ast_channel *chan;
11438 
11439    /* Handle an event on a given channel for the monitor thread. */
11440 
11441    switch (event) {
11442    case DAHDI_EVENT_NONE:
11443    case DAHDI_EVENT_BITSCHANGED:
11444       break;
11445    case DAHDI_EVENT_WINKFLASH:
11446    case DAHDI_EVENT_RINGOFFHOOK:
11447       if (i->inalarm) break;
11448       if (i->radio) break;
11449       /* Got a ring/answer.  What kind of channel are we? */
11450       switch (i->sig) {
11451       case SIG_FXOLS:
11452       case SIG_FXOGS:
11453       case SIG_FXOKS:
11454          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11455          if (res && (errno == EBUSY))
11456             break;
11457 
11458          /* Cancel VMWI spill */
11459          ast_free(i->cidspill);
11460          i->cidspill = NULL;
11461          restore_conference(i);
11462 
11463          if (i->immediate) {
11464             dahdi_enable_ec(i);
11465             /* The channel is immediately up.  Start right away */
11466             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11467             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11468             if (!chan) {
11469                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11470                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11471                if (res < 0)
11472                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11473             }
11474          } else {
11475             /* Check for callerid, digits, etc */
11476             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11477             if (chan) {
11478                if (has_voicemail(i))
11479                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11480                else
11481                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11482                if (res < 0)
11483                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11484                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11485                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11486                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11487                   if (res < 0)
11488                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11489                   ast_hangup(chan);
11490                }
11491             } else
11492                ast_log(LOG_WARNING, "Unable to create channel\n");
11493          }
11494          break;
11495       case SIG_FXSLS:
11496       case SIG_FXSGS:
11497       case SIG_FXSKS:
11498             i->ringt = i->ringt_base;
11499             /* Fall through */
11500       case SIG_EMWINK:
11501       case SIG_FEATD:
11502       case SIG_FEATDMF:
11503       case SIG_FEATDMF_TA:
11504       case SIG_E911:
11505       case SIG_FGC_CAMA:
11506       case SIG_FGC_CAMAMF:
11507       case SIG_FEATB:
11508       case SIG_EM:
11509       case SIG_EM_E1:
11510       case SIG_SFWINK:
11511       case SIG_SF_FEATD:
11512       case SIG_SF_FEATDMF:
11513       case SIG_SF_FEATB:
11514       case SIG_SF:
11515          /* Check for callerid, digits, etc */
11516          if (i->cid_start == CID_START_POLARITY_IN) {
11517             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11518          } else {
11519             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11520          }
11521 
11522          if (!chan) {
11523             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11524          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11525             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11526             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11527             if (res < 0) {
11528                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11529             }
11530             ast_hangup(chan);
11531          }
11532          break;
11533       default:
11534          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11535          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11536          if (res < 0)
11537             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11538          return NULL;
11539       }
11540       break;
11541    case DAHDI_EVENT_NOALARM:
11542       switch (i->sig) {
11543 #if defined(HAVE_PRI)
11544       case SIG_PRI_LIB_HANDLE_CASES:
11545          ast_mutex_lock(&i->lock);
11546          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11547          ast_mutex_unlock(&i->lock);
11548          break;
11549 #endif   /* defined(HAVE_PRI) */
11550 #if defined(HAVE_SS7)
11551       case SIG_SS7:
11552          sig_ss7_set_alarm(i->sig_pvt, 0);
11553          break;
11554 #endif   /* defined(HAVE_SS7) */
11555       default:
11556          i->inalarm = 0;
11557          break;
11558       }
11559       handle_clear_alarms(i);
11560       break;
11561    case DAHDI_EVENT_ALARM:
11562       switch (i->sig) {
11563 #if defined(HAVE_PRI)
11564       case SIG_PRI_LIB_HANDLE_CASES:
11565          ast_mutex_lock(&i->lock);
11566          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11567          ast_mutex_unlock(&i->lock);
11568          break;
11569 #endif   /* defined(HAVE_PRI) */
11570 #if defined(HAVE_SS7)
11571       case SIG_SS7:
11572          sig_ss7_set_alarm(i->sig_pvt, 1);
11573          break;
11574 #endif   /* defined(HAVE_SS7) */
11575       default:
11576          i->inalarm = 1;
11577          break;
11578       }
11579       res = get_alarms(i);
11580       handle_alarms(i, res);
11581       /* fall thru intentionally */
11582    case DAHDI_EVENT_ONHOOK:
11583       if (i->radio)
11584          break;
11585       /* Back on hook.  Hang up. */
11586       switch (i->sig) {
11587       case SIG_FXOLS:
11588       case SIG_FXOGS:
11589       case SIG_FEATD:
11590       case SIG_FEATDMF:
11591       case SIG_FEATDMF_TA:
11592       case SIG_E911:
11593       case SIG_FGC_CAMA:
11594       case SIG_FGC_CAMAMF:
11595       case SIG_FEATB:
11596       case SIG_EM:
11597       case SIG_EM_E1:
11598       case SIG_EMWINK:
11599       case SIG_SF_FEATD:
11600       case SIG_SF_FEATDMF:
11601       case SIG_SF_FEATB:
11602       case SIG_SF:
11603       case SIG_SFWINK:
11604       case SIG_FXSLS:
11605       case SIG_FXSGS:
11606       case SIG_FXSKS:
11607       case SIG_FXOKS:
11608          dahdi_disable_ec(i);
11609          /* Diddle the battery for the zhone */
11610 #ifdef ZHONE_HACK
11611          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11612          usleep(1);
11613 #endif
11614          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11615          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11616          break;
11617       case SIG_SS7:
11618       case SIG_PRI_LIB_HANDLE_CASES:
11619          dahdi_disable_ec(i);
11620          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11621          break;
11622       default:
11623          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11624          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11625          return NULL;
11626       }
11627       break;
11628    case DAHDI_EVENT_POLARITY:
11629       switch (i->sig) {
11630       case SIG_FXSLS:
11631       case SIG_FXSKS:
11632       case SIG_FXSGS:
11633          /* We have already got a PR before the channel was
11634             created, but it wasn't handled. We need polarity
11635             to be REV for remote hangup detection to work.
11636             At least in Spain */
11637          if (i->hanguponpolarityswitch)
11638             i->polarity = POLARITY_REV;
11639          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11640             i->polarity = POLARITY_REV;
11641             ast_verb(2, "Starting post polarity "
11642                "CID detection on channel %d\n",
11643                i->channel);
11644             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11645             if (!chan) {
11646                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11647             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11648                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11649                ast_hangup(chan);
11650             }
11651          }
11652          break;
11653       default:
11654          ast_log(LOG_WARNING, "handle_init_event detected "
11655             "polarity reversal on non-FXO (SIG_FXS) "
11656             "interface %d\n", i->channel);
11657       }
11658       break;
11659    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11660       ast_log(LOG_NOTICE,
11661             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11662             i->channel);
11663       return i;
11664    case DAHDI_EVENT_NEONMWI_ACTIVE:
11665       if (i->mwimonitor_neon) {
11666          notify_message(i->mailbox, 1);
11667          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11668       }
11669       break;
11670    case DAHDI_EVENT_NEONMWI_INACTIVE:
11671       if (i->mwimonitor_neon) {
11672          notify_message(i->mailbox, 0);
11673          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11674       }
11675       break;
11676    }
11677    return NULL;
11678 }

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

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

14883 {
14884    struct dahdi_pvt *p = NULL;
14885    int channo = 0;
14886    switch (cmd) {
14887    case CLI_INIT:
14888       e->command = "mfcr2 call files [on|off]";
14889       e->usage =
14890          "Usage: mfcr2 call files [on|off] <channel>\n"
14891          "       Enable call files creation on the specified channel.\n"
14892          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14893       return NULL;
14894    case CLI_GENERATE:
14895       return NULL;
14896    }
14897    if (a->argc < 4) {
14898       return CLI_SHOWUSAGE;
14899    }
14900    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14901    ast_mutex_lock(&iflock);
14902    for (p = iflist; p; p = p->next) {
14903       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14904          continue;
14905       }
14906       if ((channo != -1) && (p->channel != channo )) {
14907          continue;
14908       }
14909       if (ast_true(a->argv[3])) {
14910          openr2_chan_enable_call_files(p->r2chan);
14911       } else {
14912          openr2_chan_disable_call_files(p->r2chan);
14913       }
14914       if (channo != -1) {
14915          if (ast_true(a->argv[3])) {
14916             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14917          } else {
14918             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14919          }
14920          break;
14921       }
14922    }
14923    if ((channo != -1) && !p) {
14924       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14925    }
14926    if (channo == -1) {
14927       if (ast_true(a->argv[3])) {
14928          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14929       } else {
14930          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14931       }
14932    }
14933    ast_mutex_unlock(&iflock);
14934    return CLI_SUCCESS;
14935 }

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

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

14979 {
14980    struct dahdi_pvt *p = NULL;
14981    int channo = 0;
14982    switch (cmd) {
14983    case CLI_INIT:
14984       e->command = "mfcr2 set blocked";
14985       e->usage =
14986          "Usage: mfcr2 set blocked <channel>\n"
14987          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14988          "       Force the given channel into BLOCKED state.\n"
14989          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14990       return NULL;
14991    case CLI_GENERATE:
14992       return NULL;
14993    }
14994    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14995    ast_mutex_lock(&iflock);
14996    for (p = iflist; p; p = p->next) {
14997       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14998          continue;
14999       }
15000       if ((channo != -1) && (p->channel != channo )) {
15001          continue;
15002       }
15003       openr2_chan_set_blocked(p->r2chan);
15004       ast_mutex_lock(&p->lock);
15005       p->locallyblocked = 1;
15006       ast_mutex_unlock(&p->lock);
15007       if (channo != -1) {
15008          break;
15009       }
15010    }
15011    if ((channo != -1) && !p) {
15012       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15013    }
15014    ast_mutex_unlock(&iflock);
15015    return CLI_SUCCESS;
15016 }

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

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

14818 {
14819    struct dahdi_pvt *p = NULL;
14820    int channo = 0;
14821    char *toklevel = NULL;
14822    char *saveptr = NULL;
14823    char *logval = NULL;
14824    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14825    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14826    switch (cmd) {
14827    case CLI_INIT:
14828       e->command = "mfcr2 set debug";
14829       e->usage =
14830          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14831          "       Set a new logging level for the specified channel.\n"
14832          "       If no channel is specified the logging level will be applied to all channels.\n";
14833       return NULL;
14834    case CLI_GENERATE:
14835       return NULL;
14836    }
14837    if (a->argc < 4) {
14838       return CLI_SHOWUSAGE;
14839    }
14840    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14841    logval = ast_strdupa(a->argv[3]);
14842    toklevel = strtok_r(logval, ",", &saveptr);
14843    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14844       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14845       return CLI_FAILURE;
14846    } else if (OR2_LOG_NOTHING == tmplevel) {
14847       loglevel = tmplevel;
14848    } else {
14849       loglevel |= tmplevel;
14850       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14851          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14852             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14853             continue;
14854          }
14855          loglevel |= tmplevel;
14856       }
14857    }
14858    ast_mutex_lock(&iflock);
14859    for (p = iflist; p; p = p->next) {
14860       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14861          continue;
14862       }
14863       if ((channo != -1) && (p->channel != channo )) {
14864          continue;
14865       }
14866       openr2_chan_set_log_level(p->r2chan, loglevel);
14867       if (channo != -1) {
14868          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14869          break;
14870       }
14871    }
14872    if ((channo != -1) && !p) {
14873       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14874    }
14875    if (channo == -1) {
14876       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14877    }
14878    ast_mutex_unlock(&iflock);
14879    return CLI_SUCCESS;
14880 }

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

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

14938 {
14939    struct dahdi_pvt *p = NULL;
14940    int channo = 0;
14941    switch (cmd) {
14942    case CLI_INIT:
14943       e->command = "mfcr2 set idle";
14944       e->usage =
14945          "Usage: mfcr2 set idle <channel>\n"
14946          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14947          "       Force the given channel into IDLE state.\n"
14948          "       If no channel is specified, all channels will be set to IDLE.\n";
14949       return NULL;
14950    case CLI_GENERATE:
14951       return NULL;
14952    }
14953    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14954    ast_mutex_lock(&iflock);
14955    for (p = iflist; p; p = p->next) {
14956       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14957          continue;
14958       }
14959       if ((channo != -1) && (p->channel != channo )) {
14960          continue;
14961       }
14962       openr2_chan_set_idle(p->r2chan);
14963       ast_mutex_lock(&p->lock);
14964       p->locallyblocked = 0;
14965       p->mfcr2call = 0;
14966       ast_mutex_unlock(&p->lock);
14967       if (channo != -1) {
14968          break;
14969       }
14970    }
14971    if ((channo != -1) && !p) {
14972       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14973    }
14974    ast_mutex_unlock(&iflock);
14975    return CLI_SUCCESS;
14976 }

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

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

14744 {
14745 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14746    int filtertype = 0;
14747    int targetnum = 0;
14748    char channo[5];
14749    char anino[5];
14750    char dnisno[5];
14751    struct dahdi_pvt *p;
14752    openr2_context_t *r2context;
14753    openr2_variant_t r2variant;
14754    switch (cmd) {
14755    case CLI_INIT:
14756       e->command = "mfcr2 show channels [group|context]";
14757       e->usage =
14758          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14759          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14760       return NULL;
14761    case CLI_GENERATE:
14762       return NULL;
14763    }
14764    if (!((a->argc == 3) || (a->argc == 5))) {
14765       return CLI_SHOWUSAGE;
14766    }
14767    if (a->argc == 5) {
14768       if (!strcasecmp(a->argv[3], "group")) {
14769          targetnum = atoi(a->argv[4]);
14770          if ((targetnum < 0) || (targetnum > 63))
14771             return CLI_SHOWUSAGE;
14772          targetnum = 1 << targetnum;
14773          filtertype = 1;
14774       } else if (!strcasecmp(a->argv[3], "context")) {
14775          filtertype = 2;
14776       } else {
14777          return CLI_SHOWUSAGE;
14778       }
14779    }
14780    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14781    ast_mutex_lock(&iflock);
14782    for (p = iflist; p; p = p->next) {
14783       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14784          continue;
14785       }
14786       if (filtertype) {
14787          switch(filtertype) {
14788          case 1: /* mfcr2 show channels group <group> */
14789             if (p->group != targetnum) {
14790                continue;
14791             }
14792             break;
14793          case 2: /* mfcr2 show channels context <context> */
14794             if (strcasecmp(p->context, a->argv[4])) {
14795                continue;
14796             }
14797             break;
14798          default:
14799             ;
14800          }
14801       }
14802       r2context = openr2_chan_get_context(p->r2chan);
14803       r2variant = openr2_context_get_variant(r2context);
14804       snprintf(channo, sizeof(channo), "%d", p->channel);
14805       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14806       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14807       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14808             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14809             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14810             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14811    }
14812    ast_mutex_unlock(&iflock);
14813    return CLI_SUCCESS;
14814 #undef FORMAT
14815 }

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

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

14716 {
14717 #define FORMAT "%4s %40s\n"
14718    int i = 0;
14719    int numvariants = 0;
14720    const openr2_variant_entry_t *variants;
14721    switch (cmd) {
14722    case CLI_INIT:
14723       e->command = "mfcr2 show variants";
14724       e->usage =
14725          "Usage: mfcr2 show variants\n"
14726          "       Shows the list of MFC/R2 variants supported.\n";
14727       return NULL;
14728    case CLI_GENERATE:
14729       return NULL;
14730    }
14731    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14732       ast_cli(a->fd, "Failed to get list of variants.\n");
14733       return CLI_FAILURE;
14734    }
14735    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14736    for (i = 0; i < numvariants; i++) {
14737       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14738    }
14739    return CLI_SUCCESS;
14740 #undef FORMAT
14741 }

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

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

14700 {
14701    switch (cmd) {
14702    case CLI_INIT:
14703       e->command = "mfcr2 show version";
14704       e->usage =
14705          "Usage: mfcr2 show version\n"
14706          "       Shows the version of the OpenR2 library being used.\n";
14707       return NULL;
14708    case CLI_GENERATE:
14709       return NULL;
14710    }
14711    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14712    return CLI_SUCCESS;
14713 }

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

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

14312 {
14313    int span;
14314    int x;
14315    int level = 0;
14316    switch (cmd) {
14317    case CLI_INIT:
14318       e->command = "pri set debug {on|off|0|1|2} span";
14319       e->usage =
14320          "Usage: pri set debug {<level>|on|off} span <span>\n"
14321          "       Enables debugging on a given PRI span\n";
14322       return NULL;
14323    case CLI_GENERATE:
14324       return complete_span_4(a->line, a->word, a->pos, a->n);
14325    }
14326    if (a->argc < 6) {
14327       return CLI_SHOWUSAGE;
14328    }
14329 
14330    if (!strcasecmp(a->argv[3], "on")) {
14331       level = 1;
14332    } else if (!strcasecmp(a->argv[3], "off")) {
14333       level = 0;
14334    } else {
14335       level = atoi(a->argv[3]);
14336    }
14337    span = atoi(a->argv[5]);
14338    if ((span < 1) || (span > NUM_SPANS)) {
14339       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14340       return CLI_SUCCESS;
14341    }
14342    if (!pris[span-1].pri.pri) {
14343       ast_cli(a->fd, "No PRI running on span %d\n", span);
14344       return CLI_SUCCESS;
14345    }
14346 
14347    /* Set debug level in libpri */
14348    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14349       if (pris[span - 1].pri.dchans[x]) {
14350          switch (level) {
14351          case 0:
14352             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14353             break;
14354          case 1:
14355             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14356             break;
14357          default:
14358             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14359             break;
14360          }
14361       }
14362    }
14363    if (level == 0) {
14364       /* Close the debugging file if it's set */
14365       ast_mutex_lock(&pridebugfdlock);
14366       if (0 <= pridebugfd) {
14367          close(pridebugfd);
14368          pridebugfd = -1;
14369          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14370             pridebugfilename);
14371       }
14372       ast_mutex_unlock(&pridebugfdlock);
14373    }
14374    pris[span - 1].pri.debug = (level) ? 1 : 0;
14375    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14376    return CLI_SUCCESS;
14377 }

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

Definition at line 14506 of file chan_dahdi.c.

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

14507 {
14508    switch (cmd) {
14509    case CLI_INIT:
14510       e->command = "pri service disable channel";
14511       e->usage =
14512          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14513          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14514          "  to remove a channel from service, with optional interface id\n"
14515          "  as agreed upon with remote switch operator\n";
14516       return NULL;
14517    case CLI_GENERATE:
14518       return NULL;
14519    }
14520    return handle_pri_service_generic(e, cmd, a, 2);
14521 }

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

Definition at line 14489 of file chan_dahdi.c.

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

14490 {
14491    switch (cmd) {
14492    case CLI_INIT:
14493       e->command = "pri service enable channel";
14494       e->usage =
14495          "Usage: pri service enable channel <channel> [<interface id>]\n"
14496          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14497          "  to restore a channel to service, with optional interface id\n"
14498          "  as agreed upon with remote switch operator\n";
14499       return NULL;
14500    case CLI_GENERATE:
14501       return NULL;
14502    }
14503    return handle_pri_service_generic(e, cmd, a, 0);
14504 }

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

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

14383 {
14384    unsigned *why;
14385    int channel;
14386    int trunkgroup;
14387    int x, y, fd = a->fd;
14388    int interfaceid = 0;
14389    char db_chan_name[20], db_answer[5];
14390    struct dahdi_pvt *tmp;
14391    struct dahdi_pri *pri;
14392 
14393    if (a->argc < 5 || a->argc > 6)
14394       return CLI_SHOWUSAGE;
14395    if (strchr(a->argv[4], ':')) {
14396       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14397          return CLI_SHOWUSAGE;
14398       if ((trunkgroup < 1) || (channel < 1))
14399          return CLI_SHOWUSAGE;
14400       pri = NULL;
14401       for (x=0;x<NUM_SPANS;x++) {
14402          if (pris[x].pri.trunkgroup == trunkgroup) {
14403             pri = pris + x;
14404             break;
14405          }
14406       }
14407       if (!pri) {
14408          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14409          return CLI_FAILURE;
14410       }
14411    } else
14412       channel = atoi(a->argv[4]);
14413 
14414    if (a->argc == 6)
14415       interfaceid = atoi(a->argv[5]);
14416 
14417    /* either servicing a D-Channel */
14418    for (x = 0; x < NUM_SPANS; x++) {
14419       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14420          if (pris[x].dchannels[y] == channel) {
14421             pri = pris + x;
14422             if (pri->pri.enable_service_message_support) {
14423                ast_mutex_lock(&pri->pri.lock);
14424                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14425                ast_mutex_unlock(&pri->pri.lock);
14426             } else {
14427                ast_cli(fd,
14428                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14429                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14430             }
14431             return CLI_SUCCESS;
14432          }
14433       }
14434    }
14435 
14436    /* or servicing a B-Channel */
14437    ast_mutex_lock(&iflock);
14438    for (tmp = iflist; tmp; tmp = tmp->next) {
14439       if (tmp->pri && tmp->channel == channel) {
14440          ast_mutex_unlock(&iflock);
14441          ast_mutex_lock(&tmp->pri->lock);
14442          if (!tmp->pri->enable_service_message_support) {
14443             ast_mutex_unlock(&tmp->pri->lock);
14444             ast_cli(fd,
14445                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14446                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14447             return CLI_SUCCESS;
14448          }
14449          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14450          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14451          switch(changestatus) {
14452          case 0: /* enable */
14453             /* Near end wants to be in service now. */
14454             ast_db_del(db_chan_name, SRVST_DBKEY);
14455             *why &= ~SRVST_NEAREND;
14456             if (*why) {
14457                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14458                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14459             } else {
14460                dahdi_pri_update_span_devstate(tmp->pri);
14461             }
14462             break;
14463          /* case 1:  -- loop */
14464          case 2: /* disable */
14465             /* Near end wants to be out-of-service now. */
14466             ast_db_del(db_chan_name, SRVST_DBKEY);
14467             *why |= SRVST_NEAREND;
14468             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14469             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14470             dahdi_pri_update_span_devstate(tmp->pri);
14471             break;
14472          /* case 3:  -- continuity */
14473          /* case 4:  -- shutdown */
14474          default:
14475             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14476             break;
14477          }
14478          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14479          ast_mutex_unlock(&tmp->pri->lock);
14480          return CLI_SUCCESS;
14481       }
14482    }
14483    ast_mutex_unlock(&iflock);
14484 
14485    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14486    return CLI_FAILURE;
14487 }

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

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

14274 {
14275    int myfd;
14276    switch (cmd) {
14277    case CLI_INIT:
14278       e->command = "pri set debug file";
14279       e->usage = "Usage: pri set debug file [output-file]\n"
14280          "       Sends PRI debug output to the specified output file\n";
14281       return NULL;
14282    case CLI_GENERATE:
14283       return NULL;
14284    }
14285    if (a->argc < 5)
14286       return CLI_SHOWUSAGE;
14287 
14288    if (ast_strlen_zero(a->argv[4]))
14289       return CLI_SHOWUSAGE;
14290 
14291    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14292    if (myfd < 0) {
14293       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14294       return CLI_SUCCESS;
14295    }
14296 
14297    ast_mutex_lock(&pridebugfdlock);
14298 
14299    if (pridebugfd >= 0)
14300       close(pridebugfd);
14301 
14302    pridebugfd = myfd;
14303    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14304    ast_mutex_unlock(&pridebugfdlock);
14305    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14306    return CLI_SUCCESS;
14307 }

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

Definition at line 14526 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_channels(), sig_pri_cli_show_channels_header(), and ast_cli_entry::usage.

14527 {
14528    int span;
14529 
14530    switch (cmd) {
14531    case CLI_INIT:
14532       e->command = "pri show channels";
14533       e->usage =
14534          "Usage: pri show channels\n"
14535          "       Displays PRI channel information such as the current mapping\n"
14536          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14537          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14538          "       are not associated with any B channel.\n";
14539       return NULL;
14540    case CLI_GENERATE:
14541       return NULL;
14542    }
14543 
14544    if (a->argc != 3)
14545       return CLI_SHOWUSAGE;
14546 
14547    sig_pri_cli_show_channels_header(a->fd);
14548    for (span = 0; span < NUM_SPANS; ++span) {
14549       if (pris[span].pri.pri) {
14550          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14551       }
14552    }
14553    return CLI_SUCCESS;
14554 }

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

Definition at line 14620 of file chan_dahdi.c.

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

14621 {
14622    int x;
14623    int span;
14624    int count=0;
14625    int debug;
14626 
14627    switch (cmd) {
14628    case CLI_INIT:
14629       e->command = "pri show debug";
14630       e->usage =
14631          "Usage: pri show debug\n"
14632          "  Show the debug state of pri spans\n";
14633       return NULL;
14634    case CLI_GENERATE:
14635       return NULL;
14636    }
14637 
14638    for (span = 0; span < NUM_SPANS; span++) {
14639       if (pris[span].pri.pri) {
14640          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14641             if (pris[span].pri.dchans[x]) {
14642                debug = pri_get_debug(pris[span].pri.dchans[x]);
14643                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" );
14644                count++;
14645             }
14646          }
14647       }
14648 
14649    }
14650    ast_mutex_lock(&pridebugfdlock);
14651    if (pridebugfd >= 0)
14652       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14653    ast_mutex_unlock(&pridebugfdlock);
14654 
14655    if (!count)
14656       ast_cli(a->fd, "No PRI running\n");
14657    return CLI_SUCCESS;
14658 }

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

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

14587 {
14588    int span;
14589 
14590    switch (cmd) {
14591    case CLI_INIT:
14592       e->command = "pri show span";
14593       e->usage =
14594          "Usage: pri show span <span>\n"
14595          "       Displays PRI Information on a given PRI span\n";
14596       return NULL;
14597    case CLI_GENERATE:
14598       return complete_span_4(a->line, a->word, a->pos, a->n);
14599    }
14600 
14601    if (a->argc < 4)
14602       return CLI_SHOWUSAGE;
14603    span = atoi(a->argv[3]);
14604    if ((span < 1) || (span > NUM_SPANS)) {
14605       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14606       return CLI_SUCCESS;
14607    }
14608    if (!pris[span-1].pri.pri) {
14609       ast_cli(a->fd, "No PRI running on span %d\n", span);
14610       return CLI_SUCCESS;
14611    }
14612 
14613    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14614 
14615    return CLI_SUCCESS;
14616 }

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

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

14559 {
14560    int span;
14561 
14562    switch (cmd) {
14563    case CLI_INIT:
14564       e->command = "pri show spans";
14565       e->usage =
14566          "Usage: pri show spans\n"
14567          "       Displays PRI span information\n";
14568       return NULL;
14569    case CLI_GENERATE:
14570       return NULL;
14571    }
14572 
14573    if (a->argc != 3)
14574       return CLI_SHOWUSAGE;
14575 
14576    for (span = 0; span < NUM_SPANS; span++) {
14577       if (pris[span].pri.pri) {
14578          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14579       }
14580    }
14581    return CLI_SUCCESS;
14582 }

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

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

14663 {
14664    switch (cmd) {
14665    case CLI_INIT:
14666       e->command = "pri show version";
14667       e->usage =
14668          "Usage: pri show version\n"
14669          "Show libpri version information\n";
14670       return NULL;
14671    case CLI_GENERATE:
14672       return NULL;
14673    }
14674 
14675    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14676 
14677    return CLI_SUCCESS;
14678 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

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

05273 {
05274    int new_msgs;
05275    struct ast_event *event;
05276    char *mailbox, *context;
05277 
05278    mailbox = context = ast_strdupa(p->mailbox);
05279    strsep(&context, "@");
05280    if (ast_strlen_zero(context))
05281       context = "default";
05282 
05283    event = ast_event_get_cached(AST_EVENT_MWI,
05284       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05285       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05286       AST_EVENT_IE_END);
05287 
05288    if (event) {
05289       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05290       ast_event_destroy(event);
05291    } else
05292       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05293 
05294    return new_msgs;
05295 }

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

13182 {
13183 #if defined(HAVE_PRI)
13184    if (0 < span) {
13185       /* The channel must be on the specified PRI span. */
13186       if (!p->pri || p->pri->span != span) {
13187          return 0;
13188       }
13189       if (!groupmatch && channelmatch == -1) {
13190          /* Match any group since it only needs to be on the PRI span. */
13191          *groupmatched = 1;
13192          return 1;
13193       }
13194    }
13195 #endif   /* defined(HAVE_PRI) */
13196    /* check group matching */
13197    if (groupmatch) {
13198       if ((p->group & groupmatch) != groupmatch)
13199          /* Doesn't match the specified group, try the next one */
13200          return 0;
13201       *groupmatched = 1;
13202    }
13203    /* Check to see if we have a channel match */
13204    if (channelmatch != -1) {
13205       if (p->channel != channelmatch)
13206          /* Doesn't match the specified channel, try the next one */
13207          return 0;
13208       *channelmatched = 1;
13209    }
13210 
13211    return 1;
13212 }

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

Definition at line 4754 of file chan_dahdi.c.

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

Referenced by conf_del().

04755 {
04756    /* If they're listening to our channel, they're ours */
04757    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04758       return 1;
04759    /* If they're a talker on our (allocated) conference, they're ours */
04760    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04761       return 1;
04762    return 0;
04763 }

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

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

04785 {
04786    int x;
04787    int useslavenative;
04788    struct dahdi_pvt *slave = NULL;
04789    /* Start out optimistic */
04790    useslavenative = 1;
04791    /* Update conference state in a stateless fashion */
04792    for (x = 0; x < 3; x++) {
04793       /* Any three-way calling makes slave native mode *definitely* out
04794          of the question */
04795       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04796          useslavenative = 0;
04797    }
04798    /* If we don't have any 3-way calls, check to see if we have
04799       precisely one slave */
04800    if (useslavenative) {
04801       for (x = 0; x < MAX_SLAVES; x++) {
04802          if (p->slaves[x]) {
04803             if (slave) {
04804                /* Whoops already have a slave!  No
04805                   slave native and stop right away */
04806                slave = NULL;
04807                useslavenative = 0;
04808                break;
04809             } else {
04810                /* We have one slave so far */
04811                slave = p->slaves[x];
04812             }
04813          }
04814       }
04815    }
04816    /* If no slave, slave native definitely out */
04817    if (!slave)
04818       useslavenative = 0;
04819    else if (slave->law != p->law) {
04820       useslavenative = 0;
04821       slave = NULL;
04822    }
04823    if (out)
04824       *out = slave;
04825    return useslavenative;
04826 }

static int load_module ( void   )  [static]

Definition at line 18569 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_cc_agent_callbacks, dahdi_pri_cc_monitor_callbacks, dahdi_pri_cc_type, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_callrerouting_facility_exec(), dahdi_send_keypad_facility_exec(), dahdi_tech, HAVE_PRI_CCSS, round_robin, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), sig_ss7_init_linkset(), and ss_thread_complete.

18570 {
18571    int res;
18572 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18573    int y;
18574 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18575 
18576 #ifdef HAVE_PRI
18577    memset(pris, 0, sizeof(pris));
18578    for (y = 0; y < NUM_SPANS; y++) {
18579       sig_pri_init_pri(&pris[y].pri);
18580    }
18581    pri_set_error(dahdi_pri_error);
18582    pri_set_message(dahdi_pri_message);
18583    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18584 #ifdef HAVE_PRI_PROG_W_CAUSE
18585    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18586 #endif
18587 #if defined(HAVE_PRI_CCSS)
18588    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18589       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18590       __unload_module();
18591       return AST_MODULE_LOAD_FAILURE;
18592    }
18593 #endif   /* defined(HAVE_PRI_CCSS) */
18594    if (sig_pri_load(
18595 #if defined(HAVE_PRI_CCSS)
18596       dahdi_pri_cc_type
18597 #else
18598       NULL
18599 #endif   /* defined(HAVE_PRI_CCSS) */
18600       )) {
18601       __unload_module();
18602       return AST_MODULE_LOAD_FAILURE;
18603    }
18604 #endif
18605 #if defined(HAVE_SS7)
18606    memset(linksets, 0, sizeof(linksets));
18607    for (y = 0; y < NUM_SPANS; y++) {
18608       sig_ss7_init_linkset(&linksets[y].ss7);
18609    }
18610    ss7_set_error(dahdi_ss7_error);
18611    ss7_set_message(dahdi_ss7_message);
18612 #endif   /* defined(HAVE_SS7) */
18613    res = setup_dahdi(0);
18614    /* Make sure we can register our DAHDI channel type */
18615    if (res)
18616       return AST_MODULE_LOAD_DECLINE;
18617    if (ast_channel_register(&dahdi_tech)) {
18618       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18619       __unload_module();
18620       return AST_MODULE_LOAD_FAILURE;
18621    }
18622 #ifdef HAVE_PRI
18623    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18624 #endif
18625 #if defined(HAVE_SS7)
18626    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18627 #endif   /* defined(HAVE_SS7) */
18628 #ifdef HAVE_OPENR2
18629    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18630    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18631 #endif
18632 
18633    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18634    /* register all the data providers */
18635    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18636    memset(round_robin, 0, sizeof(round_robin));
18637    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18638    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18639    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18640    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18641    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18642    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18643    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18644 
18645    ast_cond_init(&ss_thread_complete, NULL);
18646 
18647    return res;
18648 }

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

Definition at line 14004 of file chan_dahdi.c.

References ast_log(), LOG_DEBUG, and SUB_REAL.

14005 {
14006    struct dahdi_mfcr2 *mfcr2 = data;
14007    /* we should be using pthread_key_create
14008       and allocate pollers dynamically.
14009       I think do_monitor() could be leaking, since it
14010       could be cancelled at any time and is not
14011       using thread keys, why?, */
14012    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14013    int res = 0;
14014    int i = 0;
14015    int oldstate = 0;
14016    int quit_loop = 0;
14017    int maxsleep = 20;
14018    int was_idle = 0;
14019    int pollsize = 0;
14020    /* now that we're ready to get calls, unblock our side and
14021       get current line state */
14022    for (i = 0; i < mfcr2->numchans; i++) {
14023       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14024       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14025    }
14026    while (1) {
14027       /* we trust here that the mfcr2 channel list will not ever change once
14028          the module is loaded */
14029       pollsize = 0;
14030       for (i = 0; i < mfcr2->numchans; i++) {
14031          pollers[i].revents = 0;
14032          pollers[i].events = 0;
14033          if (mfcr2->pvts[i]->owner) {
14034             continue;
14035          }
14036          if (!mfcr2->pvts[i]->r2chan) {
14037             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14038             quit_loop = 1;
14039             break;
14040          }
14041          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14042          pollers[i].events = POLLIN | POLLPRI;
14043          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14044          pollsize++;
14045       }
14046       if (quit_loop) {
14047          break;
14048       }
14049       if (pollsize == 0) {
14050          if (!was_idle) {
14051             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14052             was_idle = 1;
14053          }
14054          poll(NULL, 0, maxsleep);
14055          continue;
14056       }
14057       was_idle = 0;
14058       /* probably poll() is a valid cancel point, lets just be on the safe side
14059          by calling pthread_testcancel */
14060       pthread_testcancel();
14061       res = poll(pollers, mfcr2->numchans, maxsleep);
14062       pthread_testcancel();
14063       if ((res < 0) && (errno != EINTR)) {
14064          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14065          break;
14066       }
14067       /* do we want to allow to cancel while processing events? */
14068       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14069       for (i = 0; i < mfcr2->numchans; i++) {
14070          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14071             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14072          }
14073       }
14074       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14075    }
14076    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14077    return 0;
14078 }

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

Definition at line 12290 of file chan_dahdi.c.

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

Referenced by build_channels().

12291 {
12292    /* Make a dahdi_pvt structure for this interface */
12293    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12294    char fn[80];
12295    struct dahdi_bufferinfo bi;
12296 
12297    int res;
12298 #if defined(HAVE_PRI)
12299    int span = 0;
12300 #endif   /* defined(HAVE_PRI) */
12301    int here = 0;/*!< TRUE if the channel interface already exists. */
12302    int x;
12303    struct analog_pvt *analog_p = NULL;
12304    struct dahdi_params p;
12305 #if defined(HAVE_PRI)
12306    struct dahdi_spaninfo si;
12307    struct sig_pri_chan *pri_chan = NULL;
12308 #endif   /* defined(HAVE_PRI) */
12309 #if defined(HAVE_SS7)
12310    struct sig_ss7_chan *ss7_chan = NULL;
12311 #endif   /* defined(HAVE_SS7) */
12312 
12313    /* Search channel interface list to see if it already exists. */
12314    for (tmp = iflist; tmp; tmp = tmp->next) {
12315       if (!tmp->destroy) {
12316          if (tmp->channel == channel) {
12317             /* The channel interface already exists. */
12318             here = 1;
12319             break;
12320          }
12321          if (tmp->channel > channel) {
12322             /* No way it can be in the sorted list. */
12323             tmp = NULL;
12324             break;
12325          }
12326       }
12327    }
12328 
12329    if (!here && reloading != 1) {
12330       tmp = ast_calloc(1, sizeof(*tmp));
12331       if (!tmp) {
12332          return NULL;
12333       }
12334       tmp->cc_params = ast_cc_config_params_init();
12335       if (!tmp->cc_params) {
12336          ast_free(tmp);
12337          return NULL;
12338       }
12339       ast_mutex_init(&tmp->lock);
12340       ifcount++;
12341       for (x = 0; x < 3; x++)
12342          tmp->subs[x].dfd = -1;
12343       tmp->channel = channel;
12344       tmp->priindication_oob = conf->chan.priindication_oob;
12345    }
12346 
12347    if (tmp) {
12348       int chan_sig = conf->chan.sig;
12349 
12350       /* If there are variables in tmp before it is updated to match the new config, clear them */
12351       if (reloading && tmp->vars) {
12352          ast_variables_destroy(tmp->vars);
12353          tmp->vars = NULL;
12354       }
12355 
12356 
12357       if (!here) {
12358          /* Can only get here if this is a new channel interface being created. */
12359          if ((channel != CHAN_PSEUDO)) {
12360             int count = 0;
12361 
12362             snprintf(fn, sizeof(fn), "%d", channel);
12363             /* Open non-blocking */
12364             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12365             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 */
12366                usleep(1);
12367                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12368                count++;
12369             }
12370             /* Allocate a DAHDI structure */
12371             if (tmp->subs[SUB_REAL].dfd < 0) {
12372                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);
12373                destroy_dahdi_pvt(tmp);
12374                return NULL;
12375             }
12376             memset(&p, 0, sizeof(p));
12377             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12378             if (res < 0) {
12379                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12380                destroy_dahdi_pvt(tmp);
12381                return NULL;
12382             }
12383             if (conf->is_sig_auto)
12384                chan_sig = sigtype_to_signalling(p.sigtype);
12385             if (p.sigtype != (chan_sig & 0x3ffff)) {
12386                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));
12387                destroy_dahdi_pvt(tmp);
12388                return NULL;
12389             }
12390             tmp->law_default = p.curlaw;
12391             tmp->law = p.curlaw;
12392             tmp->span = p.spanno;
12393 #if defined(HAVE_PRI)
12394             span = p.spanno - 1;
12395 #endif   /* defined(HAVE_PRI) */
12396          } else {
12397             chan_sig = 0;
12398          }
12399          tmp->sig = chan_sig;
12400          tmp->outsigmod = conf->chan.outsigmod;
12401 
12402          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12403             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12404             if (!analog_p) {
12405                destroy_dahdi_pvt(tmp);
12406                return NULL;
12407             }
12408             tmp->sig_pvt = analog_p;
12409          }
12410 #if defined(HAVE_SS7)
12411          if (chan_sig == SIG_SS7) {
12412             struct dahdi_ss7 *ss7;
12413             int clear = 0;
12414 
12415             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12416                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12417                destroy_dahdi_pvt(tmp);
12418                return NULL;
12419             }
12420 
12421             ss7 = ss7_resolve_linkset(cur_linkset);
12422             if (!ss7) {
12423                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12424                destroy_dahdi_pvt(tmp);
12425                return NULL;
12426             }
12427             ss7->ss7.span = cur_linkset;
12428             if (cur_cicbeginswith < 0) {
12429                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12430                destroy_dahdi_pvt(tmp);
12431                return NULL;
12432             }
12433             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12434             if (!ss7_chan) {
12435                destroy_dahdi_pvt(tmp);
12436                return NULL;
12437             }
12438             tmp->sig_pvt = ss7_chan;
12439             tmp->ss7 = &ss7->ss7;
12440 
12441             ss7_chan->channel = tmp->channel;
12442             ss7_chan->cic = cur_cicbeginswith++;
12443 
12444             /* DB: Add CIC's DPC information */
12445             ss7_chan->dpc = cur_defaultdpc;
12446 
12447             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12448 
12449             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12450             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12451             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12452             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12453 
12454             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12455             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12456          }
12457 #endif   /* defined(HAVE_SS7) */
12458 #ifdef HAVE_OPENR2
12459          if (chan_sig == SIG_MFCR2) {
12460             struct dahdi_mfcr2 *r2_link;
12461             r2_link = dahdi_r2_get_link();
12462             if (!r2_link) {
12463                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12464                destroy_dahdi_pvt(tmp);
12465                return NULL;
12466             }
12467             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12468                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12469                destroy_dahdi_pvt(tmp);
12470                return NULL;
12471             }
12472             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12473                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12474                destroy_dahdi_pvt(tmp);
12475                return NULL;
12476             }
12477             r2_link->pvts[r2_link->numchans++] = tmp;
12478             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12479                                         tmp->subs[SUB_REAL].dfd,
12480                                         NULL, NULL);
12481             if (!tmp->r2chan) {
12482                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12483                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12484                destroy_dahdi_pvt(tmp);
12485                return NULL;
12486             }
12487             tmp->mfcr2 = r2_link;
12488             if (conf->mfcr2.call_files) {
12489                openr2_chan_enable_call_files(tmp->r2chan);
12490             }
12491             openr2_chan_set_client_data(tmp->r2chan, tmp);
12492             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12493             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12494             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12495             tmp->mfcr2_category = conf->mfcr2.category;
12496             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12497             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12498             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12499             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12500             tmp->mfcr2call = 0;
12501             tmp->mfcr2_dnis_index = 0;
12502             tmp->mfcr2_ani_index = 0;
12503             r2_link->monitored_count++;
12504          }
12505 #endif
12506 #ifdef HAVE_PRI
12507          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12508             int offset;
12509             int matchesdchan;
12510             int x,y;
12511             int myswitchtype = 0;
12512 
12513             offset = 0;
12514             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12515                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12516                destroy_dahdi_pvt(tmp);
12517                return NULL;
12518             }
12519             if (span >= NUM_SPANS) {
12520                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12521                destroy_dahdi_pvt(tmp);
12522                return NULL;
12523             } else {
12524                si.spanno = 0;
12525                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12526                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12527                   destroy_dahdi_pvt(tmp);
12528                   return NULL;
12529                }
12530                /* Store the logical span first based upon the real span */
12531                tmp->logicalspan = pris[span].prilogicalspan;
12532                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12533                if (span < 0) {
12534                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12535                   destroy_dahdi_pvt(tmp);
12536                   return NULL;
12537                }
12538                myswitchtype = conf->pri.pri.switchtype;
12539                /* Make sure this isn't a d-channel */
12540                matchesdchan=0;
12541                for (x = 0; x < NUM_SPANS; x++) {
12542                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12543                      if (pris[x].dchannels[y] == tmp->channel) {
12544                         matchesdchan = 1;
12545                         break;
12546                      }
12547                   }
12548                }
12549                if (!matchesdchan) {
12550                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12551                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12552                      destroy_dahdi_pvt(tmp);
12553                      return NULL;
12554                   }
12555                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12556                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12557                      destroy_dahdi_pvt(tmp);
12558                      return NULL;
12559                   }
12560                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12561                      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));
12562                      destroy_dahdi_pvt(tmp);
12563                      return NULL;
12564                   }
12565                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12566                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12567                      destroy_dahdi_pvt(tmp);
12568                      return NULL;
12569                   }
12570                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12571                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12572                      destroy_dahdi_pvt(tmp);
12573                      return NULL;
12574                   }
12575                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12576                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12577                      destroy_dahdi_pvt(tmp);
12578                      return NULL;
12579                   }
12580                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12581                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12582                      destroy_dahdi_pvt(tmp);
12583                      return NULL;
12584                   }
12585                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12586                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12587                         pris[span].pri.trunkgroup);
12588                      destroy_dahdi_pvt(tmp);
12589                      return NULL;
12590                   }
12591 
12592                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12593                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12594                   if (!pri_chan) {
12595                      destroy_dahdi_pvt(tmp);
12596                      return NULL;
12597                   }
12598                   tmp->sig_pvt = pri_chan;
12599                   tmp->pri = &pris[span].pri;
12600 
12601                   tmp->priexclusive = conf->chan.priexclusive;
12602 
12603                   if (!tmp->pri->cc_params) {
12604                      tmp->pri->cc_params = ast_cc_config_params_init();
12605                      if (!tmp->pri->cc_params) {
12606                         destroy_dahdi_pvt(tmp);
12607                         return NULL;
12608                      }
12609                   }
12610                   ast_cc_copy_config_params(tmp->pri->cc_params,
12611                      conf->chan.cc_params);
12612 
12613                   pris[span].pri.sig = chan_sig;
12614                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12615                   pris[span].pri.switchtype = myswitchtype;
12616                   pris[span].pri.nsf = conf->pri.pri.nsf;
12617                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12618                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12619                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12620                   pris[span].pri.minunused = conf->pri.pri.minunused;
12621                   pris[span].pri.minidle = conf->pri.pri.minidle;
12622                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12623                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12624                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12625 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12626                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12627 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12628 #ifdef HAVE_PRI_INBANDDISCONNECT
12629                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12630 #endif
12631 #if defined(HAVE_PRI_CALL_HOLD)
12632                   pris[span].pri.hold_disconnect_transfer =
12633                      conf->pri.pri.hold_disconnect_transfer;
12634 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12635 #if defined(HAVE_PRI_CCSS)
12636                   pris[span].pri.cc_ptmp_recall_mode =
12637                      conf->pri.pri.cc_ptmp_recall_mode;
12638                   pris[span].pri.cc_qsig_signaling_link_req =
12639                      conf->pri.pri.cc_qsig_signaling_link_req;
12640                   pris[span].pri.cc_qsig_signaling_link_rsp =
12641                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12642 #endif   /* defined(HAVE_PRI_CCSS) */
12643 #if defined(HAVE_PRI_CALL_WAITING)
12644                   pris[span].pri.max_call_waiting_calls =
12645                      conf->pri.pri.max_call_waiting_calls;
12646                   pris[span].pri.allow_call_waiting_calls =
12647                      conf->pri.pri.allow_call_waiting_calls;
12648 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12649                   pris[span].pri.transfer = conf->chan.transfer;
12650                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12651 #if defined(HAVE_PRI_L2_PERSISTENCE)
12652                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12653 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12654 #if defined(HAVE_PRI_AOC_EVENTS)
12655                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12656                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12657 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12658                   if (chan_sig == SIG_BRI_PTMP) {
12659                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12660                   } else {
12661                      /* Option does not apply to this line type. */
12662                      pris[span].pri.layer1_ignored = 0;
12663                   }
12664                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12665                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12666                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12667 #if defined(HAVE_PRI_MWI)
12668                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12669                      conf->pri.pri.mwi_mailboxes,
12670                      sizeof(pris[span].pri.mwi_mailboxes));
12671 #endif   /* defined(HAVE_PRI_MWI) */
12672                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12673                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12674                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12675                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12676                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12677                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12678                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12679                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12680 
12681                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12682                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12683                   }
12684 
12685 #if defined(HAVE_PRI_CALL_WAITING)
12686                   /* Channel initial config parameters. */
12687                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12688                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12689                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12690                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12691                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12692                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12693                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12694                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12695                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12696                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12697 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12698                } else {
12699                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12700                   destroy_dahdi_pvt(tmp);
12701                   return NULL;
12702                }
12703             }
12704          }
12705 #endif
12706       } else {
12707          /* already exists in interface list */
12708          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));
12709          chan_sig = tmp->sig;
12710          if (tmp->subs[SUB_REAL].dfd > -1) {
12711             memset(&p, 0, sizeof(p));
12712             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12713          }
12714       }
12715       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12716       switch (chan_sig) {
12717       case SIG_FXSKS:
12718       case SIG_FXSLS:
12719       case SIG_EM:
12720       case SIG_EM_E1:
12721       case SIG_EMWINK:
12722       case SIG_FEATD:
12723       case SIG_FEATDMF:
12724       case SIG_FEATDMF_TA:
12725       case SIG_FEATB:
12726       case SIG_E911:
12727       case SIG_SF:
12728       case SIG_SFWINK:
12729       case SIG_FGC_CAMA:
12730       case SIG_FGC_CAMAMF:
12731       case SIG_SF_FEATD:
12732       case SIG_SF_FEATDMF:
12733       case SIG_SF_FEATB:
12734          p.starttime = 250;
12735          break;
12736       }
12737 
12738       if (tmp->radio) {
12739          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12740          p.channo = channel;
12741          p.rxwinktime = 1;
12742          p.rxflashtime = 1;
12743          p.starttime = 1;
12744          p.debouncetime = 5;
12745       } else {
12746          p.channo = channel;
12747          /* Override timing settings based on config file */
12748          if (conf->timing.prewinktime >= 0)
12749             p.prewinktime = conf->timing.prewinktime;
12750          if (conf->timing.preflashtime >= 0)
12751             p.preflashtime = conf->timing.preflashtime;
12752          if (conf->timing.winktime >= 0)
12753             p.winktime = conf->timing.winktime;
12754          if (conf->timing.flashtime >= 0)
12755             p.flashtime = conf->timing.flashtime;
12756          if (conf->timing.starttime >= 0)
12757             p.starttime = conf->timing.starttime;
12758          if (conf->timing.rxwinktime >= 0)
12759             p.rxwinktime = conf->timing.rxwinktime;
12760          if (conf->timing.rxflashtime >= 0)
12761             p.rxflashtime = conf->timing.rxflashtime;
12762          if (conf->timing.debouncetime >= 0)
12763             p.debouncetime = conf->timing.debouncetime;
12764       }
12765 
12766       /* don't set parms on a pseudo-channel */
12767       if (tmp->subs[SUB_REAL].dfd >= 0)
12768       {
12769          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12770          if (res < 0) {
12771             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12772             destroy_dahdi_pvt(tmp);
12773             return NULL;
12774          }
12775       }
12776 #if 1
12777       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12778          memset(&bi, 0, sizeof(bi));
12779          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12780          if (!res) {
12781             bi.txbufpolicy = conf->chan.buf_policy;
12782             bi.rxbufpolicy = conf->chan.buf_policy;
12783             bi.numbufs = conf->chan.buf_no;
12784             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12785             if (res < 0) {
12786                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12787             }
12788          } else {
12789             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12790          }
12791          tmp->buf_policy = conf->chan.buf_policy;
12792          tmp->buf_no = conf->chan.buf_no;
12793          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12794          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12795          tmp->faxbuf_no = conf->chan.faxbuf_no;
12796          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12797           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12798           * The reason the ioctl call above failed should to be determined before worrying about the
12799           * faxbuffer-related ioctl calls */
12800          tmp->bufsize = bi.bufsize;
12801       }
12802 #endif
12803       tmp->immediate = conf->chan.immediate;
12804       tmp->transfertobusy = conf->chan.transfertobusy;
12805       if (chan_sig & __DAHDI_SIG_FXS) {
12806          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12807          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12808          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12809       }
12810       tmp->ringt_base = ringt_base;
12811       tmp->firstradio = 0;
12812       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12813          tmp->permcallwaiting = conf->chan.callwaiting;
12814       else
12815          tmp->permcallwaiting = 0;
12816       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12817       tmp->destroy = 0;
12818       tmp->drings = conf->chan.drings;
12819 
12820       /* 10 is a nice default. */
12821       if (tmp->drings.ringnum[0].range == 0)
12822          tmp->drings.ringnum[0].range = 10;
12823       if (tmp->drings.ringnum[1].range == 0)
12824          tmp->drings.ringnum[1].range = 10;
12825       if (tmp->drings.ringnum[2].range == 0)
12826          tmp->drings.ringnum[2].range = 10;
12827 
12828       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12829       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12830       tmp->threewaycalling = conf->chan.threewaycalling;
12831       tmp->adsi = conf->chan.adsi;
12832       tmp->use_smdi = conf->chan.use_smdi;
12833       tmp->permhidecallerid = conf->chan.hidecallerid;
12834       tmp->hidecalleridname = conf->chan.hidecalleridname;
12835       tmp->callreturn = conf->chan.callreturn;
12836       tmp->echocancel = conf->chan.echocancel;
12837       tmp->echotraining = conf->chan.echotraining;
12838       tmp->pulse = conf->chan.pulse;
12839       if (tmp->echocancel.head.tap_length) {
12840          tmp->echocanbridged = conf->chan.echocanbridged;
12841       } else {
12842          if (conf->chan.echocanbridged)
12843             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12844          tmp->echocanbridged = 0;
12845       }
12846       tmp->busydetect = conf->chan.busydetect;
12847       tmp->busycount = conf->chan.busycount;
12848       tmp->busycompare = conf->chan.busycompare;
12849       tmp->busytonelength = conf->chan.busytonelength;
12850       tmp->busyquietlength = conf->chan.busyquietlength;
12851       tmp->busyfuzziness = conf->chan.busyfuzziness;
12852       tmp->silencethreshold = conf->chan.silencethreshold;
12853       tmp->callprogress = conf->chan.callprogress;
12854       tmp->waitfordialtone = conf->chan.waitfordialtone;
12855       tmp->cancallforward = conf->chan.cancallforward;
12856       tmp->dtmfrelax = conf->chan.dtmfrelax;
12857       tmp->callwaiting = tmp->permcallwaiting;
12858       tmp->hidecallerid = tmp->permhidecallerid;
12859       tmp->channel = channel;
12860       tmp->stripmsd = conf->chan.stripmsd;
12861       tmp->use_callerid = conf->chan.use_callerid;
12862       tmp->cid_signalling = conf->chan.cid_signalling;
12863       tmp->cid_start = conf->chan.cid_start;
12864       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12865       tmp->restrictcid = conf->chan.restrictcid;
12866       tmp->use_callingpres = conf->chan.use_callingpres;
12867       if (tmp->usedistinctiveringdetection) {
12868          if (!tmp->use_callerid) {
12869             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12870             tmp->use_callerid = 1;
12871          }
12872       }
12873 
12874       if (tmp->cid_signalling == CID_SIG_SMDI) {
12875          if (!tmp->use_smdi) {
12876             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12877             tmp->use_smdi = 1;
12878          }
12879       }
12880       if (tmp->use_smdi) {
12881          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12882          if (!(tmp->smdi_iface)) {
12883             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12884             tmp->use_smdi = 0;
12885          }
12886       }
12887 
12888       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12889       tmp->amaflags = conf->chan.amaflags;
12890       if (!here) {
12891          tmp->confno = -1;
12892          tmp->propconfno = -1;
12893       }
12894       tmp->canpark = conf->chan.canpark;
12895       tmp->transfer = conf->chan.transfer;
12896       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12897       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12898       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12899       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12900       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12901       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12902       tmp->cid_ton = 0;
12903       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12904          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12905          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12906       } else {
12907          tmp->cid_num[0] = '\0';
12908          tmp->cid_name[0] = '\0';
12909       }
12910 #if defined(HAVE_PRI)
12911       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12912          tmp->cid_tag[0] = '\0';
12913       } else
12914 #endif   /* defined(HAVE_PRI) */
12915       {
12916          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12917       }
12918       tmp->cid_subaddr[0] = '\0';
12919       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12920       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12921          char *mailbox, *context;
12922          mailbox = context = ast_strdupa(tmp->mailbox);
12923          strsep(&context, "@");
12924          if (ast_strlen_zero(context))
12925             context = "default";
12926          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12927             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12928             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12929             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12930             AST_EVENT_IE_END);
12931       }
12932 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12933       tmp->mwisend_setting = conf->chan.mwisend_setting;
12934       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12935       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12936 #endif
12937 
12938       tmp->group = conf->chan.group;
12939       tmp->callgroup = conf->chan.callgroup;
12940       tmp->pickupgroup= conf->chan.pickupgroup;
12941       if (conf->chan.vars) {
12942          struct ast_variable *v, *tmpvar;
12943                    for (v = conf->chan.vars ; v ; v = v->next) {
12944                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12945                                   tmpvar->next = tmp->vars;
12946                                    tmp->vars = tmpvar;
12947                            }
12948                   }
12949       }
12950       tmp->cid_rxgain = conf->chan.cid_rxgain;
12951       tmp->rxgain = conf->chan.rxgain;
12952       tmp->txgain = conf->chan.txgain;
12953       tmp->txdrc = conf->chan.txdrc;
12954       tmp->rxdrc = conf->chan.rxdrc;
12955       tmp->tonezone = conf->chan.tonezone;
12956       if (tmp->subs[SUB_REAL].dfd > -1) {
12957          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12958          if (tmp->dsp)
12959             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12960          update_conf(tmp);
12961          if (!here) {
12962             switch (chan_sig) {
12963             case SIG_PRI_LIB_HANDLE_CASES:
12964             case SIG_SS7:
12965             case SIG_MFCR2:
12966                break;
12967             default:
12968                /* Hang it up to be sure it's good */
12969                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12970                break;
12971             }
12972          }
12973          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12974          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12975             /* the dchannel is down so put the channel in alarm */
12976             switch (tmp->sig) {
12977 #ifdef HAVE_PRI
12978             case SIG_PRI_LIB_HANDLE_CASES:
12979                sig_pri_set_alarm(tmp->sig_pvt, 1);
12980                break;
12981 #endif
12982 #if defined(HAVE_SS7)
12983             case SIG_SS7:
12984                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12985                break;
12986 #endif   /* defined(HAVE_SS7) */
12987             default:
12988                /* The only sig submodule left should be sig_analog. */
12989                analog_p = tmp->sig_pvt;
12990                if (analog_p) {
12991                   analog_p->inalarm = 1;
12992                }
12993                tmp->inalarm = 1;
12994                break;
12995             }
12996             handle_alarms(tmp, res);
12997          }
12998       }
12999 
13000       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13001       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13002       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13003       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13004       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13005 
13006       if (!here) {
13007          tmp->locallyblocked = 0;
13008          tmp->remotelyblocked = 0;
13009          switch (tmp->sig) {
13010 #if defined(HAVE_PRI)
13011          case SIG_PRI_LIB_HANDLE_CASES:
13012             tmp->inservice = 1;/* Inservice until actually implemented. */
13013 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13014             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13015             if (chan_sig == SIG_PRI) {
13016                char db_chan_name[20];
13017                char db_answer[5];
13018 
13019                /*
13020                 * Initialize the active out-of-service status
13021                 * and delete any record if the feature is not enabled.
13022                 */
13023                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13024                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13025                   unsigned *why;
13026 
13027                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13028                   if (tmp->pri->enable_service_message_support) {
13029                      char state;
13030 
13031                      sscanf(db_answer, "%1c:%30u", &state, why);
13032 
13033                      /* Ensure that only the implemented bits could be set.*/
13034                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13035                   }
13036                   if (!*why) {
13037                      ast_db_del(db_chan_name, SRVST_DBKEY);
13038                   }
13039                }
13040             }
13041 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13042             break;
13043 #endif   /* defined(HAVE_PRI) */
13044 #if defined(HAVE_SS7)
13045          case SIG_SS7:
13046             tmp->inservice = 0;
13047             break;
13048 #endif   /* defined(HAVE_SS7) */
13049          default:
13050              /* We default to in service on protocols that don't have a reset */
13051             tmp->inservice = 1;
13052             break;
13053          }
13054       }
13055 
13056       switch (tmp->sig) {
13057 #if defined(HAVE_PRI)
13058       case SIG_PRI_LIB_HANDLE_CASES:
13059          if (pri_chan) {
13060             pri_chan->channel = tmp->channel;
13061             pri_chan->hidecallerid = tmp->hidecallerid;
13062             pri_chan->hidecalleridname = tmp->hidecalleridname;
13063             pri_chan->immediate = tmp->immediate;
13064             pri_chan->inalarm = tmp->inalarm;
13065             pri_chan->priexclusive = tmp->priexclusive;
13066             pri_chan->priindication_oob = tmp->priindication_oob;
13067             pri_chan->use_callerid = tmp->use_callerid;
13068             pri_chan->use_callingpres = tmp->use_callingpres;
13069             ast_copy_string(pri_chan->context, tmp->context,
13070                sizeof(pri_chan->context));
13071             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13072                sizeof(pri_chan->mohinterpret));
13073             pri_chan->stripmsd = tmp->stripmsd;
13074          }
13075          break;
13076 #endif   /* defined(HAVE_PRI) */
13077 #if defined(HAVE_SS7)
13078       case SIG_SS7:
13079          if (ss7_chan) {
13080             ss7_chan->inalarm = tmp->inalarm;
13081 
13082             ss7_chan->stripmsd = tmp->stripmsd;
13083             ss7_chan->hidecallerid = tmp->hidecallerid;
13084             ss7_chan->use_callerid = tmp->use_callerid;
13085             ss7_chan->use_callingpres = tmp->use_callingpres;
13086             ss7_chan->immediate = tmp->immediate;
13087             ss7_chan->locallyblocked = tmp->locallyblocked;
13088             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13089             ast_copy_string(ss7_chan->context, tmp->context,
13090                sizeof(ss7_chan->context));
13091             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13092                sizeof(ss7_chan->mohinterpret));
13093          }
13094          break;
13095 #endif   /* defined(HAVE_SS7) */
13096       default:
13097          /* The only sig submodule left should be sig_analog. */
13098          analog_p = tmp->sig_pvt;
13099          if (analog_p) {
13100             analog_p->channel = tmp->channel;
13101             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13102             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13103             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13104             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13105             analog_p->callreturn = conf->chan.callreturn;
13106             analog_p->cancallforward = conf->chan.cancallforward;
13107             analog_p->canpark = conf->chan.canpark;
13108             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13109             analog_p->immediate = conf->chan.immediate;
13110             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13111             analog_p->pulse = conf->chan.pulse;
13112             analog_p->threewaycalling = conf->chan.threewaycalling;
13113             analog_p->transfer = conf->chan.transfer;
13114             analog_p->transfertobusy = conf->chan.transfertobusy;
13115             analog_p->use_callerid = tmp->use_callerid;
13116             analog_p->use_smdi = tmp->use_smdi;
13117             analog_p->smdi_iface = tmp->smdi_iface;
13118             analog_p->outsigmod = ANALOG_SIG_NONE;
13119             analog_p->echotraining = conf->chan.echotraining;
13120             analog_p->cid_signalling = conf->chan.cid_signalling;
13121             analog_p->stripmsd = conf->chan.stripmsd;
13122             switch (conf->chan.cid_start) {
13123             case CID_START_POLARITY:
13124                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13125                break;
13126             case CID_START_POLARITY_IN:
13127                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13128                break;
13129             case CID_START_DTMF_NOALERT:
13130                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13131                break;
13132             default:
13133                analog_p->cid_start = ANALOG_CID_START_RING;
13134                break;
13135             }
13136             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13137             analog_p->ringt = conf->chan.ringt;
13138             analog_p->ringt_base = ringt_base;
13139             analog_p->chan_tech = &dahdi_tech;
13140             analog_p->onhooktime = time(NULL);
13141             if (chan_sig & __DAHDI_SIG_FXO) {
13142                memset(&p, 0, sizeof(p));
13143                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13144                if (!res) {
13145                   analog_p->fxsoffhookstate = p.rxisoffhook;
13146                }
13147 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13148                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13149 #endif
13150             }
13151             analog_p->msgstate = -1;
13152 
13153             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13154             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13155             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13156 
13157             analog_config_complete(analog_p);
13158          }
13159          break;
13160       }
13161 #if defined(HAVE_PRI)
13162       if (tmp->channel == CHAN_PSEUDO) {
13163          /*
13164           * Save off pseudo channel buffer policy values for dynamic creation of
13165           * no B channel interfaces.
13166           */
13167          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13168          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13169          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13170          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13171       }
13172 #endif   /* defined(HAVE_PRI) */
13173    }
13174    if (tmp && !here) {
13175       /* Add the new channel interface to the sorted channel interface list. */
13176       dahdi_iflist_insert(tmp);
13177    }
13178    return tmp;
13179 }

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

Definition at line 480 of file chan_dahdi.c.

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

00481 {
00482    /* This module does not handle MWI in an event-based manner.  However, it
00483     * subscribes to MWI for each mailbox that is configured so that the core
00484     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00485     * event cache instead of checking the mailbox directly. */
00486 }

static int mwi_send_init ( struct dahdi_pvt pvt  )  [static]

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

11228 {
11229    int x;
11230 
11231 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11232    /* Determine how this spill is to be sent */
11233    if (pvt->mwisend_rpas) {
11234       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11235       pvt->mwisendactive = 1;
11236    } else if (pvt->mwisend_fsk) {
11237       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11238       pvt->mwisendactive = 1;
11239    } else {
11240       pvt->mwisendactive = 0;
11241       return 0;
11242    }
11243 #else
11244    if (mwisend_rpas) {
11245       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11246    } else {
11247       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11248    }
11249    pvt->mwisendactive = 1;
11250 #endif
11251 
11252    if (pvt->cidspill) {
11253       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11254       ast_free(pvt->cidspill);
11255       pvt->cidspill = NULL;
11256       pvt->cidpos = 0;
11257       pvt->cidlen = 0;
11258    }
11259    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11260    if (!pvt->cidspill) {
11261       pvt->mwisendactive = 0;
11262       return -1;
11263    }
11264    x = DAHDI_FLUSH_BOTH;
11265    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11266    x = 3000;
11267    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11268 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11269    if (pvt->mwisend_fsk) {
11270 #endif
11271       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11272                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11273       pvt->cidpos = 0;
11274 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11275    }
11276 #endif
11277    return 0;
11278 }

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

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

11281 {
11282    struct timeval    now;
11283    int         res;
11284 
11285    /* sanity check to catch if this had been interrupted previously
11286    *  i.e. state says there is more to do but there is no spill allocated
11287    */
11288    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11289       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11290    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11291       /* Normal processing -- Perform mwi send action */
11292       switch ( pvt->mwisend_data.mwisend_current) {
11293       case MWI_SEND_SA:
11294          /* Send the Ring Pulse Signal Alert */
11295          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11296          if (res) {
11297             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11298             goto quit;
11299          }
11300          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11301          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11302          break;
11303       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11304          break;
11305       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11306 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11307          if (pvt->mwisend_fsk) {
11308 #endif
11309             gettimeofday(&now, NULL);
11310             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11311                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11312             }
11313 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11314          } else { /* support for mwisendtype=nofsk */
11315             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11316          }
11317 #endif
11318          break;
11319       case MWI_SEND_SPILL:
11320          /* We read some number of bytes.  Write an equal amount of data */
11321          if(0 < num_read) {
11322             if (num_read > pvt->cidlen - pvt->cidpos)
11323                num_read = pvt->cidlen - pvt->cidpos;
11324             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11325             if (res > 0) {
11326                pvt->cidpos += res;
11327                if (pvt->cidpos >= pvt->cidlen) {
11328                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11329                }
11330             } else {
11331                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11332                goto quit;
11333             }
11334          }
11335          break;
11336       case MWI_SEND_CLEANUP:
11337          /* For now, do nothing */
11338          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11339          break;
11340       default:
11341          /* Should not get here, punt*/
11342          goto quit;
11343       }
11344    }
11345 
11346    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11347       if (pvt->cidspill) {
11348          ast_free(pvt->cidspill);
11349          pvt->cidspill = NULL;
11350          pvt->cidpos = 0;
11351          pvt->cidlen = 0;
11352       }
11353       pvt->mwisendactive = 0;
11354    }
11355    return 0;
11356 quit:
11357    if (pvt->cidspill) {
11358       ast_free(pvt->cidspill);
11359       pvt->cidspill = NULL;
11360       pvt->cidpos = 0;
11361       pvt->cidlen = 0;
11362    }
11363    pvt->mwisendactive = 0;
11364    return -1;
11365 }

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

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

11368 {
11369    int handled = 0;
11370 
11371    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11372       switch (event) {
11373       case DAHDI_EVENT_RINGEROFF:
11374          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11375             handled = 1;
11376 
11377             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11378                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11379                ast_free(pvt->cidspill);
11380                pvt->cidspill = NULL;
11381                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11382                pvt->mwisendactive = 0;
11383             } else {
11384                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11385                gettimeofday(&pvt->mwisend_data.pause, NULL);
11386             }
11387          }
11388          break;
11389       /* Going off hook, I need to punt this spill */
11390       case DAHDI_EVENT_RINGOFFHOOK:
11391          if (pvt->cidspill) {
11392             ast_free(pvt->cidspill);
11393             pvt->cidspill = NULL;
11394             pvt->cidpos = 0;
11395             pvt->cidlen = 0;
11396          }
11397          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11398          pvt->mwisendactive = 0;
11399          break;
11400       case DAHDI_EVENT_RINGERON:
11401       case DAHDI_EVENT_HOOKCOMPLETE:
11402          break;
11403       default:
11404          break;
11405       }
11406    }
11407    return handled;
11408 }

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

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

11076 {
11077    struct mwi_thread_data *mtd = data;
11078    struct callerid_state *cs;
11079    pthread_t threadid;
11080    int samples = 0;
11081    char *name, *number;
11082    int flags;
11083    int i, res;
11084    unsigned int spill_done = 0;
11085    int spill_result = -1;
11086 
11087    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11088       goto quit_no_clean;
11089    }
11090 
11091    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11092 
11093    bump_gains(mtd->pvt);
11094 
11095    for (;;) {
11096       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11097       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11098          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11099          goto quit;
11100       }
11101 
11102       if (i & DAHDI_IOMUX_SIGEVENT) {
11103          struct ast_channel *chan;
11104 
11105          /* If we get an event, screen out events that we do not act on.
11106           * Otherwise, cancel and go to the simple switch to let it deal with it.
11107           */
11108          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11109 
11110          switch (res) {
11111          case DAHDI_EVENT_NEONMWI_ACTIVE:
11112          case DAHDI_EVENT_NEONMWI_INACTIVE:
11113          case DAHDI_EVENT_NONE:
11114          case DAHDI_EVENT_BITSCHANGED:
11115             break;
11116          case DAHDI_EVENT_NOALARM:
11117             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11118                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11119 
11120                analog_p->inalarm = 0;
11121             }
11122             mtd->pvt->inalarm = 0;
11123             handle_clear_alarms(mtd->pvt);
11124             break;
11125          case DAHDI_EVENT_ALARM:
11126             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11127                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11128 
11129                analog_p->inalarm = 1;
11130             }
11131             mtd->pvt->inalarm = 1;
11132             res = get_alarms(mtd->pvt);
11133             handle_alarms(mtd->pvt, res);
11134             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11135          default:
11136             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11137             callerid_free(cs);
11138 
11139             restore_gains(mtd->pvt);
11140             mtd->pvt->ringt = mtd->pvt->ringt_base;
11141 
11142             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11143                int result;
11144 
11145                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11146                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11147                } else {
11148                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11149                }
11150                if (result) {
11151                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11152                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11153                   if (res < 0)
11154                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11155                   ast_hangup(chan);
11156                }
11157             } else {
11158                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11159             }
11160             goto quit_no_clean;
11161          }
11162       } else if (i & DAHDI_IOMUX_READ) {
11163          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11164             if (errno != ELAST) {
11165                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11166                goto quit;
11167             }
11168             break;
11169          }
11170          samples += res;
11171          if (!spill_done) {
11172             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11173                /*
11174                 * The previous diagnostic message output likely
11175                 * explains why it failed.
11176                 */
11177                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11178                break;
11179             } else if (spill_result) {
11180                spill_done = 1;
11181             }
11182          } else {
11183             /* keep reading data until the energy level drops below the threshold
11184                so we don't get another 'trigger' on the remaining carrier signal
11185             */
11186             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11187                break;
11188          }
11189          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11190             break;
11191       }
11192    }
11193 
11194    if (spill_result == 1) {
11195       callerid_get(cs, &name, &number, &flags);
11196       if (flags & CID_MSGWAITING) {
11197          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11198          notify_message(mtd->pvt->mailbox, 1);
11199       } else if (flags & CID_NOMSGWAITING) {
11200          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11201          notify_message(mtd->pvt->mailbox, 0);
11202       } else {
11203          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11204       }
11205    }
11206 
11207 
11208 quit:
11209    callerid_free(cs);
11210 
11211    restore_gains(mtd->pvt);
11212 
11213 quit_no_clean:
11214    mtd->pvt->mwimonitoractive = 0;
11215    ast_free(mtd);
11216 
11217    return NULL;
11218 }

static void my_all_subchannels_hungup ( void *  pvt  )  [static]

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

02408 {
02409    struct dahdi_pvt *p = pvt;
02410    int res, law;
02411 
02412    p->faxhandled = 0;
02413    p->didtdd = 0;
02414 
02415    if (p->dsp) {
02416       ast_dsp_free(p->dsp);
02417       p->dsp = NULL;
02418    }
02419 
02420    p->law = p->law_default;
02421    law = p->law_default;
02422    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02423    if (res < 0)
02424       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02425 
02426    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02427 
02428 #if 1
02429    {
02430    int i;
02431    p->owner = NULL;
02432    /* Cleanup owners here */
02433    for (i = 0; i < 3; i++) {
02434       p->subs[i].owner = NULL;
02435    }
02436    }
02437 #endif
02438 
02439    reset_conf(p);
02440    if (num_restart_pending == 0) {
02441       restart_monitor();
02442    }
02443 }

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

Definition at line 2718 of file chan_dahdi.c.

References alloc_sub(), and analogsub_to_dahdisub().

02719 {
02720    struct dahdi_pvt *p = pvt;
02721 
02722    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02723 }

static void my_ami_channel_event ( void *  pvt,
struct ast_channel chan 
) [static]

Definition at line 2175 of file chan_dahdi.c.

References dahdi_ami_channel_event().

02176 {
02177    struct dahdi_pvt *p = pvt;
02178 
02179    dahdi_ami_channel_event(p, chan);
02180 }

static void my_answer_polarityswitch ( void *  pvt  )  [static]

Definition at line 2956 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

02957 {
02958    struct dahdi_pvt *p = pvt;
02959 
02960    if (!p->answeronpolarityswitch) {
02961       return;
02962    }
02963 
02964    my_set_polarity(pvt, 1);
02965 }

static int my_callwait ( void *  pvt  )  [static]

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

01905 {
01906    struct dahdi_pvt *p = pvt;
01907    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01908    if (p->cidspill) {
01909       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01910       ast_free(p->cidspill);
01911    }
01912 
01913    /*
01914     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01915     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01916     */
01917    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01918       return -1;
01919    save_conference(p);
01920    /* Silence */
01921    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01922    if (!p->callwaitrings && p->callwaitingcallerid) {
01923       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01924       p->callwaitcas = 1;
01925       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01926    } else {
01927       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01928       p->callwaitcas = 0;
01929       p->cidlen = 2400 + READ_SIZE * 4;
01930    }
01931    p->cidpos = 0;
01932    send_callerid(p);
01933 
01934    return 0;
01935 }

static void my_cancel_cidspill ( void *  pvt  )  [static]

Definition at line 2357 of file chan_dahdi.c.

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

02358 {
02359    struct dahdi_pvt *p = pvt;
02360 
02361    ast_free(p->cidspill);
02362    p->cidspill = NULL;
02363    restore_conference(p);
02364 }

static int my_check_confirmanswer ( void *  pvt  )  [static]

Definition at line 2340 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02341 {
02342    struct dahdi_pvt *p = pvt;
02343    if (p->confirmanswer) {
02344       return 1;
02345    }
02346 
02347    return 0;
02348 }

static int my_check_for_conference ( void *  pvt  )  [static]

Definition at line 2517 of file chan_dahdi.c.

References check_for_conference().

02518 {
02519    struct dahdi_pvt *p = pvt;
02520    return check_for_conference(p);
02521 }

static int my_check_waitingfordt ( void *  pvt  )  [static]

Definition at line 2323 of file chan_dahdi.c.

References dahdi_pvt::waitingfordt.

02324 {
02325    struct dahdi_pvt *p = pvt;
02326 
02327    if (p->waitingfordt.tv_usec) {
02328       return 1;
02329    }
02330 
02331    return 0;
02332 }

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

Definition at line 2467 of file chan_dahdi.c.

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

02468 {
02469    struct dahdi_pvt *p = pvt;
02470    int needconf = needconference;
02471    int x;
02472    int useslavenative;
02473    struct dahdi_pvt *slave = NULL;
02474 
02475    useslavenative = isslavenative(p, &slave);
02476 
02477    /* If we have a slave, add him to our conference now. or DAX
02478       if this is slave native */
02479    for (x = 0; x < MAX_SLAVES; x++) {
02480       if (p->slaves[x]) {
02481          if (useslavenative)
02482             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02483          else {
02484             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02485             needconf++;
02486          }
02487       }
02488    }
02489    /* If we're supposed to be in there, do so now */
02490    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02491       if (useslavenative)
02492          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02493       else {
02494          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02495          needconf++;
02496       }
02497    }
02498    /* If we have a master, add ourselves to his conference */
02499    if (p->master) {
02500       if (isslavenative(p->master, NULL)) {
02501          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02502       } else {
02503          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02504       }
02505    }
02506    if (!needconf) {
02507       /* Nobody is left (or should be left) in our conference.
02508          Kill it. */
02509       p->confno = -1;
02510    }
02511 
02512    return 0;
02513 }

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

Definition at line 2457 of file chan_dahdi.c.

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

02458 {
02459    struct dahdi_pvt *p = pvt;
02460    int x = analogsub_to_dahdisub(sub);
02461 
02462    return conf_add(p, &p->subs[x], x, 0);
02463 }

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

Definition at line 2447 of file chan_dahdi.c.

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

02448 {
02449    struct dahdi_pvt *p = pvt;
02450    int x = analogsub_to_dahdisub(sub);
02451 
02452    return conf_del(p, &p->subs[x], x);
02453 }

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

Definition at line 2366 of file chan_dahdi.c.

References dahdi_confmute().

02367 {
02368    struct dahdi_pvt *p = pvt;
02369    return dahdi_confmute(p, mute);
02370 }

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

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

09351 {
09352    int sent=0;
09353    int size;
09354    int res;
09355    int fd;
09356    fd = p->subs[idx].dfd;
09357    while (len) {
09358       size = len;
09359       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09360          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09361       res = write(fd, buf, size);
09362       if (res != size) {
09363          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09364          return sent;
09365       }
09366       len -= size;
09367       buf += size;
09368    }
09369    return sent;
09370 }

static void my_deadlock_avoidance_private ( void *  pvt  )  [static]

Definition at line 2122 of file chan_dahdi.c.

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

02123 {
02124    struct dahdi_pvt *p = pvt;
02125 
02126    DEADLOCK_AVOIDANCE(&p->lock);
02127 }

static void my_decrease_ss_count ( void   )  [static]

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

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

02991 {
02992    int index = analogsub_to_dahdisub(sub);
02993    int res;
02994    struct dahdi_pvt *p = pvt;
02995    struct dahdi_dialoperation ddop;
02996 
02997    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02998       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02999       return -1;
03000    }
03001 
03002    if (sub != ANALOG_SUB_REAL) {
03003       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03004          dop->dialstr, p->channel, sub);
03005       return -1;
03006    }
03007 
03008    ddop.op = DAHDI_DIAL_OP_REPLACE;
03009    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03010 
03011    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03012 
03013    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03014    if (res == -1) {
03015       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03016    }
03017 
03018    return res;
03019 }

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

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

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

static int my_dsp_reset_and_flush_digits ( void *  pvt  )  [static]

Definition at line 1972 of file chan_dahdi.c.

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

01973 {
01974    struct dahdi_pvt *p = pvt;
01975    if (p->dsp)
01976       ast_dsp_digitreset(p->dsp);
01977 
01978    return 0;
01979 }

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

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

01982 {
01983    struct dahdi_pvt *p = pvt;
01984 
01985    if (p->channel == CHAN_PSEUDO)
01986       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01987 
01988    if (mode == ANALOG_DIGITMODE_DTMF) {
01989       /* If we do hardware dtmf, no need for a DSP */
01990       if (p->hardwaredtmf) {
01991          if (p->dsp) {
01992             ast_dsp_free(p->dsp);
01993             p->dsp = NULL;
01994          }
01995          return 0;
01996       }
01997 
01998       if (!p->dsp) {
01999          p->dsp = ast_dsp_new();
02000          if (!p->dsp) {
02001             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02002             return -1;
02003          }
02004       }
02005 
02006       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02007    } else if (mode == ANALOG_DIGITMODE_MF) {
02008       if (!p->dsp) {
02009          p->dsp = ast_dsp_new();
02010          if (!p->dsp) {
02011             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02012             return -1;
02013          }
02014       }
02015       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02016    }
02017    return 0;
02018 }

static int my_flash ( void *  pvt  )  [static]

Definition at line 2915 of file chan_dahdi.c.

References SUB_REAL, and dahdi_pvt::subs.

02916 {
02917    struct dahdi_pvt *p = pvt;
02918    int func = DAHDI_FLASH;
02919    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02920 }

static void my_get_and_handle_alarms ( void *  pvt  )  [static]

Definition at line 2208 of file chan_dahdi.c.

References get_alarms(), and handle_alarms().

02209 {
02210    int res;
02211    struct dahdi_pvt *p = pvt;
02212 
02213    res = get_alarms(p);
02214    handle_alarms(p, res);
02215 }

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

Definition at line 1691 of file chan_dahdi.c.

References ANALOG_EVENT_NONE, ANALOG_MAX_CID, ast_copy_string(), ast_debug, 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_WARNING, name, analog_pvt::ringt, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

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

static int my_get_event ( void *  pvt  )  [static]

Definition at line 2848 of file chan_dahdi.c.

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

02849 {
02850    struct dahdi_pvt *p = pvt;
02851    int res;
02852 
02853    if (p->fake_event) {
02854       res = p->fake_event;
02855       p->fake_event = 0;
02856    } else
02857       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02858 
02859    return dahdievent_to_analogevent(res);
02860 }

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

Definition at line 2385 of file chan_dahdi.c.

References dahdi_pvt::dialstring.

02386 {
02387    struct dahdi_pvt *p = pvt;
02388 
02389    return p->dialstring;
02390 }

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

Definition at line 2217 of file chan_dahdi.c.

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

02218 {
02219    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02220    if (p)
02221       return p->sig_pvt;
02222    else
02223       return NULL;
02224 }

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

Definition at line 2226 of file chan_dahdi.c.

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

02227 {
02228    struct dahdi_pvt *p = pvt;
02229    int dahdi_sub = analogsub_to_dahdisub(sub);
02230    return p->subs[dahdi_sub].dfd;
02231 }

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

Definition at line 9831 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

09832 {
09833    char c;
09834 
09835    *str = 0; /* start with empty output buffer */
09836    for (;;)
09837    {
09838       /* Wait for the first digit (up to specified ms). */
09839       c = ast_waitfordigit(chan, ms);
09840       /* if timeout, hangup or error, return as such */
09841       if (c < 1)
09842          return c;
09843       *str++ = c;
09844       *str = 0;
09845       if (strchr(term, c))
09846          return 1;
09847    }
09848 }

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

Definition at line 3113 of file chan_dahdi.c.

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

03114 {
03115    int x;
03116 
03117    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03118    switch (x) {
03119    case DAHDI_EVENT_NONE:
03120       break;
03121    case DAHDI_EVENT_ALARM:
03122    case DAHDI_EVENT_NOALARM:
03123       if (sig_pri_is_alarm_ignored(pri)) {
03124          break;
03125       }
03126       /* Fall through */
03127    default:
03128       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03129          event2str(x), x, pri->span);
03130       break;
03131    }
03132    /* Keep track of alarm state */
03133    switch (x) {
03134    case DAHDI_EVENT_ALARM:
03135       pri_event_alarm(pri, index, 0);
03136       break;
03137    case DAHDI_EVENT_NOALARM:
03138       pri_event_noalarm(pri, index, 0);
03139       break;
03140    default:
03141       break;
03142    }
03143 }

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

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

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

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

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

03633 {
03634    struct dahdi_pvt *p = pvt;
03635 
03636    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03637       return;
03638 
03639    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03640       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03641       notify_message(p->mailbox, 1);
03642    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03643       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03644       notify_message(p->mailbox, 0);
03645    }
03646    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03647    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03648    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03649       ast_hangup(chan);
03650       return;
03651    }
03652 }

static void my_hangup_polarityswitch ( void *  pvt  )  [static]

Definition at line 2967 of file chan_dahdi.c.

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

02968 {
02969    struct dahdi_pvt *p = pvt;
02970 
02971    if (!p->hanguponpolarityswitch) {
02972       return;
02973    }
02974 
02975    if (p->answeronpolarityswitch) {
02976       my_set_polarity(pvt, 0);
02977    } else {
02978       my_set_polarity(pvt, 1);
02979    }
02980 }

static int my_has_voicemail ( void *  pvt  )  [static]

Definition at line 2727 of file chan_dahdi.c.

References has_voicemail().

02728 {
02729    struct dahdi_pvt *p = pvt;
02730 
02731    return has_voicemail(p);
02732 }

static int my_have_progressdetect ( void *  pvt  )  [static]

Definition at line 3654 of file chan_dahdi.c.

References dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, CANPROGRESSDETECT, dahdi_pvt::dsp, and dahdi_pvt::outgoing.

03655 {
03656    struct dahdi_pvt *p = pvt;
03657 
03658    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03659       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03660       return 1;
03661    } else {
03662       /* Don't have progress detection. */
03663       return 0;
03664    }
03665 }

static void my_increase_ss_count ( void   )  [static]

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

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

03033 {
03034    struct dahdi_pvt *p = pvt;
03035    int index;
03036    int x;
03037 
03038    index = analogsub_to_dahdisub(sub);
03039 
03040    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03041       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03042       return -1;
03043    }
03044 
03045    return x;
03046 }

static int my_is_off_hook ( void *  pvt  )  [static]

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

02863 {
02864    struct dahdi_pvt *p = pvt;
02865    int res;
02866    struct dahdi_params par;
02867 
02868    memset(&par, 0, sizeof(par));
02869 
02870    if (p->subs[SUB_REAL].dfd > -1)
02871       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02872    else {
02873       /* Assume not off hook on CVRS */
02874       res = 0;
02875       par.rxisoffhook = 0;
02876    }
02877    if (res) {
02878       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02879    }
02880 
02881    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02882       /* When "onhook" that means no battery on the line, and thus
02883       it is out of service..., if it's on a TDM card... If it's a channel
02884       bank, there is no telling... */
02885       return (par.rxbits > -1) || par.rxisoffhook;
02886    }
02887 
02888    return par.rxisoffhook;
02889 }

static void my_lock_private ( void *  pvt  )  [static]

Definition at line 2110 of file chan_dahdi.c.

References ast_mutex_lock, and dahdi_pvt::lock.

02111 {
02112    struct dahdi_pvt *p = pvt;
02113    ast_mutex_lock(&p->lock);
02114 }

static void my_module_ref ( void   )  [static]

Definition at line 3365 of file chan_dahdi.c.

References ast_module_ref().

03366 {
03367    ast_module_ref(ast_module_info->self);
03368 }

static void my_module_unref ( void   )  [static]

Definition at line 3379 of file chan_dahdi.c.

References ast_module_unref().

03380 {
03381    ast_module_unref(ast_module_info->self);
03382 }

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

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

02558 {
02559    struct dahdi_pvt *p = pvt;
02560    int dsub = analogsub_to_dahdisub(sub);
02561 
02562    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02563 }

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

02578 {
02579    struct dahdi_pvt *p = pvt;
02580    int audio;
02581    int newlaw = -1;
02582 
02583    switch (p->sig) {
02584    case SIG_PRI_LIB_HANDLE_CASES:
02585       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02586          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02587          break;
02588       }
02589       /* Fall through */
02590    default:
02591       /* Set to audio mode at this point */
02592       audio = 1;
02593       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02594          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02595             p->channel, audio, strerror(errno));
02596       }
02597       break;
02598    }
02599 
02600    if (law != SIG_PRI_DEFLAW) {
02601       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02602    }
02603 
02604    ast_copy_string(p->exten, exten, sizeof(p->exten));
02605 
02606    switch (law) {
02607       case SIG_PRI_DEFLAW:
02608          newlaw = 0;
02609          break;
02610       case SIG_PRI_ALAW:
02611          newlaw = DAHDI_LAW_ALAW;
02612          break;
02613       case SIG_PRI_ULAW:
02614          newlaw = DAHDI_LAW_MULAW;
02615          break;
02616    }
02617    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02618 }

static int my_off_hook ( void *  pvt  )  [static]

Definition at line 2924 of file chan_dahdi.c.

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

02925 {
02926    struct dahdi_pvt *p = pvt;
02927    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02928 }

static int my_on_hook ( void *  pvt  )  [static]

Definition at line 3048 of file chan_dahdi.c.

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

03049 {
03050    struct dahdi_pvt *p = pvt;
03051    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03052 }

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

Definition at line 2734 of file chan_dahdi.c.

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

02735 {
02736    struct dahdi_pvt *p = pvt;
02737    int index;
02738 
02739    index = analogsub_to_dahdisub(sub);
02740 
02741    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02742 }

static void my_pri_dial_digits ( void *  p,
const char *  dial_string 
) [static]

Definition at line 2687 of file chan_dahdi.c.

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

02688 {
02689    struct dahdi_dialoperation zo = {
02690       .op = DAHDI_DIAL_OP_APPEND,
02691    };
02692    struct dahdi_pvt *pvt = p;
02693    int res;
02694 
02695    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02696    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02697    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02698    if (res) {
02699       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02700          pvt->channel, dial_string, strerror(errno));
02701    } else {
02702       pvt->dialing = 1;
02703    }
02704 }

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

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

03056 {
03057    struct dahdi_pvt *old_chan = chan_old;
03058    struct dahdi_pvt *new_chan = chan_new;
03059 
03060    new_chan->owner = old_chan->owner;
03061    old_chan->owner = NULL;
03062    if (new_chan->owner) {
03063       new_chan->owner->tech_pvt = new_chan;
03064       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03065       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03066       old_chan->subs[SUB_REAL].owner = NULL;
03067    }
03068    /* Copy any DSP that may be present */
03069    new_chan->dsp = old_chan->dsp;
03070    new_chan->dsp_features = old_chan->dsp_features;
03071    old_chan->dsp = NULL;
03072    old_chan->dsp_features = 0;
03073 
03074    /* Transfer flags from the old channel. */
03075    new_chan->dialing = old_chan->dialing;
03076    new_chan->digital = old_chan->digital;
03077    new_chan->outgoing = old_chan->outgoing;
03078    old_chan->dialing = 0;
03079    old_chan->digital = 0;
03080    old_chan->outgoing = 0;
03081 
03082    /* More stuff to transfer to the new channel. */
03083    new_chan->law = old_chan->law;
03084    strcpy(new_chan->dialstring, old_chan->dialstring);
03085 }

static void my_pri_init_config ( void *  priv,
struct sig_pri_span pri 
) [static]

Definition at line 13281 of file chan_dahdi.c.

References ast_copy_string(), sig_pri_span::ch_cfg, sig_pri_span::context, dahdi_pvt::context, sig_pri_span::hidecallerid, dahdi_pvt::hidecallerid, sig_pri_span::hidecalleridname, dahdi_pvt::hidecalleridname, sig_pri_span::immediate, dahdi_pvt::immediate, sig_pri_span::mohinterpret, dahdi_pvt::mohinterpret, dahdi_pvt::pri, sig_pri_span::priexclusive, dahdi_pvt::priexclusive, sig_pri_span::priindication_oob, dahdi_pvt::priindication_oob, sig_pri_span::stripmsd, dahdi_pvt::stripmsd, sig_pri_span::use_callerid, dahdi_pvt::use_callerid, sig_pri_span::use_callingpres, and dahdi_pvt::use_callingpres.

13282 {
13283    struct dahdi_pvt *pvt = priv;
13284 
13285    pvt->stripmsd = pri->ch_cfg.stripmsd;
13286    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13287    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13288    pvt->immediate = pri->ch_cfg.immediate;
13289    pvt->priexclusive = pri->ch_cfg.priexclusive;
13290    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13291    pvt->use_callerid = pri->ch_cfg.use_callerid;
13292    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13293    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13294    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13295 }

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

Definition at line 3254 of file chan_dahdi.c.

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

03255 {
03256    char *dial;
03257    struct dahdi_pvt *pvt;
03258    AST_DECLARE_APP_ARGS(args,
03259       AST_APP_ARG(tech);   /* channel technology token */
03260       AST_APP_ARG(group);  /* channel/group token */
03261       //AST_APP_ARG(ext);  /* extension token */
03262       //AST_APP_ARG(opts); /* options token */
03263       //AST_APP_ARG(other);   /* Any remining unused arguments */
03264    );
03265 
03266    pvt = priv;
03267    dial = ast_strdupa(pvt->dialstring);
03268    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03269    if (!args.tech) {
03270       ast_copy_string(buf, pvt->dialstring, buf_size);
03271       return;
03272    }
03273    if (!args.group) {
03274       /* Append the ISDN span channel restriction to the dialstring. */
03275       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03276       return;
03277    }
03278    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03279       /* The ISDN span channel restriction is not needed or already
03280        * in the dialstring. */
03281       ast_copy_string(buf, pvt->dialstring, buf_size);
03282       return;
03283    }
03284    /* Insert the ISDN span channel restriction into the dialstring. */
03285    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03286 }

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

Definition at line 3147 of file chan_dahdi.c.

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

03148 {
03149    struct dahdi_pvt *p = pvt;
03150 
03151    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03152 }

static void my_pri_ss7_open_media ( void *  p  )  [static]

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

02634 {
02635    struct dahdi_pvt *pvt = p;
02636    int res;
02637    int dfd;
02638    int set_val;
02639 
02640    dfd = pvt->subs[SUB_REAL].dfd;
02641 
02642    /* Open the media path. */
02643    set_val = 1;
02644    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02645    if (res < 0) {
02646       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02647          pvt->channel, strerror(errno));
02648    }
02649 
02650    /* Set correct companding law for this call. */
02651    res = dahdi_setlaw(dfd, pvt->law);
02652    if (res < 0) {
02653       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02654    }
02655 
02656    /* Set correct gain for this call. */
02657    if (pvt->digital) {
02658       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02659    } else {
02660       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02661          pvt->law);
02662    }
02663    if (res < 0) {
02664       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02665    }
02666 
02667    if (pvt->dsp_features && pvt->dsp) {
02668       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02669       pvt->dsp_features = 0;
02670    }
02671 }

static int my_ring ( void *  pvt  )  [static]

Definition at line 2908 of file chan_dahdi.c.

References dahdi_ring_phone().

02909 {
02910    struct dahdi_pvt *p = pvt;
02911 
02912    return dahdi_ring_phone(p);
02913 }

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

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

01938 {
01939    struct dahdi_pvt *p = pvt;
01940 
01941    ast_debug(2, "Starting cid spill\n");
01942 
01943    if (p->cidspill) {
01944       ast_log(LOG_WARNING, "cidspill already exists??\n");
01945       ast_free(p->cidspill);
01946    }
01947 
01948    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01949       if (cwcid == 0) {
01950          p->cidlen = ast_callerid_generate(p->cidspill,
01951             caller->id.name.str,
01952             caller->id.number.str,
01953             AST_LAW(p));
01954       } else {
01955          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01956             caller->id.name.str, caller->id.number.str);
01957          p->callwaitcas = 0;
01958          p->cidcwexpire = 0;
01959          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01960             caller->id.name.str,
01961             caller->id.number.str,
01962             AST_LAW(p));
01963          p->cidlen += READ_SIZE * 4;
01964       }
01965       p->cidpos = 0;
01966       p->cid_suppress_expire = 0;
01967       send_callerid(p);
01968    }
01969    return 0;
01970 }

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

Definition at line 2249 of file chan_dahdi.c.

References dahdi_pvt::inalarm.

02250 {
02251    struct dahdi_pvt *p = pvt;
02252 
02253    p->inalarm = in_alarm;
02254 }

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

Definition at line 2233 of file chan_dahdi.c.

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

02234 {
02235    struct dahdi_pvt *p = pvt;
02236 
02237    /* Choose proper cadence */
02238    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02239       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02240          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02241       *cid_rings = cidrings[p->distinctivering - 1];
02242    } else {
02243       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02244          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02245       *cid_rings = p->sendcalleridafter;
02246    }
02247 }

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

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

03167 {
03168    struct dahdi_pvt *p = pvt;
03169 
03170    ast_copy_string(p->cid_num,
03171       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03172       sizeof(p->cid_num));
03173    ast_copy_string(p->cid_name,
03174       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03175       sizeof(p->cid_name));
03176    ast_copy_string(p->cid_subaddr,
03177       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03178       sizeof(p->cid_subaddr));
03179    p->cid_ton = caller->id.number.plan;
03180    p->callingpres = ast_party_id_presentation(&caller->id);
03181    if (caller->id.tag) {
03182       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03183    }
03184    ast_copy_string(p->cid_ani,
03185       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03186       sizeof(p->cid_ani));
03187    p->cid_ani2 = caller->ani2;
03188 }

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

Definition at line 2350 of file chan_dahdi.c.

References dahdi_pvt::callwaiting.

02351 {
02352    struct dahdi_pvt *p = pvt;
02353 
02354    p->callwaiting = callwaiting_enable;
02355 }

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

Definition at line 2334 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02335 {
02336    struct dahdi_pvt *p = pvt;
02337    p->confirmanswer = flag;
02338 }

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

Definition at line 2256 of file chan_dahdi.c.

References dahdi_pvt::dialing.

02257 {
02258    struct dahdi_pvt *p = pvt;
02259 
02260    p->dialing = is_dialing;
02261 }

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

Definition at line 2271 of file chan_dahdi.c.

References dahdi_pvt::digital.

02272 {
02273    struct dahdi_pvt *p = pvt;
02274 
02275    p->digital = is_digital;
02276 }

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

Definition at line 3202 of file chan_dahdi.c.

References ast_copy_string(), and dahdi_pvt::dnid.

03203 {
03204    struct dahdi_pvt *p = pvt;
03205 
03206    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03207 }

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

Definition at line 2894 of file chan_dahdi.c.

References dahdi_disable_ec(), and dahdi_enable_ec().

02895 {
02896    struct dahdi_pvt *p = pvt;
02897 
02898    if (enable)
02899       dahdi_enable_ec(p);
02900    else
02901       dahdi_disable_ec(p);
02902 
02903    return 0;
02904 }

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

Definition at line 2198 of file chan_dahdi.c.

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

02199 {
02200    struct dahdi_pvt *p = pvt;
02201    int idx = analogsub_to_dahdisub(sub);
02202 
02203    p->subs[idx].inthreeway = inthreeway;
02204 }

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

Definition at line 2186 of file chan_dahdi.c.

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

02187 {
02188    struct dahdi_pvt *p = pvt;
02189    int oldval;
02190    int idx = analogsub_to_dahdisub(sub);
02191    
02192    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02193    oldval = p->subs[idx].linear;
02194    p->subs[idx].linear = linear_mode ? 1 : 0;
02195    return oldval;
02196 }

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

Definition at line 2930 of file chan_dahdi.c.

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

02931 {
02932    struct dahdi_pvt *p = pvt;
02933    p->subs[SUB_REAL].needringing = value;
02934 }

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

Definition at line 2378 of file chan_dahdi.c.

References dahdi_pvt::owner.

02379 {
02380    struct dahdi_pvt *p = pvt;
02381 
02382    p->owner = new_owner;
02383 }

static void my_set_outgoing ( void *  pvt,
int  is_outgoing 
) [static]

Definition at line 2263 of file chan_dahdi.c.

References dahdi_pvt::outgoing.

02264 {
02265    struct dahdi_pvt *p = pvt;
02266 
02267    p->outgoing = is_outgoing;
02268 }

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

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

02937 {
02938    struct dahdi_pvt *p = pvt;
02939 
02940    if (p->channel == CHAN_PSEUDO) {
02941       return;
02942    }
02943    p->polarity = value;
02944    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02945 }

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

Definition at line 2372 of file chan_dahdi.c.

References dahdi_pvt::pulsedial.

02373 {
02374    struct dahdi_pvt *p = pvt;
02375    p->pulsedial = flag;
02376 }

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

Definition at line 3221 of file chan_dahdi.c.

References ast_copy_string(), and dahdi_pvt::rdnis.

03222 {
03223    struct dahdi_pvt *p = pvt;
03224 
03225    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03226 }

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

Definition at line 2306 of file chan_dahdi.c.

References dahdi_pvt::ringt.

02307 {
02308    struct dahdi_pvt *p = pvt;
02309    p->ringt = ringt;
02310 }

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

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

02313 {
02314    struct dahdi_pvt *p = pvt;
02315 
02316    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02317       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02318       gettimeofday(&p->waitingfordt, NULL);
02319       ast_setstate(ast, AST_STATE_OFFHOOK);
02320    }
02321 }

static int my_start ( void *  pvt  )  [static]

Definition at line 2982 of file chan_dahdi.c.

References SUB_REAL, and dahdi_pvt::subs.

02983 {
02984    struct dahdi_pvt *p = pvt;
02985    int x = DAHDI_START;
02986 
02987    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02988 }

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

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

01667 {
01668    struct dahdi_pvt *p = pvt;
01669    int index = SUB_REAL;
01670    p->cs = callerid_new(cid_signalling);
01671    if (!p->cs) {
01672       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01673       return -1;
01674    }
01675    bump_gains(p);
01676    dahdi_setlinear(p->subs[index].dfd, 0);
01677 
01678    return 0;
01679 }

static void my_start_polarityswitch ( void *  pvt  )  [static]

Definition at line 2947 of file chan_dahdi.c.

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

02948 {
02949    struct dahdi_pvt *p = pvt;
02950 
02951    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02952       my_set_polarity(pvt, 0);
02953    }
02954 }

static int my_stop_callwait ( void *  pvt  )  [static]

Definition at line 1890 of file chan_dahdi.c.

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

01891 {
01892    struct dahdi_pvt *p = pvt;
01893    p->callwaitingrepeat = 0;
01894    p->cidcwexpire = 0;
01895    p->cid_suppress_expire = 0;
01896 
01897    return 0;
01898 }

static int my_stop_cid_detect ( void *  pvt  )  [static]

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

01682 {
01683    struct dahdi_pvt *p = pvt;
01684    int index = SUB_REAL;
01685    if (p->cs)
01686       callerid_free(p->cs);
01687    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01688    return 0;
01689 }

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

02524 {
02525    struct dahdi_pvt *p = pvt;
02526    int da, db;
02527    int tchan;
02528    int tinthreeway;
02529 
02530    da = analogsub_to_dahdisub(a);
02531    db = analogsub_to_dahdisub(b);
02532 
02533    tchan = p->subs[da].chan;
02534    p->subs[da].chan = p->subs[db].chan;
02535    p->subs[db].chan = tchan;
02536 
02537    tinthreeway = p->subs[da].inthreeway;
02538    p->subs[da].inthreeway = p->subs[db].inthreeway;
02539    p->subs[db].inthreeway = tinthreeway;
02540 
02541    p->subs[da].owner = ast_a;
02542    p->subs[db].owner = ast_b;
02543 
02544    if (ast_a)
02545       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02546    if (ast_b)
02547       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02548 
02549    wakeup_sub(p, a);
02550    wakeup_sub(p, b);
02551 
02552    return;
02553 }

static int my_train_echocanceller ( void *  pvt  )  [static]

Definition at line 3023 of file chan_dahdi.c.

References dahdi_train_ec().

03024 {
03025    struct dahdi_pvt *p = pvt;
03026 
03027    dahdi_train_ec(p);
03028 
03029    return 0;
03030 }

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

Definition at line 2709 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and unalloc_sub().

02710 {
02711    struct dahdi_pvt *p = pvt;
02712 
02713    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02714 }

static void my_unlock_private ( void *  pvt  )  [static]

Definition at line 2116 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pvt::lock.

02117 {
02118    struct dahdi_pvt *p = pvt;
02119    ast_mutex_unlock(&p->lock);
02120 }

static int my_wait_event ( void *  pvt  )  [static]

Definition at line 2841 of file chan_dahdi.c.

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

02842 {
02843    struct dahdi_pvt *p = pvt;
02844 
02845    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02846 }

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

Definition at line 2022 of file chan_dahdi.c.

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

02023 {
02024    struct dahdi_pvt *p = pvt;
02025    int index = analogsub_to_dahdisub(sub);
02026    if (index != SUB_REAL) {
02027       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02028    }
02029    return dahdi_wink(p, index);
02030 }

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

03604 {
03605    char s[sizeof(mwimonitornotify) + 80];
03606    struct ast_event *event;
03607    char *mailbox, *context;
03608 
03609    /* Strip off @default */
03610    context = mailbox = ast_strdupa(mailbox_full);
03611    strsep(&context, "@");
03612    if (ast_strlen_zero(context))
03613       context = "default";
03614 
03615    if (!(event = ast_event_new(AST_EVENT_MWI,
03616          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03617          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03618          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03619          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03620          AST_EVENT_IE_END))) {
03621       return;
03622    }
03623 
03624    ast_event_queue_and_cache(event);
03625 
03626    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03627       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03628       ast_safe_system(s);
03629    }
03630 }

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

Definition at line 7047 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write().

07048 {
07049    int res;
07050    char policy_str[21] = "";
07051 
07052    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07053       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07054       return 1;
07055    }
07056    if (*num_buffers < 0) {
07057       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07058       return -1;
07059    }
07060    if (!strcasecmp(policy_str, "full")) {
07061       *policy = DAHDI_POLICY_WHEN_FULL;
07062    } else if (!strcasecmp(policy_str, "immediate")) {
07063       *policy = DAHDI_POLICY_IMMEDIATE;
07064 #if defined(HAVE_DAHDI_HALF_FULL)
07065    } else if (!strcasecmp(policy_str, "half")) {
07066       *policy = DAHDI_POLICY_HALF_FULL;
07067 #endif
07068    } else {
07069       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07070       return -1;
07071    }
07072 
07073    return 0;
07074 }

static char* parse_spanchan ( char *  chanstr,
char **  subdir 
) [static]

Definition at line 16816 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

16817 {
16818    char *p;
16819 
16820    if ((p = strrchr(chanstr, '!')) == NULL) {
16821       *subdir = NULL;
16822       return chanstr;
16823    }
16824    *p++ = '\0';
16825    string_replace(chanstr, '!', '/');
16826    *subdir = chanstr;
16827    return p;
16828 }

static int prepare_pri ( struct dahdi_pri pri  )  [static]

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

14188 {
14189    int i, res, x;
14190    struct dahdi_params p;
14191    struct dahdi_bufferinfo bi;
14192    struct dahdi_spaninfo si;
14193 
14194    pri->pri.calls = &dahdi_pri_callbacks;
14195 
14196    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14197       if (!pri->dchannels[i])
14198          break;
14199       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14200       x = pri->dchannels[i];
14201       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14202          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14203          return -1;
14204       }
14205       memset(&p, 0, sizeof(p));
14206       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14207       if (res) {
14208          dahdi_close_pri_fd(pri, i);
14209          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14210          return -1;
14211       }
14212       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14213          dahdi_close_pri_fd(pri, i);
14214          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14215          return -1;
14216       }
14217       memset(&si, 0, sizeof(si));
14218       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14219       if (res) {
14220          dahdi_close_pri_fd(pri, i);
14221          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14222       }
14223       if (!si.alarms) {
14224          pri_event_noalarm(&pri->pri, i, 1);
14225       } else {
14226          pri_event_alarm(&pri->pri, i, 1);
14227       }
14228       memset(&bi, 0, sizeof(bi));
14229       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14230       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14231       bi.numbufs = 32;
14232       bi.bufsize = 1024;
14233       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14234          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14235          dahdi_close_pri_fd(pri, i);
14236          return -1;
14237       }
14238       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14239    }
14240    return 0;
14241 }

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

Definition at line 12099 of file chan_dahdi.c.

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

Referenced by setup_dahdi_int().

12100 {
12101    if (pris[span].mastertrunkgroup) {
12102       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);
12103       return -1;
12104    }
12105    pris[span].mastertrunkgroup = trunkgroup;
12106    pris[span].prilogicalspan = logicalspan;
12107    return 0;
12108 }

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

Definition at line 12036 of file chan_dahdi.c.

References ast_log(), NUM_SPANS, and pris.

Referenced by setup_dahdi_int().

12037 {
12038    struct dahdi_spaninfo si;
12039    struct dahdi_params p;
12040    int fd;
12041    int span;
12042    int ospan=0;
12043    int x,y;
12044    for (x = 0; x < NUM_SPANS; x++) {
12045       if (pris[x].pri.trunkgroup == trunkgroup) {
12046          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12047          return -1;
12048       }
12049    }
12050    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12051       if (!channels[y])
12052          break;
12053       memset(&si, 0, sizeof(si));
12054       memset(&p, 0, sizeof(p));
12055       fd = open("/dev/dahdi/channel", O_RDWR);
12056       if (fd < 0) {
12057          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12058          return -1;
12059       }
12060       x = channels[y];
12061       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12062          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12063          close(fd);
12064          return -1;
12065       }
12066       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12067          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12068          return -1;
12069       }
12070       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12071          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12072          close(fd);
12073          return -1;
12074       }
12075       span = p.spanno - 1;
12076       if (pris[span].pri.trunkgroup) {
12077          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12078          close(fd);
12079          return -1;
12080       }
12081       if (pris[span].pri.pvts[0]) {
12082          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12083          close(fd);
12084          return -1;
12085       }
12086       if (!y) {
12087          pris[span].pri.trunkgroup = trunkgroup;
12088          ospan = span;
12089       }
12090       pris[ospan].dchannels[y] = channels[y];
12091       pris[span].pri.span = span + 1;
12092       close(fd);
12093    }
12094    return 0;
12095 }

static int pri_resolve_span ( int *  span,
int  channel,
int  offset,
struct dahdi_spaninfo *  si 
) [static]

Definition at line 11990 of file chan_dahdi.c.

References ast_log(), dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pvt::pri, pris, and sig_pri_span::trunkgroup.

11991 {
11992    int x;
11993    int trunkgroup;
11994    /* Get appropriate trunk group if there is one */
11995    trunkgroup = pris[*span].mastertrunkgroup;
11996    if (trunkgroup) {
11997       /* Select a specific trunk group */
11998       for (x = 0; x < NUM_SPANS; x++) {
11999          if (pris[x].pri.trunkgroup == trunkgroup) {
12000             *span = x;
12001             return 0;
12002          }
12003       }
12004       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12005       *span = -1;
12006    } else {
12007       if (pris[*span].pri.trunkgroup) {
12008          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);
12009          *span = -1;
12010       } else if (pris[*span].mastertrunkgroup) {
12011          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12012          *span = -1;
12013       } else {
12014          if (si->totalchans == 31) {
12015             /* E1 */
12016             pris[*span].dchannels[0] = 16 + offset;
12017          } else if (si->totalchans == 24) {
12018             /* T1 or J1 */
12019             pris[*span].dchannels[0] = 24 + offset;
12020          } else if (si->totalchans == 3) {
12021             /* BRI */
12022             pris[*span].dchannels[0] = 3 + offset;
12023          } else {
12024             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);
12025             *span = -1;
12026             return 0;
12027          }
12028          pris[*span].pri.span = *span + 1;
12029       }
12030    }
12031    return 0;
12032 }

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

Definition at line 16959 of file chan_dahdi.c.

References ast_jb_read_conf(), ast_log(), build_channels(), global_jbconf, ast_variable::lineno, ast_variable::name, ast_variable::next, PROC_DAHDI_OPT_NOCHAN, and ast_variable::value.

Referenced by setup_dahdi_int().

16960 {
16961    struct dahdi_pvt *tmp;
16962    int y;
16963    int found_pseudo = 0;
16964    struct ast_variable *dahdichan = NULL;
16965 
16966    for (; v; v = v->next) {
16967       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16968          continue;
16969 
16970       /* Create the interface list */
16971       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16972          if (options & PROC_DAHDI_OPT_NOCHAN) {
16973             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16974             continue;
16975          }
16976          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16977             if (confp->ignore_failed_channels) {
16978                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16979                continue;
16980             } else {
16981                return -1;
16982             }
16983          }
16984          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16985       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16986          confp->ignore_failed_channels = ast_true(v->value);
16987       } else if (!strcasecmp(v->name, "buffers")) {
16988          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16989             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16990             confp->chan.buf_no = numbufs;
16991             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16992          }
16993       } else if (!strcasecmp(v->name, "faxbuffers")) {
16994          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16995             confp->chan.usefaxbuffers = 1;
16996          }
16997       } else if (!strcasecmp(v->name, "dahdichan")) {
16998          /* Only process the last dahdichan value. */
16999          dahdichan = v;
17000       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17001          usedistinctiveringdetection = ast_true(v->value);
17002       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17003          distinctiveringaftercid = ast_true(v->value);
17004       } else if (!strcasecmp(v->name, "dring1context")) {
17005          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17006       } else if (!strcasecmp(v->name, "dring2context")) {
17007          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17008       } else if (!strcasecmp(v->name, "dring3context")) {
17009          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17010       } else if (!strcasecmp(v->name, "dring1range")) {
17011          confp->chan.drings.ringnum[0].range = atoi(v->value);
17012       } else if (!strcasecmp(v->name, "dring2range")) {
17013          confp->chan.drings.ringnum[1].range = atoi(v->value);
17014       } else if (!strcasecmp(v->name, "dring3range")) {
17015          confp->chan.drings.ringnum[2].range = atoi(v->value);
17016       } else if (!strcasecmp(v->name, "dring1")) {
17017          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]);
17018       } else if (!strcasecmp(v->name, "dring2")) {
17019          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]);
17020       } else if (!strcasecmp(v->name, "dring3")) {
17021          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]);
17022       } else if (!strcasecmp(v->name, "usecallerid")) {
17023          confp->chan.use_callerid = ast_true(v->value);
17024       } else if (!strcasecmp(v->name, "cidsignalling")) {
17025          if (!strcasecmp(v->value, "bell"))
17026             confp->chan.cid_signalling = CID_SIG_BELL;
17027          else if (!strcasecmp(v->value, "v23"))
17028             confp->chan.cid_signalling = CID_SIG_V23;
17029          else if (!strcasecmp(v->value, "dtmf"))
17030             confp->chan.cid_signalling = CID_SIG_DTMF;
17031          else if (!strcasecmp(v->value, "smdi"))
17032             confp->chan.cid_signalling = CID_SIG_SMDI;
17033          else if (!strcasecmp(v->value, "v23_jp"))
17034             confp->chan.cid_signalling = CID_SIG_V23_JP;
17035          else if (ast_true(v->value))
17036             confp->chan.cid_signalling = CID_SIG_BELL;
17037       } else if (!strcasecmp(v->name, "cidstart")) {
17038          if (!strcasecmp(v->value, "ring"))
17039             confp->chan.cid_start = CID_START_RING;
17040          else if (!strcasecmp(v->value, "polarity_in"))
17041             confp->chan.cid_start = CID_START_POLARITY_IN;
17042          else if (!strcasecmp(v->value, "polarity"))
17043             confp->chan.cid_start = CID_START_POLARITY;
17044          else if (!strcasecmp(v->value, "dtmf"))
17045             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17046          else if (ast_true(v->value))
17047             confp->chan.cid_start = CID_START_RING;
17048       } else if (!strcasecmp(v->name, "threewaycalling")) {
17049          confp->chan.threewaycalling = ast_true(v->value);
17050       } else if (!strcasecmp(v->name, "cancallforward")) {
17051          confp->chan.cancallforward = ast_true(v->value);
17052       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17053          if (ast_true(v->value))
17054             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17055          else
17056             confp->chan.dtmfrelax = 0;
17057       } else if (!strcasecmp(v->name, "mailbox")) {
17058          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17059       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17060          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17061             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17062          }
17063       } else if (!strcasecmp(v->name, "adsi")) {
17064          confp->chan.adsi = ast_true(v->value);
17065       } else if (!strcasecmp(v->name, "usesmdi")) {
17066          confp->chan.use_smdi = ast_true(v->value);
17067       } else if (!strcasecmp(v->name, "smdiport")) {
17068          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17069       } else if (!strcasecmp(v->name, "transfer")) {
17070          confp->chan.transfer = ast_true(v->value);
17071       } else if (!strcasecmp(v->name, "canpark")) {
17072          confp->chan.canpark = ast_true(v->value);
17073       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17074          confp->chan.echocanbridged = ast_true(v->value);
17075       } else if (!strcasecmp(v->name, "busydetect")) {
17076          confp->chan.busydetect = ast_true(v->value);
17077       } else if (!strcasecmp(v->name, "busycount")) {
17078          confp->chan.busycount = atoi(v->value);
17079       } else if (!strcasecmp(v->name, "silencethreshold")) {
17080          confp->chan.silencethreshold = atoi(v->value);
17081       } else if (!strcasecmp(v->name, "busycompare")) {
17082          confp->chan.busycompare = ast_true(v->value);
17083       } else if (!strcasecmp(v->name, "busypattern")) {
17084          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
17085             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17086          }
17087          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
17088          if (count == 1)
17089             confp->chan.busyquietlength = 0;
17090          else if (count < 1)
17091             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
17092       } else if (!strcasecmp(v->name, "busyfuzziness")) {
17093          confp->chan.busyfuzziness = atoi(v->value);
17094       } else if (!strcasecmp(v->name, "callprogress")) {
17095          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17096          if (ast_true(v->value))
17097             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17098       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17099          confp->chan.waitfordialtone = atoi(v->value);
17100       } else if (!strcasecmp(v->name, "faxdetect")) {
17101          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17102          if (!strcasecmp(v->value, "incoming")) {
17103             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17104          } else if (!strcasecmp(v->value, "outgoing")) {
17105             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17106          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17107             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17108       } else if (!strcasecmp(v->name, "echocancel")) {
17109          process_echocancel(confp, v->value, v->lineno);
17110       } else if (!strcasecmp(v->name, "echotraining")) {
17111          if (sscanf(v->value, "%30d", &y) == 1) {
17112             if ((y < 10) || (y > 4000)) {
17113                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17114             } else {
17115                confp->chan.echotraining = y;
17116             }
17117          } else if (ast_true(v->value)) {
17118             confp->chan.echotraining = 400;
17119          } else
17120             confp->chan.echotraining = 0;
17121       } else if (!strcasecmp(v->name, "hidecallerid")) {
17122          confp->chan.hidecallerid = ast_true(v->value);
17123       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17124          confp->chan.hidecalleridname = ast_true(v->value);
17125       } else if (!strcasecmp(v->name, "pulsedial")) {
17126          confp->chan.pulse = ast_true(v->value);
17127       } else if (!strcasecmp(v->name, "callreturn")) {
17128          confp->chan.callreturn = ast_true(v->value);
17129       } else if (!strcasecmp(v->name, "callwaiting")) {
17130          confp->chan.callwaiting = ast_true(v->value);
17131       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17132          confp->chan.callwaitingcallerid = ast_true(v->value);
17133       } else if (!strcasecmp(v->name, "context")) {
17134          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17135       } else if (!strcasecmp(v->name, "language")) {
17136          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17137       } else if (!strcasecmp(v->name, "progzone")) {
17138          ast_copy_string(progzone, v->value, sizeof(progzone));
17139       } else if (!strcasecmp(v->name, "mohinterpret")
17140          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17141          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17142       } else if (!strcasecmp(v->name, "mohsuggest")) {
17143          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17144       } else if (!strcasecmp(v->name, "parkinglot")) {
17145          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17146       } else if (!strcasecmp(v->name, "stripmsd")) {
17147          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17148          confp->chan.stripmsd = atoi(v->value);
17149       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17150          numbufs = atoi(v->value);
17151       } else if (!strcasecmp(v->name, "group")) {
17152          confp->chan.group = ast_get_group(v->value);
17153       } else if (!strcasecmp(v->name, "callgroup")) {
17154          if (!strcasecmp(v->value, "none"))
17155             confp->chan.callgroup = 0;
17156          else
17157             confp->chan.callgroup = ast_get_group(v->value);
17158       } else if (!strcasecmp(v->name, "pickupgroup")) {
17159          if (!strcasecmp(v->value, "none"))
17160             confp->chan.pickupgroup = 0;
17161          else
17162             confp->chan.pickupgroup = ast_get_group(v->value);
17163       } else if (!strcasecmp(v->name, "setvar")) {
17164          char *varname = ast_strdupa(v->value), *varval = NULL;
17165          struct ast_variable *tmpvar;
17166          if (varname && (varval = strchr(varname, '='))) {
17167             *varval++ = '\0';
17168             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17169                tmpvar->next = confp->chan.vars;
17170                confp->chan.vars = tmpvar;
17171             }
17172          }
17173       } else if (!strcasecmp(v->name, "immediate")) {
17174          confp->chan.immediate = ast_true(v->value);
17175       } else if (!strcasecmp(v->name, "transfertobusy")) {
17176          confp->chan.transfertobusy = ast_true(v->value);
17177       } else if (!strcasecmp(v->name, "mwimonitor")) {
17178          confp->chan.mwimonitor_neon = 0;
17179          confp->chan.mwimonitor_fsk = 0;
17180          confp->chan.mwimonitor_rpas = 0;
17181          if (strcasestr(v->value, "fsk")) {
17182             confp->chan.mwimonitor_fsk = 1;
17183          }
17184          if (strcasestr(v->value, "rpas")) {
17185             confp->chan.mwimonitor_rpas = 1;
17186          }
17187          if (strcasestr(v->value, "neon")) {
17188             confp->chan.mwimonitor_neon = 1;
17189          }
17190          /* If set to true or yes, assume that simple fsk is desired */
17191          if (ast_true(v->value)) {
17192             confp->chan.mwimonitor_fsk = 1;
17193          }
17194       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17195          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17196             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17197          }
17198       } else if (!strcasecmp(v->name, "rxgain")) {
17199          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17200             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17201          }
17202       } else if (!strcasecmp(v->name, "txgain")) {
17203          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17204             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17205          }
17206       } else if (!strcasecmp(v->name, "txdrc")) {
17207          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17208             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17209          }
17210       } else if (!strcasecmp(v->name, "rxdrc")) {
17211          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17212             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17213          }
17214       } else if (!strcasecmp(v->name, "tonezone")) {
17215          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17216             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17217          }
17218       } else if (!strcasecmp(v->name, "callerid")) {
17219          if (!strcasecmp(v->value, "asreceived")) {
17220             confp->chan.cid_num[0] = '\0';
17221             confp->chan.cid_name[0] = '\0';
17222          } else {
17223             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17224          }
17225       } else if (!strcasecmp(v->name, "fullname")) {
17226          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17227       } else if (!strcasecmp(v->name, "cid_number")) {
17228          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17229       } else if (!strcasecmp(v->name, "cid_tag")) {
17230          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17231       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17232          confp->chan.dahditrcallerid = ast_true(v->value);
17233       } else if (!strcasecmp(v->name, "restrictcid")) {
17234          confp->chan.restrictcid = ast_true(v->value);
17235       } else if (!strcasecmp(v->name, "usecallingpres")) {
17236          confp->chan.use_callingpres = ast_true(v->value);
17237       } else if (!strcasecmp(v->name, "accountcode")) {
17238          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17239       } else if (!strcasecmp(v->name, "amaflags")) {
17240          y = ast_cdr_amaflags2int(v->value);
17241          if (y < 0)
17242             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17243          else
17244             confp->chan.amaflags = y;
17245       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17246          confp->chan.polarityonanswerdelay = atoi(v->value);
17247       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17248          confp->chan.answeronpolarityswitch = ast_true(v->value);
17249       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17250          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17251       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17252          confp->chan.sendcalleridafter = atoi(v->value);
17253       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17254          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17255       } else if (ast_cc_is_config_param(v->name)) {
17256          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17257       } else if (!strcasecmp(v->name, "mwisendtype")) {
17258 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17259          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17260             mwisend_rpas = 1;
17261          } else {
17262             mwisend_rpas = 0;
17263          }
17264 #else
17265          /* Default is fsk, to turn it off you must specify nofsk */
17266          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17267          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17268             confp->chan.mwisend_fsk = 0;
17269          } else {             /* Default FSK */
17270             confp->chan.mwisend_fsk = 1;
17271          }
17272          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17273             confp->chan.mwisend_rpas = 1;
17274          } else {
17275             confp->chan.mwisend_rpas = 0;
17276          }
17277          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17278             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17279          }
17280          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17281             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17282          }
17283          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17284             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17285          }
17286 #endif
17287       } else if (reload != 1) {
17288           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17289             int orig_radio = confp->chan.radio;
17290             int orig_outsigmod = confp->chan.outsigmod;
17291             int orig_auto = confp->is_sig_auto;
17292 
17293             confp->chan.radio = 0;
17294             confp->chan.outsigmod = -1;
17295             confp->is_sig_auto = 0;
17296             if (!strcasecmp(v->value, "em")) {
17297                confp->chan.sig = SIG_EM;
17298             } else if (!strcasecmp(v->value, "em_e1")) {
17299                confp->chan.sig = SIG_EM_E1;
17300             } else if (!strcasecmp(v->value, "em_w")) {
17301                confp->chan.sig = SIG_EMWINK;
17302             } else if (!strcasecmp(v->value, "fxs_ls")) {
17303                confp->chan.sig = SIG_FXSLS;
17304             } else if (!strcasecmp(v->value, "fxs_gs")) {
17305                confp->chan.sig = SIG_FXSGS;
17306             } else if (!strcasecmp(v->value, "fxs_ks")) {
17307                confp->chan.sig = SIG_FXSKS;
17308             } else if (!strcasecmp(v->value, "fxo_ls")) {
17309                confp->chan.sig = SIG_FXOLS;
17310             } else if (!strcasecmp(v->value, "fxo_gs")) {
17311                confp->chan.sig = SIG_FXOGS;
17312             } else if (!strcasecmp(v->value, "fxo_ks")) {
17313                confp->chan.sig = SIG_FXOKS;
17314             } else if (!strcasecmp(v->value, "fxs_rx")) {
17315                confp->chan.sig = SIG_FXSKS;
17316                confp->chan.radio = 1;
17317             } else if (!strcasecmp(v->value, "fxo_rx")) {
17318                confp->chan.sig = SIG_FXOLS;
17319                confp->chan.radio = 1;
17320             } else if (!strcasecmp(v->value, "fxs_tx")) {
17321                confp->chan.sig = SIG_FXSLS;
17322                confp->chan.radio = 1;
17323             } else if (!strcasecmp(v->value, "fxo_tx")) {
17324                confp->chan.sig = SIG_FXOGS;
17325                confp->chan.radio = 1;
17326             } else if (!strcasecmp(v->value, "em_rx")) {
17327                confp->chan.sig = SIG_EM;
17328                confp->chan.radio = 1;
17329             } else if (!strcasecmp(v->value, "em_tx")) {
17330                confp->chan.sig = SIG_EM;
17331                confp->chan.radio = 1;
17332             } else if (!strcasecmp(v->value, "em_rxtx")) {
17333                confp->chan.sig = SIG_EM;
17334                confp->chan.radio = 2;
17335             } else if (!strcasecmp(v->value, "em_txrx")) {
17336                confp->chan.sig = SIG_EM;
17337                confp->chan.radio = 2;
17338             } else if (!strcasecmp(v->value, "sf")) {
17339                confp->chan.sig = SIG_SF;
17340             } else if (!strcasecmp(v->value, "sf_w")) {
17341                confp->chan.sig = SIG_SFWINK;
17342             } else if (!strcasecmp(v->value, "sf_featd")) {
17343                confp->chan.sig = SIG_FEATD;
17344             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17345                confp->chan.sig = SIG_FEATDMF;
17346             } else if (!strcasecmp(v->value, "sf_featb")) {
17347                confp->chan.sig = SIG_SF_FEATB;
17348             } else if (!strcasecmp(v->value, "sf")) {
17349                confp->chan.sig = SIG_SF;
17350             } else if (!strcasecmp(v->value, "sf_rx")) {
17351                confp->chan.sig = SIG_SF;
17352                confp->chan.radio = 1;
17353             } else if (!strcasecmp(v->value, "sf_tx")) {
17354                confp->chan.sig = SIG_SF;
17355                confp->chan.radio = 1;
17356             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17357                confp->chan.sig = SIG_SF;
17358                confp->chan.radio = 2;
17359             } else if (!strcasecmp(v->value, "sf_txrx")) {
17360                confp->chan.sig = SIG_SF;
17361                confp->chan.radio = 2;
17362             } else if (!strcasecmp(v->value, "featd")) {
17363                confp->chan.sig = SIG_FEATD;
17364             } else if (!strcasecmp(v->value, "featdmf")) {
17365                confp->chan.sig = SIG_FEATDMF;
17366             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17367                confp->chan.sig = SIG_FEATDMF_TA;
17368             } else if (!strcasecmp(v->value, "e911")) {
17369                confp->chan.sig = SIG_E911;
17370             } else if (!strcasecmp(v->value, "fgccama")) {
17371                confp->chan.sig = SIG_FGC_CAMA;
17372             } else if (!strcasecmp(v->value, "fgccamamf")) {
17373                confp->chan.sig = SIG_FGC_CAMAMF;
17374             } else if (!strcasecmp(v->value, "featb")) {
17375                confp->chan.sig = SIG_FEATB;
17376 #ifdef HAVE_PRI
17377             } else if (!strcasecmp(v->value, "pri_net")) {
17378                confp->chan.sig = SIG_PRI;
17379                confp->pri.pri.nodetype = PRI_NETWORK;
17380             } else if (!strcasecmp(v->value, "pri_cpe")) {
17381                confp->chan.sig = SIG_PRI;
17382                confp->pri.pri.nodetype = PRI_CPE;
17383             } else if (!strcasecmp(v->value, "bri_cpe")) {
17384                confp->chan.sig = SIG_BRI;
17385                confp->pri.pri.nodetype = PRI_CPE;
17386             } else if (!strcasecmp(v->value, "bri_net")) {
17387                confp->chan.sig = SIG_BRI;
17388                confp->pri.pri.nodetype = PRI_NETWORK;
17389             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17390                confp->chan.sig = SIG_BRI_PTMP;
17391                confp->pri.pri.nodetype = PRI_CPE;
17392             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17393 #if defined(HAVE_PRI_CALL_HOLD)
17394                confp->chan.sig = SIG_BRI_PTMP;
17395                confp->pri.pri.nodetype = PRI_NETWORK;
17396 #else
17397                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17398 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17399 #endif
17400 #if defined(HAVE_SS7)
17401             } else if (!strcasecmp(v->value, "ss7")) {
17402                confp->chan.sig = SIG_SS7;
17403 #endif   /* defined(HAVE_SS7) */
17404 #ifdef HAVE_OPENR2
17405             } else if (!strcasecmp(v->value, "mfcr2")) {
17406                confp->chan.sig = SIG_MFCR2;
17407 #endif
17408             } else if (!strcasecmp(v->value, "auto")) {
17409                confp->is_sig_auto = 1;
17410             } else {
17411                confp->chan.outsigmod = orig_outsigmod;
17412                confp->chan.radio = orig_radio;
17413                confp->is_sig_auto = orig_auto;
17414                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17415             }
17416           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17417             if (!strcasecmp(v->value, "em")) {
17418                confp->chan.outsigmod = SIG_EM;
17419             } else if (!strcasecmp(v->value, "em_e1")) {
17420                confp->chan.outsigmod = SIG_EM_E1;
17421             } else if (!strcasecmp(v->value, "em_w")) {
17422                confp->chan.outsigmod = SIG_EMWINK;
17423             } else if (!strcasecmp(v->value, "sf")) {
17424                confp->chan.outsigmod = SIG_SF;
17425             } else if (!strcasecmp(v->value, "sf_w")) {
17426                confp->chan.outsigmod = SIG_SFWINK;
17427             } else if (!strcasecmp(v->value, "sf_featd")) {
17428                confp->chan.outsigmod = SIG_FEATD;
17429             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17430                confp->chan.outsigmod = SIG_FEATDMF;
17431             } else if (!strcasecmp(v->value, "sf_featb")) {
17432                confp->chan.outsigmod = SIG_SF_FEATB;
17433             } else if (!strcasecmp(v->value, "sf")) {
17434                confp->chan.outsigmod = SIG_SF;
17435             } else if (!strcasecmp(v->value, "featd")) {
17436                confp->chan.outsigmod = SIG_FEATD;
17437             } else if (!strcasecmp(v->value, "featdmf")) {
17438                confp->chan.outsigmod = SIG_FEATDMF;
17439             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17440                confp->chan.outsigmod = SIG_FEATDMF_TA;
17441             } else if (!strcasecmp(v->value, "e911")) {
17442                confp->chan.outsigmod = SIG_E911;
17443             } else if (!strcasecmp(v->value, "fgccama")) {
17444                confp->chan.outsigmod = SIG_FGC_CAMA;
17445             } else if (!strcasecmp(v->value, "fgccamamf")) {
17446                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17447             } else if (!strcasecmp(v->value, "featb")) {
17448                confp->chan.outsigmod = SIG_FEATB;
17449             } else {
17450                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17451             }
17452 #ifdef HAVE_PRI
17453          } else if (!strcasecmp(v->name, "pridialplan")) {
17454             if (!strcasecmp(v->value, "national")) {
17455                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17456             } else if (!strcasecmp(v->value, "unknown")) {
17457                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17458             } else if (!strcasecmp(v->value, "private")) {
17459                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17460             } else if (!strcasecmp(v->value, "international")) {
17461                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17462             } else if (!strcasecmp(v->value, "local")) {
17463                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17464             } else if (!strcasecmp(v->value, "dynamic")) {
17465                confp->pri.pri.dialplan = -1;
17466             } else if (!strcasecmp(v->value, "redundant")) {
17467                confp->pri.pri.dialplan = -2;
17468             } else {
17469                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17470             }
17471          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17472             if (!strcasecmp(v->value, "national")) {
17473                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17474             } else if (!strcasecmp(v->value, "unknown")) {
17475                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17476             } else if (!strcasecmp(v->value, "private")) {
17477                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17478             } else if (!strcasecmp(v->value, "international")) {
17479                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17480             } else if (!strcasecmp(v->value, "local")) {
17481                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17482             } else if (!strcasecmp(v->value, "dynamic")) {
17483                confp->pri.pri.localdialplan = -1;
17484             } else if (!strcasecmp(v->value, "redundant")) {
17485                confp->pri.pri.localdialplan = -2;
17486             } else {
17487                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17488             }
17489          } else if (!strcasecmp(v->name, "switchtype")) {
17490             if (!strcasecmp(v->value, "national"))
17491                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17492             else if (!strcasecmp(v->value, "ni1"))
17493                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17494             else if (!strcasecmp(v->value, "dms100"))
17495                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17496             else if (!strcasecmp(v->value, "4ess"))
17497                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17498             else if (!strcasecmp(v->value, "5ess"))
17499                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17500             else if (!strcasecmp(v->value, "euroisdn"))
17501                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17502             else if (!strcasecmp(v->value, "qsig"))
17503                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17504             else {
17505                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17506                return -1;
17507             }
17508          } else if (!strcasecmp(v->name, "msn")) {
17509             ast_copy_string(confp->pri.pri.msn_list, v->value,
17510                sizeof(confp->pri.pri.msn_list));
17511          } else if (!strcasecmp(v->name, "nsf")) {
17512             if (!strcasecmp(v->value, "sdn"))
17513                confp->pri.pri.nsf = PRI_NSF_SDN;
17514             else if (!strcasecmp(v->value, "megacom"))
17515                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17516             else if (!strcasecmp(v->value, "tollfreemegacom"))
17517                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17518             else if (!strcasecmp(v->value, "accunet"))
17519                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17520             else if (!strcasecmp(v->value, "none"))
17521                confp->pri.pri.nsf = PRI_NSF_NONE;
17522             else {
17523                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17524                confp->pri.pri.nsf = PRI_NSF_NONE;
17525             }
17526          } else if (!strcasecmp(v->name, "priindication")) {
17527             if (!strcasecmp(v->value, "outofband"))
17528                confp->chan.priindication_oob = 1;
17529             else if (!strcasecmp(v->value, "inband"))
17530                confp->chan.priindication_oob = 0;
17531             else
17532                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17533                   v->value, v->lineno);
17534          } else if (!strcasecmp(v->name, "priexclusive")) {
17535             confp->chan.priexclusive = ast_true(v->value);
17536          } else if (!strcasecmp(v->name, "internationalprefix")) {
17537             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17538          } else if (!strcasecmp(v->name, "nationalprefix")) {
17539             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17540          } else if (!strcasecmp(v->name, "localprefix")) {
17541             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17542          } else if (!strcasecmp(v->name, "privateprefix")) {
17543             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17544          } else if (!strcasecmp(v->name, "unknownprefix")) {
17545             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17546          } else if (!strcasecmp(v->name, "resetinterval")) {
17547             if (!strcasecmp(v->value, "never"))
17548                confp->pri.pri.resetinterval = -1;
17549             else if (atoi(v->value) >= 60)
17550                confp->pri.pri.resetinterval = atoi(v->value);
17551             else
17552                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17553                   v->value, v->lineno);
17554          } else if (!strcasecmp(v->name, "minunused")) {
17555             confp->pri.pri.minunused = atoi(v->value);
17556          } else if (!strcasecmp(v->name, "minidle")) {
17557             confp->pri.pri.minidle = atoi(v->value);
17558          } else if (!strcasecmp(v->name, "idleext")) {
17559             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17560          } else if (!strcasecmp(v->name, "idledial")) {
17561             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17562          } else if (!strcasecmp(v->name, "overlapdial")) {
17563             if (ast_true(v->value)) {
17564                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17565             } else if (!strcasecmp(v->value, "incoming")) {
17566                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17567             } else if (!strcasecmp(v->value, "outgoing")) {
17568                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17569             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17570                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17571             } else {
17572                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17573             }
17574 #ifdef HAVE_PRI_PROG_W_CAUSE
17575          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17576             if (!strcasecmp(v->value, "logical")) {
17577                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17578             } else if (!strcasecmp(v->value, "physical")) {
17579                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17580             } else {
17581                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17582             }
17583 #endif
17584          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17585             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17586 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17587          } else if (!strcasecmp(v->name, "service_message_support")) {
17588             /* assuming switchtype for this channel group has been configured already */
17589             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17590                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17591                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17592                confp->pri.pri.enable_service_message_support = 1;
17593             } else {
17594                confp->pri.pri.enable_service_message_support = 0;
17595             }
17596 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17597 #ifdef HAVE_PRI_INBANDDISCONNECT
17598          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17599             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17600 #endif
17601          } else if (!strcasecmp(v->name, "pritimer")) {
17602 #ifdef PRI_GETSET_TIMERS
17603             char tmp[20];
17604             char *timerc;
17605             char *c;
17606             int timer;
17607             int timeridx;
17608 
17609             ast_copy_string(tmp, v->value, sizeof(tmp));
17610             c = tmp;
17611             timerc = strsep(&c, ",");
17612             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17613                timeridx = pri_timer2idx(timerc);
17614                timer = atoi(c);
17615                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17616                   ast_log(LOG_WARNING,
17617                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17618                      v->lineno);
17619                } else if (!timer) {
17620                   ast_log(LOG_WARNING,
17621                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17622                      c, timerc, v->lineno);
17623                } else {
17624                   confp->pri.pri.pritimers[timeridx] = timer;
17625                }
17626             } else {
17627                ast_log(LOG_WARNING,
17628                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17629                   v->value, v->lineno);
17630             }
17631 #endif /* PRI_GETSET_TIMERS */
17632          } else if (!strcasecmp(v->name, "facilityenable")) {
17633             confp->pri.pri.facilityenable = ast_true(v->value);
17634 #if defined(HAVE_PRI_AOC_EVENTS)
17635          } else if (!strcasecmp(v->name, "aoc_enable")) {
17636             confp->pri.pri.aoc_passthrough_flag = 0;
17637             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17638                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17639             }
17640             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17641                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17642             }
17643             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17644                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17645             }
17646          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17647             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17648 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17649 #if defined(HAVE_PRI_CALL_HOLD)
17650          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17651             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17652 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17653 #if defined(HAVE_PRI_CCSS)
17654          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17655             if (!strcasecmp(v->value, "global")) {
17656                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17657             } else if (!strcasecmp(v->value, "specific")) {
17658                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17659             } else {
17660                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17661             }
17662          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17663             if (!strcasecmp(v->value, "release")) {
17664                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17665             } else if (!strcasecmp(v->value, "retain")) {
17666                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17667             } else if (!strcasecmp(v->value, "do_not_care")) {
17668                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17669             } else {
17670                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17671             }
17672          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17673             if (!strcasecmp(v->value, "release")) {
17674                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17675             } else if (!strcasecmp(v->value, "retain")) {
17676                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17677             } else {
17678                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17679             }
17680 #endif   /* defined(HAVE_PRI_CCSS) */
17681 #if defined(HAVE_PRI_CALL_WAITING)
17682          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17683             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17684             if (confp->pri.pri.max_call_waiting_calls < 0) {
17685                /* Negative values are not allowed. */
17686                confp->pri.pri.max_call_waiting_calls = 0;
17687             }
17688          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17689             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17690 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17691 #if defined(HAVE_PRI_MWI)
17692          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17693             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17694                sizeof(confp->pri.pri.mwi_mailboxes));
17695 #endif   /* defined(HAVE_PRI_MWI) */
17696          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17697             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17698          } else if (!strcasecmp(v->name, "layer1_presence")) {
17699             if (!strcasecmp(v->value, "required")) {
17700                confp->pri.pri.layer1_ignored = 0;
17701             } else if (!strcasecmp(v->value, "ignore")) {
17702                confp->pri.pri.layer1_ignored = 1;
17703             } else {
17704                /* Default */
17705                confp->pri.pri.layer1_ignored = 0;
17706             }
17707 #if defined(HAVE_PRI_L2_PERSISTENCE)
17708          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17709             if (!strcasecmp(v->value, "keep_up")) {
17710                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17711             } else if (!strcasecmp(v->value, "leave_down")) {
17712                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17713             } else {
17714                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17715             }
17716 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17717 #endif /* HAVE_PRI */
17718 #if defined(HAVE_SS7)
17719          } else if (!strcasecmp(v->name, "ss7type")) {
17720             if (!strcasecmp(v->value, "itu")) {
17721                cur_ss7type = SS7_ITU;
17722             } else if (!strcasecmp(v->value, "ansi")) {
17723                cur_ss7type = SS7_ANSI;
17724             } else
17725                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17726          } else if (!strcasecmp(v->name, "linkset")) {
17727             cur_linkset = atoi(v->value);
17728          } else if (!strcasecmp(v->name, "pointcode")) {
17729             cur_pointcode = parse_pointcode(v->value);
17730          } else if (!strcasecmp(v->name, "adjpointcode")) {
17731             cur_adjpointcode = parse_pointcode(v->value);
17732          } else if (!strcasecmp(v->name, "defaultdpc")) {
17733             cur_defaultdpc = parse_pointcode(v->value);
17734          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17735             cur_cicbeginswith = atoi(v->value);
17736          } else if (!strcasecmp(v->name, "networkindicator")) {
17737             if (!strcasecmp(v->value, "national"))
17738                cur_networkindicator = SS7_NI_NAT;
17739             else if (!strcasecmp(v->value, "national_spare"))
17740                cur_networkindicator = SS7_NI_NAT_SPARE;
17741             else if (!strcasecmp(v->value, "international"))
17742                cur_networkindicator = SS7_NI_INT;
17743             else if (!strcasecmp(v->value, "international_spare"))
17744                cur_networkindicator = SS7_NI_INT_SPARE;
17745             else
17746                cur_networkindicator = -1;
17747          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17748             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17749          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17750             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17751          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17752             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17753          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17754             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17755          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17756             if (!strcasecmp(v->value, "national")) {
17757                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17758             } else if (!strcasecmp(v->value, "international")) {
17759                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17760             } else if (!strcasecmp(v->value, "subscriber")) {
17761                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17762             } else if (!strcasecmp(v->value, "unknown")) {
17763                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17764             } else if (!strcasecmp(v->value, "dynamic")) {
17765                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17766             } else {
17767                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17768             }
17769          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17770             if (!strcasecmp(v->value, "national")) {
17771                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17772             } else if (!strcasecmp(v->value, "international")) {
17773                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17774             } else if (!strcasecmp(v->value, "subscriber")) {
17775                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17776             } else if (!strcasecmp(v->value, "unknown")) {
17777                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17778             } else if (!strcasecmp(v->value, "dynamic")) {
17779                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17780             } else {
17781                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17782             }
17783          } else if (!strcasecmp(v->name, "sigchan")) {
17784             int sigchan, res;
17785             sigchan = atoi(v->value);
17786             res = linkset_addsigchan(sigchan);
17787             if (res < 0)
17788                return -1;
17789 
17790          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17791             struct dahdi_ss7 *link;
17792             link = ss7_resolve_linkset(cur_linkset);
17793             if (!link) {
17794                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17795                return -1;
17796             }
17797             if (ast_true(v->value))
17798                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17799 #endif   /* defined(HAVE_SS7) */
17800 #ifdef HAVE_OPENR2
17801          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17802             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17803             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);
17804          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17805             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17806          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17807             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17808             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17809                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17810                confp->mfcr2.variant = OR2_VAR_ITU;
17811             }
17812          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17813             confp->mfcr2.mfback_timeout = atoi(v->value);
17814             if (!confp->mfcr2.mfback_timeout) {
17815                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17816                confp->mfcr2.mfback_timeout = -1;
17817             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17818                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17819             }
17820          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17821             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17822             if (confp->mfcr2.metering_pulse_timeout > 500) {
17823                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17824             }
17825          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17826             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17827          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17828             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17829          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17830             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17831          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17832             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17833          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17834             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17835          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17836             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17837          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17838             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17839 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17840          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17841             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17842 #endif
17843          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17844             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17845          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17846             confp->mfcr2.max_ani = atoi(v->value);
17847             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17848                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17849             }
17850          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17851             confp->mfcr2.max_dnis = atoi(v->value);
17852             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17853                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17854             }
17855          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17856             confp->mfcr2.category = openr2_proto_get_category(v->value);
17857             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17858                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17859                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17860                      v->value, v->lineno);
17861             }
17862          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17863             openr2_log_level_t tmplevel;
17864             char *clevel;
17865             char *logval = ast_strdupa(v->value);
17866             while (logval) {
17867                clevel = strsep(&logval,",");
17868                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17869                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17870                   continue;
17871                }
17872                confp->mfcr2.loglevel |= tmplevel;
17873             }
17874 #endif /* HAVE_OPENR2 */
17875          } else if (!strcasecmp(v->name, "cadence")) {
17876             /* setup to scan our argument */
17877             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17878             int i;
17879             struct dahdi_ring_cadence new_cadence;
17880             int cid_location = -1;
17881             int firstcadencepos = 0;
17882             char original_args[80];
17883             int cadence_is_ok = 1;
17884 
17885             ast_copy_string(original_args, v->value, sizeof(original_args));
17886             /* 16 cadences allowed (8 pairs) */
17887             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]);
17888 
17889             /* Cadence must be even (on/off) */
17890             if (element_count % 2 == 1) {
17891                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17892                cadence_is_ok = 0;
17893             }
17894 
17895             /* Ring cadences cannot be negative */
17896             for (i = 0; i < element_count; i++) {
17897                if (c[i] == 0) {
17898                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17899                   cadence_is_ok = 0;
17900                   break;
17901                } else if (c[i] < 0) {
17902                   if (i % 2 == 1) {
17903                      /* Silence duration, negative possibly okay */
17904                      if (cid_location == -1) {
17905                         cid_location = i;
17906                         c[i] *= -1;
17907                      } else {
17908                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17909                         cadence_is_ok = 0;
17910                         break;
17911                      }
17912                   } else {
17913                      if (firstcadencepos == 0) {
17914                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17915                                  /* duration will be passed negative to the DAHDI driver */
17916                      } else {
17917                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17918                         cadence_is_ok = 0;
17919                         break;
17920                      }
17921                   }
17922                }
17923             }
17924 
17925             /* Substitute our scanned cadence */
17926             for (i = 0; i < 16; i++) {
17927                new_cadence.ringcadence[i] = c[i];
17928             }
17929 
17930             if (cadence_is_ok) {
17931                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17932                if (element_count < 2) {
17933                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17934                } else {
17935                   if (cid_location == -1) {
17936                      /* user didn't say; default to first pause */
17937                      cid_location = 1;
17938                   } else {
17939                      /* convert element_index to cidrings value */
17940                      cid_location = (cid_location + 1) / 2;
17941                   }
17942                   /* ---we like their cadence; try to install it--- */
17943                   if (!user_has_defined_cadences++)
17944                      /* this is the first user-defined cadence; clear the default user cadences */
17945                      num_cadence = 0;
17946                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17947                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17948                   else {
17949                      cadences[num_cadence] = new_cadence;
17950                      cidrings[num_cadence++] = cid_location;
17951                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17952                   }
17953                }
17954             }
17955          } else if (!strcasecmp(v->name, "ringtimeout")) {
17956             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17957          } else if (!strcasecmp(v->name, "prewink")) {
17958             confp->timing.prewinktime = atoi(v->value);
17959          } else if (!strcasecmp(v->name, "preflash")) {
17960             confp->timing.preflashtime = atoi(v->value);
17961          } else if (!strcasecmp(v->name, "wink")) {
17962             confp->timing.winktime = atoi(v->value);
17963          } else if (!strcasecmp(v->name, "flash")) {
17964             confp->timing.flashtime = atoi(v->value);
17965          } else if (!strcasecmp(v->name, "start")) {
17966             confp->timing.starttime = atoi(v->value);
17967          } else if (!strcasecmp(v->name, "rxwink")) {
17968             confp->timing.rxwinktime = atoi(v->value);
17969          } else if (!strcasecmp(v->name, "rxflash")) {
17970             confp->timing.rxflashtime = atoi(v->value);
17971          } else if (!strcasecmp(v->name, "debounce")) {
17972             confp->timing.debouncetime = atoi(v->value);
17973          } else if (!strcasecmp(v->name, "toneduration")) {
17974             int toneduration;
17975             int ctlfd;
17976             int res;
17977             struct dahdi_dialparams dps;
17978 
17979             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17980             if (ctlfd == -1) {
17981                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17982                return -1;
17983             }
17984 
17985             toneduration = atoi(v->value);
17986             if (toneduration > -1) {
17987                memset(&dps, 0, sizeof(dps));
17988 
17989                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17990                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17991                if (res < 0) {
17992                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17993                   close(ctlfd);
17994                   return -1;
17995                }
17996             }
17997             close(ctlfd);
17998          } else if (!strcasecmp(v->name, "defaultcic")) {
17999             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18000          } else if (!strcasecmp(v->name, "defaultozz")) {
18001             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18002          } else if (!strcasecmp(v->name, "mwilevel")) {
18003             mwilevel = atoi(v->value);
18004          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18005             dtmfcid_level = atoi(v->value);
18006          } else if (!strcasecmp(v->name, "reportalarms")) {
18007             if (!strcasecmp(v->value, "all"))
18008                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18009             if (!strcasecmp(v->value, "none"))
18010                report_alarms = 0;
18011             else if (!strcasecmp(v->value, "channels"))
18012                report_alarms = REPORT_CHANNEL_ALARMS;
18013             else if (!strcasecmp(v->value, "spans"))
18014                report_alarms = REPORT_SPAN_ALARMS;
18015           }
18016       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18017          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18018    }
18019 
18020    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18021    if (confp->chan.vars) {
18022       ast_variables_destroy(confp->chan.vars);
18023       confp->chan.vars = NULL;
18024    }
18025 
18026    if (dahdichan) {
18027       /* Process the deferred dahdichan value. */
18028       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18029          &found_pseudo)) {
18030          if (confp->ignore_failed_channels) {
18031             ast_log(LOG_WARNING,
18032                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18033                dahdichan->value);
18034          } else {
18035             return -1;
18036          }
18037       }
18038    }
18039 
18040    /* mark the first channels of each DAHDI span to watch for their span alarms */
18041    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18042       if (!tmp->destroy && tmp->span != y) {
18043          tmp->manages_span_alarms = 1;
18044          y = tmp->span; 
18045       } else {
18046          tmp->manages_span_alarms = 0;
18047       }
18048    }
18049 
18050    /*< \todo why check for the pseudo in the per-channel section.
18051     * Any actual use for manual setup of the pseudo channel? */
18052    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18053       /* use the default configuration for a channel, so
18054          that any settings from real configured channels
18055          don't "leak" into the pseudo channel config
18056       */
18057       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18058 
18059       if (conf.chan.cc_params) {
18060          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18061       } else {
18062          tmp = NULL;
18063       }
18064       if (tmp) {
18065          ast_verb(3, "Automatically generated pseudo channel\n");
18066       } else {
18067          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18068       }
18069       ast_cc_config_params_destroy(conf.chan.cc_params);
18070    }
18071    return 0;
18072 }

static void process_echocancel ( struct dahdi_chan_conf confp,
const char *  data,
unsigned int  line 
) [static]

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

16904 {
16905    char *parse = ast_strdupa(data);
16906    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16907    unsigned int param_count;
16908    unsigned int x;
16909 
16910    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16911       return;
16912 
16913    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16914 
16915    /* first parameter is tap length, process it here */
16916 
16917    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16918 
16919    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16920       confp->chan.echocancel.head.tap_length = x;
16921    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16922       confp->chan.echocancel.head.tap_length = 128;
16923 
16924    /* now process any remaining parameters */
16925 
16926    for (x = 1; x < param_count; x++) {
16927       struct {
16928          char *name;
16929          char *value;
16930       } param;
16931 
16932       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16933          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16934          continue;
16935       }
16936 
16937       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16938          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16939          continue;
16940       }
16941 
16942       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16943 
16944       if (param.value) {
16945          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16946             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16947             continue;
16948          }
16949       }
16950       confp->chan.echocancel.head.param_count++;
16951    }
16952 }

static int reload ( void   )  [static]

Definition at line 18750 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

18751 {
18752    int res = 0;
18753 
18754    res = setup_dahdi(1);
18755    if (res) {
18756       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18757       return -1;
18758    }
18759    return 0;
18760 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

04829 {
04830    p->confno = -1;
04831    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04832    if (p->subs[SUB_REAL].dfd > -1) {
04833       struct dahdi_confinfo zi;
04834 
04835       memset(&zi, 0, sizeof(zi));
04836       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04837          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04838    }
04839    return 0;
04840 }

static int restart_monitor ( void   )  [static]

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

11964 {
11965    /* If we're supposed to be stopped -- stay stopped */
11966    if (monitor_thread == AST_PTHREADT_STOP)
11967       return 0;
11968    ast_mutex_lock(&monlock);
11969    if (monitor_thread == pthread_self()) {
11970       ast_mutex_unlock(&monlock);
11971       ast_log(LOG_WARNING, "Cannot kill myself\n");
11972       return -1;
11973    }
11974    if (monitor_thread != AST_PTHREADT_NULL) {
11975       /* Wake up the thread */
11976       pthread_kill(monitor_thread, SIGURG);
11977    } else {
11978       /* Start a new monitor */
11979       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11980          ast_mutex_unlock(&monlock);
11981          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11982          return -1;
11983       }
11984    }
11985    ast_mutex_unlock(&monlock);
11986    return 0;
11987 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

05242 {
05243    int res;
05244    if (p->saveconf.confmode) {
05245       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05246       p->saveconf.confmode = 0;
05247       if (res) {
05248          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05249          return -1;
05250       }
05251       ast_debug(1, "Restored conferencing\n");
05252    }
05253    return 0;
05254 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

05149 {
05150    int res;
05151 
05152    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05153    if (res) {
05154       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05155       return -1;
05156    }
05157 
05158    return 0;
05159 }

static int revert_fax_buffers ( struct dahdi_pvt p,
struct ast_channel ast 
) [static]

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

06139 {
06140    if (p->bufferoverrideinuse) {
06141       /* faxbuffers are in use, revert them */
06142       struct dahdi_bufferinfo bi = {
06143          .txbufpolicy = p->buf_policy,
06144          .rxbufpolicy = p->buf_policy,
06145          .bufsize = p->bufsize,
06146          .numbufs = p->buf_no
06147       };
06148       int bpres;
06149 
06150       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06151          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06152       }
06153       p->bufferoverrideinuse = 0;
06154       return bpres;
06155    }
06156 
06157    return -1;
06158 }

static int save_conference ( struct dahdi_pvt p  )  [static]

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

05216 {
05217    struct dahdi_confinfo c;
05218    int res;
05219    if (p->saveconf.confmode) {
05220       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05221       return -1;
05222    }
05223    p->saveconf.chan = 0;
05224    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05225    if (res) {
05226       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05227       p->saveconf.confmode = 0;
05228       return -1;
05229    }
05230    memset(&c, 0, sizeof(c));
05231    c.confmode = DAHDI_CONF_NORMAL;
05232    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05233    if (res) {
05234       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05235       return -1;
05236    }
05237    ast_debug(1, "Disabled conferencing\n");
05238    return 0;
05239 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

05300 {
05301    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05302    int res;
05303    /* Take out of linear mode if necessary */
05304    if (p->subs[SUB_REAL].linear) {
05305       p->subs[SUB_REAL].linear = 0;
05306       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05307    }
05308    while (p->cidpos < p->cidlen) {
05309       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05310       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05311       if (res < 0) {
05312          if (errno == EAGAIN)
05313             return 0;
05314          else {
05315             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05316             return -1;
05317          }
05318       }
05319       if (!res)
05320          return 0;
05321       p->cidpos += res;
05322    }
05323    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05324    ast_free(p->cidspill);
05325    p->cidspill = NULL;
05326    if (p->callwaitcas) {
05327       /* Wait for CID/CW to expire */
05328       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05329       p->cid_suppress_expire = p->cidcwexpire;
05330    } else
05331       restore_conference(p);
05332    return 0;
05333 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

05257 {
05258    p->callwaitcas = 0;
05259    p->cidcwexpire = 0;
05260    p->cid_suppress_expire = 0;
05261    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05262       return -1;
05263    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05264    /* Make sure we account for the end */
05265    p->cidlen += READ_SIZE * 4;
05266    p->cidpos = 0;
05267    send_callerid(p);
05268    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05269    return 0;
05270 }

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

Definition at line 5129 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

Referenced by bump_gains(), dahdi_call(), my_pri_ss7_open_media(), and restore_gains().

05130 {
05131    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05132 }

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

Definition at line 5112 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().

05113 {
05114    struct dahdi_gains g;
05115    int res;
05116 
05117    memset(&g, 0, sizeof(g));
05118    res = ioctl(fd, DAHDI_GETGAINS, &g);
05119    if (res) {
05120       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05121       return res;
05122    }
05123 
05124    fill_rxgain(&g, gain, drc, law);
05125 
05126    return ioctl(fd, DAHDI_SETGAINS, &g);
05127 }

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

Definition at line 5095 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().

05096 {
05097    struct dahdi_gains g;
05098    int res;
05099 
05100    memset(&g, 0, sizeof(g));
05101    res = ioctl(fd, DAHDI_GETGAINS, &g);
05102    if (res) {
05103       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05104       return res;
05105    }
05106 
05107    fill_txgain(&g, gain, drc, law);
05108 
05109    return ioctl(fd, DAHDI_SETGAINS, &g);
05110 }

static int setup_dahdi ( int  reload  )  [static]

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

18394 {
18395    int res;
18396    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18397    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18398    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18399 
18400    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18401       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18402    } else {
18403       res = -1;
18404    }
18405    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18406    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18407    ast_cc_config_params_destroy(conf.chan.cc_params);
18408 
18409    return res;
18410 }

static int setup_dahdi_int ( int  reload,
struct dahdi_chan_conf default_conf,
struct dahdi_chan_conf base_conf,
struct dahdi_chan_conf conf 
) [static]

Definition at line 18106 of file chan_dahdi.c.

References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_config_new(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, config, CONFIG_FLAG_FILEUNCHANGED, 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_NOWARN, process_dahdi(), sig_pri_start_pri(), and ast_variable::value.

Referenced by setup_dahdi().

18107 {
18108    struct ast_config *cfg;
18109    struct ast_config *ucfg;
18110    struct ast_variable *v;
18111    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18112    const char *chans;
18113    const char *cat;
18114    int res;
18115 
18116 #ifdef HAVE_PRI
18117    char *c;
18118    int spanno;
18119    int i;
18120    int logicalspan;
18121    int trunkgroup;
18122    int dchannels[SIG_PRI_NUM_DCHANS];
18123 #endif
18124    int have_cfg_now;
18125    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18126 
18127    cfg = ast_config_load(config, config_flags);
18128    have_cfg_now = !!cfg;
18129    if (!cfg) {
18130       /* Error if we have no config file */
18131       if (had_cfg_before) {
18132          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18133          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18134       }
18135       cfg = ast_config_new();/* Dummy config */
18136       if (!cfg) {
18137          return 0;
18138       }
18139       ucfg = ast_config_load("users.conf", config_flags);
18140       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18141          ast_config_destroy(cfg);
18142          return 0;
18143       }
18144       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18145          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18146          ast_config_destroy(cfg);
18147          return 0;
18148       }
18149    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18150       ucfg = ast_config_load("users.conf", config_flags);
18151       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18152          return 0;
18153       }
18154       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18155          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18156          return 0;
18157       }
18158       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18159       cfg = ast_config_load(config, config_flags);
18160       have_cfg_now = !!cfg;
18161       if (!cfg) {
18162          if (had_cfg_before) {
18163             /* We should have been able to load the config. */
18164             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18165             ast_config_destroy(ucfg);
18166             return 0;
18167          }
18168          cfg = ast_config_new();/* Dummy config */
18169          if (!cfg) {
18170             ast_config_destroy(ucfg);
18171             return 0;
18172          }
18173       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18174          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18175          ast_config_destroy(ucfg);
18176          return 0;
18177       }
18178    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18179       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18180       return 0;
18181    } else {
18182       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18183       ucfg = ast_config_load("users.conf", config_flags);
18184       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18185          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18186          ast_config_destroy(cfg);
18187          return 0;
18188       }
18189    }
18190    had_cfg_before = have_cfg_now;
18191 
18192    /* It's a little silly to lock it, but we might as well just to be sure */
18193    ast_mutex_lock(&iflock);
18194 #ifdef HAVE_PRI
18195    if (reload != 1) {
18196       /* Process trunkgroups first */
18197       v = ast_variable_browse(cfg, "trunkgroups");
18198       while (v) {
18199          if (!strcasecmp(v->name, "trunkgroup")) {
18200             trunkgroup = atoi(v->value);
18201             if (trunkgroup > 0) {
18202                if ((c = strchr(v->value, ','))) {
18203                   i = 0;
18204                   memset(dchannels, 0, sizeof(dchannels));
18205                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18206                      dchannels[i] = atoi(c + 1);
18207                      if (dchannels[i] < 0) {
18208                         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);
18209                      } else
18210                         i++;
18211                      c = strchr(c + 1, ',');
18212                   }
18213                   if (i) {
18214                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18215                         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);
18216                   } else
18217                         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");
18218                   } else
18219                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18220                } else
18221                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18222             } else
18223                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18224          } else if (!strcasecmp(v->name, "spanmap")) {
18225             spanno = atoi(v->value);
18226             if (spanno > 0) {
18227                if ((c = strchr(v->value, ','))) {
18228                   trunkgroup = atoi(c + 1);
18229                   if (trunkgroup > 0) {
18230                      if ((c = strchr(c + 1, ',')))
18231                         logicalspan = atoi(c + 1);
18232                      else
18233                         logicalspan = 0;
18234                      if (logicalspan >= 0) {
18235                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18236                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18237                      } else
18238                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18239                      } else
18240                         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);
18241                   } else
18242                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18243                } else
18244                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18245             } else
18246                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18247          } else {
18248             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18249          }
18250          v = v->next;
18251       }
18252    }
18253 #endif
18254 
18255    /* Copy the default jb config over global_jbconf */
18256    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18257 
18258    mwimonitornotify[0] = '\0';
18259 
18260    v = ast_variable_browse(cfg, "channels");
18261    if ((res = process_dahdi(base_conf,
18262       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18263       v, reload, 0))) {
18264       ast_mutex_unlock(&iflock);
18265       ast_config_destroy(cfg);
18266       if (ucfg) {
18267          ast_config_destroy(ucfg);
18268       }
18269       return res;
18270    }
18271 
18272    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18273    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18274       /* [channels] and [trunkgroups] are used. Let's also reserve
18275        * [globals] and [general] for future use
18276        */
18277       if (!strcasecmp(cat, "general") ||
18278          !strcasecmp(cat, "trunkgroups") ||
18279          !strcasecmp(cat, "globals") ||
18280          !strcasecmp(cat, "channels")) {
18281          continue;
18282       }
18283 
18284       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18285       if (ast_strlen_zero(chans)) {
18286          /* Section is useless without a dahdichan value present. */
18287          continue;
18288       }
18289 
18290       /* Copy base_conf to conf. */
18291       deep_copy_dahdi_chan_conf(conf, base_conf);
18292 
18293       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18294          ast_mutex_unlock(&iflock);
18295          ast_config_destroy(cfg);
18296          if (ucfg) {
18297             ast_config_destroy(ucfg);
18298          }
18299          return res;
18300       }
18301    }
18302 
18303    ast_config_destroy(cfg);
18304 
18305    if (ucfg) {
18306       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18307       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18308       process_dahdi(base_conf,
18309          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18310          ast_variable_browse(ucfg, "general"), 1, 0);
18311 
18312       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18313          if (!strcasecmp(cat, "general")) {
18314             continue;
18315          }
18316 
18317          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18318          if (ast_strlen_zero(chans)) {
18319             /* Section is useless without a dahdichan value present. */
18320             continue;
18321          }
18322 
18323          /* Copy base_conf to conf. */
18324          deep_copy_dahdi_chan_conf(conf, base_conf);
18325 
18326          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18327             ast_config_destroy(ucfg);
18328             ast_mutex_unlock(&iflock);
18329             return res;
18330          }
18331       }
18332       ast_config_destroy(ucfg);
18333    }
18334    ast_mutex_unlock(&iflock);
18335 
18336 #ifdef HAVE_PRI
18337    if (reload != 1) {
18338       int x;
18339       for (x = 0; x < NUM_SPANS; x++) {
18340          if (pris[x].pri.pvts[0]) {
18341             prepare_pri(pris + x);
18342             if (sig_pri_start_pri(&pris[x].pri)) {
18343                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18344                return -1;
18345             } else
18346                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18347          }
18348       }
18349    }
18350 #endif
18351 #if defined(HAVE_SS7)
18352    if (reload != 1) {
18353       int x;
18354       for (x = 0; x < NUM_SPANS; x++) {
18355          if (linksets[x].ss7.ss7) {
18356             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18357             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18358                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18359                return -1;
18360             } else
18361                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18362          }
18363       }
18364    }
18365 #endif   /* defined(HAVE_SS7) */
18366 #ifdef HAVE_OPENR2
18367    if (reload != 1) {
18368       int x;
18369       for (x = 0; x < r2links_count; x++) {
18370          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18371             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18372             return -1;
18373          } else {
18374             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18375          }
18376       }
18377    }
18378 #endif
18379    /* And start the monitor for the first time */
18380    restart_monitor();
18381    return 0;
18382 }

static int sig_pri_tone_to_dahditone ( enum sig_pri_tone  tone  )  [static]

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

03090 {
03091    switch (tone) {
03092    case SIG_PRI_TONE_RINGTONE:
03093       return DAHDI_TONE_RINGTONE;
03094    case SIG_PRI_TONE_STUTTER:
03095       return DAHDI_TONE_STUTTER;
03096    case SIG_PRI_TONE_CONGESTION:
03097       return DAHDI_TONE_CONGESTION;
03098    case SIG_PRI_TONE_DIALTONE:
03099       return DAHDI_TONE_DIALTONE;
03100    case SIG_PRI_TONE_DIALRECALL:
03101       return DAHDI_TONE_DIALRECALL;
03102    case SIG_PRI_TONE_INFO:
03103       return DAHDI_TONE_INFO;
03104    case SIG_PRI_TONE_BUSY:
03105       return DAHDI_TONE_BUSY;
03106    default:
03107       return -1;
03108    }
03109 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 12239 of file chan_dahdi.c.

12240 {
12241    return sigtype;
12242 }

static void string_replace ( char *  str,
int  char1,
int  char2 
) [static]

Definition at line 16807 of file chan_dahdi.c.

Referenced by parse_spanchan().

16808 {
16809    for (; *str; str++) {
16810       if (*str == char1) {
16811          *str = char2;
16812       }
16813    }
16814 }

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

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

04285 {
04286    int tchan;
04287    int tinthreeway;
04288    struct ast_channel *towner;
04289 
04290    ast_debug(1, "Swapping %d and %d\n", a, b);
04291 
04292    tchan = p->subs[a].chan;
04293    towner = p->subs[a].owner;
04294    tinthreeway = p->subs[a].inthreeway;
04295 
04296    p->subs[a].chan = p->subs[b].chan;
04297    p->subs[a].owner = p->subs[b].owner;
04298    p->subs[a].inthreeway = p->subs[b].inthreeway;
04299 
04300    p->subs[b].chan = tchan;
04301    p->subs[b].owner = towner;
04302    p->subs[b].inthreeway = tinthreeway;
04303 
04304    if (p->subs[a].owner)
04305       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04306    if (p->subs[b].owner)
04307       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04308    wakeup_sub(p, a);
04309    wakeup_sub(p, b);
04310 }

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

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

04431 {
04432    if (!x) {
04433       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04434       return -1;
04435    }
04436    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04437    dahdi_close_sub(p, x);
04438    p->subs[x].linear = 0;
04439    p->subs[x].chan = 0;
04440    p->subs[x].owner = NULL;
04441    p->subs[x].inthreeway = 0;
04442    p->polarity = POLARITY_IDLE;
04443    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04444    return 0;
04445 }

static int unload_module ( void   )  [static]

Definition at line 16791 of file chan_dahdi.c.

References __unload_module(), ast_mutex_destroy, sig_ss7_linkset::lock, sig_pri_span::lock, and dahdi_pvt::pri.

16792 {
16793 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16794    int y;
16795 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16796 #ifdef HAVE_PRI
16797    for (y = 0; y < NUM_SPANS; y++)
16798       ast_mutex_destroy(&pris[y].pri.lock);
16799 #endif
16800 #if defined(HAVE_SS7)
16801    for (y = 0; y < NUM_SPANS; y++)
16802       ast_mutex_destroy(&linksets[y].ss7.lock);
16803 #endif   /* defined(HAVE_SS7) */
16804    return __unload_module();
16805 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

04843 {
04844    int needconf = 0;
04845    int x;
04846    int useslavenative;
04847    struct dahdi_pvt *slave = NULL;
04848 
04849    useslavenative = isslavenative(p, &slave);
04850    /* Start with the obvious, general stuff */
04851    for (x = 0; x < 3; x++) {
04852       /* Look for three way calls */
04853       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04854          conf_add(p, &p->subs[x], x, 0);
04855          needconf++;
04856       } else {
04857          conf_del(p, &p->subs[x], x);
04858       }
04859    }
04860    /* If we have a slave, add him to our conference now. or DAX
04861       if this is slave native */
04862    for (x = 0; x < MAX_SLAVES; x++) {
04863       if (p->slaves[x]) {
04864          if (useslavenative)
04865             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04866          else {
04867             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04868             needconf++;
04869          }
04870       }
04871    }
04872    /* If we're supposed to be in there, do so now */
04873    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04874       if (useslavenative)
04875          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04876       else {
04877          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04878          needconf++;
04879       }
04880    }
04881    /* If we have a master, add ourselves to his conference */
04882    if (p->master) {
04883       if (isslavenative(p->master, NULL)) {
04884          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04885       } else {
04886          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04887       }
04888    }
04889    if (!needconf) {
04890       /* Nobody is left (or should be left) in our conference.
04891          Kill it. */
04892       p->confno = -1;
04893    }
04894    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04895    return 0;
04896 }

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

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

03792 {
03793    dahdi_lock_sub_owner(p, a);
03794    if (p->subs[a].owner) {
03795       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03796       ast_channel_unlock(p->subs[a].owner);
03797    }
03798 }


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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", } [static]

Definition at line 18772 of file chan_dahdi.c.

int alarm

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

Referenced by mwi_send_process_buffer().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 18772 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

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

Referenced by handle_dahdi_show_cadences(), and my_set_cadence().

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

Definition at line 341 of file chan_dahdi.c.

const char* const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static]

Definition at line 5996 of file chan_dahdi.c.

struct analog_callback dahdi_analog_callbacks [static]

Definition at line 3667 of file chan_dahdi.c.

struct ast_data_handler dahdi_channels_data_provider [static]

Initial value:

Definition at line 18553 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

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

Referenced by load_module().

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 15018 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct sig_pri_callback dahdi_pri_callbacks [static]

Definition at line 3391 of file chan_dahdi.c.

Referenced by prepare_pri().

struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks [static]

Definition at line 16671 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks [static]

Definition at line 16689 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

const char dahdi_pri_cc_type[] = "DAHDI/PRI" [static]

DAHDI PRI CCSS agent and monitor type name.

Definition at line 599 of file chan_dahdi.c.

Referenced by dahdi_queryoption(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

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

openr2_transcoder_interface_t dahdi_r2_transcode_iface [static]

Initial value:

Definition at line 4277 of file chan_dahdi.c.

char* dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility" [static]

Definition at line 5926 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 5899 of file chan_dahdi.c.

struct ast_data_handler dahdi_status_data_provider [static]

Initial value:

Definition at line 18548 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Note:
Values shown here match the defaults shown in chan_dahdi.conf.sample

Definition at line 290 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 414 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 415 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 426 of file chan_dahdi.c.

int dtmfcid_level = 256 [static]

Definition at line 431 of file chan_dahdi.c.

const char* const events[] [static]

Definition at line 4557 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

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

Referenced by analog_ss_thread(), and mgcp_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 298 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 455 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 1316 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 1315 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Protect the interface list (of dahdi_pvt's).

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

Referenced by dahdi_show_status(), and dahdi_status_data_provider_get().

int matchdigittimeout = 3000 [static]

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

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

Referenced by __sip_reliable_xmit(), __unload_module(), restart_monitor(), and unload_module().

ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [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 463 of file chan_dahdi.c.

Referenced by __unload_module(), do_monitor(), restart_monitor(), and unload_module().

int mwilevel = 512 [static]

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

Referenced by notify_message(), and setup_dahdi_int().

char* name

Definition at line 4581 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 384 of file chan_dahdi.c.

Referenced by handle_dahdi_show_cadences(), and my_set_cadence().

int num_restart_pending = 0 [static]

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

int pridebugfd = -1 [static]

Definition at line 438 of file chan_dahdi.c.

Referenced by handle_pri_set_debug_file().

ast_mutex_t pridebugfdlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 458 of file chan_dahdi.c.

Referenced by handle_pri_set_debug_file().

char pridebugfilename[1024] = "" [static]

Definition at line 439 of file chan_dahdi.c.

Referenced by handle_pri_set_debug_file().

struct dahdi_pri pris[NUM_SPANS] [static]

Definition at line 595 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_channels(), 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 423 of file chan_dahdi.c.

Referenced by dahdi_new().

struct dahdi_mfcr2** r2links [static]

Definition at line 580 of file chan_dahdi.c.

Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().

int r2links_count = 0 [static]

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

Referenced by handle_alarms(), and handle_clear_alarms().

ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

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

struct dahdi_pvt* round_robin[32] [static]

Round robin search locations.

Definition at line 3738 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 468 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 471 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

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

Referenced by alloc_sub(), dahdi_bridge(), and dahdi_new().

const char tdesc[] [static]

Definition at line 320 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 425 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 385 of file chan_dahdi.c.


Generated on Mon Oct 8 12:39:13 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7