Mon Jun 27 16:51:04 2011

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <math.h>
#include <ctype.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include "sig_analog.h"
#include "sig_pri.h"
#include <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 check_for_conference (struct dahdi_pvt *p)
static char * complete_span_4 (const char *line, const char *word, int pos, int state)
static char * complete_span_helper (const char *line, const char *word, int pos, int state, int rpos)
static int conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
static struct ast_strcreate_channel_name (struct dahdi_pvt *i, int is_outgoing, char *address)
static int dahdi_accept_r2_call_exec (struct ast_channel *chan, const char *data)
static int dahdi_answer (struct ast_channel *ast)
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause (int cause)
static enum ast_bridge_result dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int dahdi_call (struct ast_channel *ast, char *rdest, int timeout)
static int dahdi_callwait (struct ast_channel *ast)
static int dahdi_cc_callback (struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
 Callback made when dial failed to get a channel out of dahdi_request().
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static int dahdi_channels_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_close (int fd)
static void dahdi_close_pri_fd (struct dahdi_pri *pri, int fd_num)
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
static char * dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_destroy_channel_bynum (int channel)
static int dahdi_devicestate (void *data)
static int dahdi_digit_begin (struct ast_channel *ast, char digit)
static int dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void dahdi_disable_ec (struct dahdi_pvt *p)
static int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
static void dahdi_enable_ec (struct dahdi_pvt *p)
static struct ast_framedahdi_exception (struct ast_channel *ast)
static int dahdi_fake_event (struct dahdi_pvt *p, int mode)
static int dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int dahdi_func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
static int dahdi_func_write (struct ast_channel *chan, const char *function, char *data, const char *value)
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events.
static void dahdi_handle_dtmf (struct ast_channel *ast, int idx, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
static void dahdi_iflist_extract (struct dahdi_pvt *pvt)
static void dahdi_iflist_insert (struct dahdi_pvt *pvt)
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
static void dahdi_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx)
static struct ast_channeldahdi_new (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
static int dahdi_new_pri_nobch_channel (struct sig_pri_span *pri)
static void dahdi_nobch_extract (struct sig_pri_span *pri, struct dahdi_pvt *pvt)
static void dahdi_nobch_insert (struct sig_pri_span *pri, struct dahdi_pvt *pvt)
static int dahdi_open (char *fn)
static void dahdi_pri_error (struct pri *pri, char *s)
static void dahdi_pri_message (struct pri *pri, char *s)
static void dahdi_pri_update_span_devstate (struct sig_pri_span *pri)
static int dahdi_queryoption (struct ast_channel *chan, int option, void *data, int *datalen)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f)
static int16_t dahdi_r2_alaw_to_linear (uint8_t sample)
static int dahdi_r2_answer (struct dahdi_pvt *p)
static int dahdi_r2_cause_to_ast_cause (openr2_call_disconnect_cause_t cause)
static void dahdi_r2_destroy_links (void)
static void dahdi_r2_disconnect_call (struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
static openr2_calling_party_category_t dahdi_r2_get_channel_category (struct ast_channel *c)
static struct dahdi_mfcr2dahdi_r2_get_link (void)
static uint8_t dahdi_r2_linear_to_alaw (int sample)
static void dahdi_r2_on_ani_digit_received (openr2_chan_t *r2chan, char digit)
static void dahdi_r2_on_billing_pulse_received (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_accepted (openr2_chan_t *r2chan, openr2_call_mode_t mode)
static void dahdi_r2_on_call_answered (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_disconnect (openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
static void dahdi_r2_on_call_end (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_init (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_offered (openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
static void dahdi_r2_on_call_read (openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
static void dahdi_r2_on_chan_log (openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
static void dahdi_r2_on_context_log (openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
static int dahdi_r2_on_dnis_digit_received (openr2_chan_t *r2chan, char digit)
static void dahdi_r2_on_hardware_alarm (openr2_chan_t *r2chan, int alarm)
static void dahdi_r2_on_line_blocked (openr2_chan_t *r2chan)
static void dahdi_r2_on_line_idle (openr2_chan_t *r2chan)
static void dahdi_r2_on_os_error (openr2_chan_t *r2chan, int errorcode)
static void dahdi_r2_on_protocol_error (openr2_chan_t *r2chan, openr2_protocol_error_t reason)
static int dahdi_r2_set_context (struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
static void dahdi_r2_write_log (openr2_log_level_t level, char *logmessage)
static struct ast_framedahdi_read (struct ast_channel *ast)
static struct ast_channeldahdi_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static int dahdi_restart (void)
static char * dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_ring_phone (struct dahdi_pvt *p)
static int dahdi_send_callrerouting_facility_exec (struct ast_channel *chan, const char *data)
static int dahdi_send_keypad_facility_exec (struct ast_channel *chan, const char *digits)
static int dahdi_sendtext (struct ast_channel *c, const char *text)
static char * dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_set_hook (int fd, int hs)
static char * dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_setlaw (int dfd, int law)
static int dahdi_setlinear (int dfd, int linear)
static int dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen)
static char * dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_sig2str (int sig)
static int dahdi_sig_pri_lib_handles (int signaling)
static void dahdi_softhangup_all (void)
static 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_next_iface_in_span (struct dahdi_pvt *cur)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alms)
static void handle_clear_alarms (struct dahdi_pvt *p)
static char * handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
static char * handle_mfcr2_call_files (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_blocked (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_idle (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_show_variants (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_disable_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_enable_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_generic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
static char * handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static 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_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 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_fixup_chans (void *chan_old, void *chan_new)
static void my_pri_make_cc_dialstring (void *priv, char *buf, size_t buf_size)
static void my_pri_open_media (void *p)
static int my_pri_play_tone (void *pvt, enum sig_pri_tone tone)
static int my_ring (void *pvt)
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
static void my_set_alarm (void *pvt, int in_alarm)
static void my_set_cadence (void *pvt, int *cidrings, struct ast_channel *ast)
static void my_set_callerid (void *pvt, const struct ast_party_caller *caller)
static void my_set_callwaiting (void *pvt, int callwaiting_enable)
static void my_set_confirmanswer (void *pvt, int flag)
static void my_set_dialing (void *pvt, int is_dialing)
static void my_set_digital (void *pvt, int is_digital)
static void my_set_dnid (void *pvt, const char *dnid)
static int my_set_echocanceller (void *pvt, int enable)
static void my_set_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_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", }
struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "chan_dahdi.conf"
static const char *const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call"
static struct analog_callback dahdi_analog_callbacks
static struct ast_data_handler dahdi_channels_data_provider
static struct ast_cli_entry dahdi_cli []
static struct ast_data_entry dahdi_data_providers []
static struct ast_cli_entry dahdi_mfcr2_cli []
static struct sig_pri_callback dahdi_pri_callbacks
static struct ast_cli_entry dahdi_pri_cli []
static struct dahdi_parms_pseudo dahdi_pseudo_parms
static openr2_event_interface_t dahdi_r2_event_iface
static openr2_transcoder_interface_t dahdi_r2_transcode_iface
static char * dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility"
static char * dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility"
static struct 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 char parkinglot [AST_MAX_EXTENSION] = ""
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 293 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 360 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmf(), and my_handle_dtmf().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 359 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 358 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_PROGRESS   1

Definition at line 357 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

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

10,000 ms

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

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

100 ms

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

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

#define CHAN_PSEUDO   -2

Definition at line 355 of file chan_dahdi.c.

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

#define CHAN_TAG   "Chan "

Referenced by dahdi_r2_on_chan_log().

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

500 ms

Definition at line 499 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 633 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

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

#define DEFAULT_CIDRINGS   1

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

Definition at line 291 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 501 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

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

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

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

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

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

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

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

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

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

Definition at line 1518 of file chan_dahdi.c.

Referenced by my_complete_conference_update().

#define HANGUP   1

Definition at line 15431 of file chan_dahdi.c.

Referenced by action_transferhangup(), and dahdi_fake_event().

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

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

#define HEADER_MS   50

Referenced by dahdi_sendtext().

#define ISTRUNK (  ) 

Value:

((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
         (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))

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

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_dahdi().

#define MAX_SLAVES   4

Definition at line 636 of file chan_dahdi.c.

Referenced by isslavenative(), and my_complete_conference_update().

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

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

Referenced by analog_ss_thread(), and dahdi_new().

#define NUM_CADENCE_MAX   25

Definition at line 362 of file chan_dahdi.c.

#define NUM_SPANS   32

Definition at line 352 of file chan_dahdi.c.

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

#define POLARITY_IDLE   0

Definition at line 593 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 594 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 16444 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 16446 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

#define R2_LINK_CAPACITY   10

Definition at line 11795 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 491 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 414 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

#define REPORT_SPAN_ALARMS   2

Definition at line 415 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

#define sig2str   dahdi_sig2str

Definition at line 4526 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 338 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 339 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 327 of file chan_dahdi.c.

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

#define SIG_EM   DAHDI_SIG_EM

Definition at line 322 of file chan_dahdi.c.

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

#define SIG_EM_E1   DAHDI_SIG_EM_E1

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_EMWINK   (0x0100000 | DAHDI_SIG_EM)

Definition at line 323 of file chan_dahdi.c.

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

#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)

Definition at line 326 of file chan_dahdi.c.

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

#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)

Definition at line 324 of file chan_dahdi.c.

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

#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)

Definition at line 325 of file chan_dahdi.c.

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

#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)

Definition at line 328 of file chan_dahdi.c.

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

#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)

Definition at line 329 of file chan_dahdi.c.

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

#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)

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

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

#define SIG_FXOKS   DAHDI_SIG_FXOKS

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

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

#define SIG_FXSGS   DAHDI_SIG_FXSGS

Definition at line 332 of file chan_dahdi.c.

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

#define SIG_FXSKS   DAHDI_SIG_FXSKS

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

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

#define SIG_MFCR2   DAHDI_SIG_CAS

Definition at line 341 of file chan_dahdi.c.

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

#define SIG_MFCR2_MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 83 of file chan_dahdi.c.

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 337 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 1520 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 342 of file chan_dahdi.c.

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

#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)

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_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)

Definition at line 344 of file chan_dahdi.c.

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

#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)

Definition at line 345 of file chan_dahdi.c.

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

#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)

Definition at line 343 of file chan_dahdi.c.

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

#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)

Definition at line 340 of file chan_dahdi.c.

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

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 255 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 589 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 588 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_fixup_chans(), my_pri_open_media(), my_pri_play_tone(), 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 590 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 15430 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 657 of file chan_dahdi.c.

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

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

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


Function Documentation

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

Definition at line 8513 of file chan_dahdi.c.

References ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

Referenced by dahdi_exception(), and dahdi_read().

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

static void __reg_module ( void   )  [static]

Definition at line 18188 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

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

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

static void __unreg_module ( void   )  [static]

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

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

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

Definition at line 15539 of file chan_dahdi.c.

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

Referenced by load_module().

15540 {
15541    struct dahdi_pvt *p = NULL;
15542    const char *channel = astman_get_header(m, "DAHDIChannel");
15543    const char *number = astman_get_header(m, "Number");
15544    int i;
15545 
15546    if (ast_strlen_zero(channel)) {
15547       astman_send_error(s, m, "No channel specified");
15548       return 0;
15549    }
15550    if (ast_strlen_zero(number)) {
15551       astman_send_error(s, m, "No number specified");
15552       return 0;
15553    }
15554    p = find_channel(atoi(channel));
15555    if (!p) {
15556       astman_send_error(s, m, "No such channel");
15557       return 0;
15558    }
15559    if (!p->owner) {
15560       astman_send_error(s, m, "Channel does not have it's owner");
15561       return 0;
15562    }
15563    for (i = 0; i < strlen(number); i++) {
15564       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15565       dahdi_queue_frame(p, &f);
15566    }
15567    astman_send_ack(s, m, "DAHDIDialOffhook");
15568    return 0;
15569 }

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

Definition at line 15482 of file chan_dahdi.c.

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

Referenced by load_module().

15483 {
15484    struct dahdi_pvt *p = NULL;
15485    const char *channel = astman_get_header(m, "DAHDIChannel");
15486 
15487    if (ast_strlen_zero(channel)) {
15488       astman_send_error(s, m, "No channel specified");
15489       return 0;
15490    }
15491    p = find_channel(atoi(channel));
15492    if (!p) {
15493       astman_send_error(s, m, "No such channel");
15494       return 0;
15495    }
15496    dahdi_dnd(p, 0);
15497    astman_send_ack(s, m, "DND Disabled");
15498    return 0;
15499 }

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

Definition at line 15463 of file chan_dahdi.c.

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

Referenced by load_module().

15464 {
15465    struct dahdi_pvt *p = NULL;
15466    const char *channel = astman_get_header(m, "DAHDIChannel");
15467 
15468    if (ast_strlen_zero(channel)) {
15469       astman_send_error(s, m, "No channel specified");
15470       return 0;
15471    }
15472    p = find_channel(atoi(channel));
15473    if (!p) {
15474       astman_send_error(s, m, "No such channel");
15475       return 0;
15476    }
15477    dahdi_dnd(p, 1);
15478    astman_send_ack(s, m, "DND Enabled");
15479    return 0;
15480 }

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

Definition at line 14771 of file chan_dahdi.c.

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

Referenced by load_module().

14772 {
14773    if (dahdi_restart() != 0) {
14774       astman_send_error(s, m, "Failed rereading DAHDI configuration");
14775       return 1;
14776    }
14777    astman_send_ack(s, m, "DAHDIRestart: Success");
14778    return 0;
14779 }

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

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

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

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

Definition at line 15501 of file chan_dahdi.c.

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

Referenced by load_module().

15502 {
15503    struct dahdi_pvt *p = NULL;
15504    const char *channel = astman_get_header(m, "DAHDIChannel");
15505 
15506    if (ast_strlen_zero(channel)) {
15507       astman_send_error(s, m, "No channel specified");
15508       return 0;
15509    }
15510    p = find_channel(atoi(channel));
15511    if (!p) {
15512       astman_send_error(s, m, "No such channel");
15513       return 0;
15514    }
15515    dahdi_fake_event(p,TRANSFER);
15516    astman_send_ack(s, m, "DAHDITransfer");
15517    return 0;
15518 }

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

Definition at line 15520 of file chan_dahdi.c.

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

Referenced by load_module().

15521 {
15522    struct dahdi_pvt *p = NULL;
15523    const char *channel = astman_get_header(m, "DAHDIChannel");
15524 
15525    if (ast_strlen_zero(channel)) {
15526       astman_send_error(s, m, "No channel specified");
15527       return 0;
15528    }
15529    p = find_channel(atoi(channel));
15530    if (!p) {
15531       astman_send_error(s, m, "No such channel");
15532       return 0;
15533    }
15534    dahdi_fake_event(p,HANGUP);
15535    astman_send_ack(s, m, "DAHDIHangup");
15536    return 0;
15537 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4443 of file chan_dahdi.c.

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

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

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

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

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

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

Definition at line 4528 of file chan_dahdi.c.

References SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

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

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

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

Definition at line 9576 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_clear_flag, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FRAME_DTMF, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parking_ext_valid(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), bump_gains(), dahdi_pvt::call_forward, ast_channel::caller, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_pvt::cs, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, 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().

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

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

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

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

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

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

AST_DATA_STRUCTURE ( dahdi_pvt  ,
DATA_EXPORT_DAHDI_PVT   
)

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

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

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

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 10701 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by mwi_thread().

10702 {
10703    int x;
10704    int sum = 0;
10705 
10706    if (!len)
10707       return 0;
10708 
10709    for (x = 0; x < len; x++)
10710       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10711 
10712    return sum / len;
10713 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 13856 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

13857 {
13858    return complete_span_helper(line,word,pos,state,3);
13859 }

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

Definition at line 13835 of file chan_dahdi.c.

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

Referenced by complete_span_4().

13836 {
13837    int which, span;
13838    char *ret = NULL;
13839 
13840    if (pos != rpos)
13841       return ret;
13842 
13843    for (which = span = 0; span < NUM_SPANS; span++) {
13844       if (pris[span].pri.pri && ++which > state) {
13845          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
13846             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13847          }
13848          break;
13849       }
13850    }
13851    return ret;
13852 }

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

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

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

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

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

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

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

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

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

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

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

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

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

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

static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause ( int  cause  )  [static]

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

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

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

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

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

Definition at line 5219 of file chan_dahdi.c.

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

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

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

17908 {
17909    struct dahdi_pvt *tmp;
17910    struct ast_data *data_channel;
17911 
17912    ast_mutex_lock(&iflock);
17913    for (tmp = iflist; tmp; tmp = tmp->next) {
17914       data_channel = ast_data_add_node(data_root, "channel");
17915       if (!data_channel) {
17916          continue;
17917       }
17918 
17919       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
17920 
17921       /* if this channel doesn't match remove it. */
17922       if (!ast_data_search_match(search, data_channel)) {
17923          ast_data_remove_node(data_root, data_channel);
17924       }
17925    }
17926    ast_mutex_unlock(&iflock);
17927 
17928    return 0;
17929 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4213 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().

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

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

Definition at line 4226 of file chan_dahdi.c.

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

Referenced by __unload_module(), and prepare_pri().

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

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

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

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

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

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

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

static char* dahdi_destroy_channel ( 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, 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.

14587 {
14588    int channel;
14589    int ret;
14590    switch (cmd) {
14591    case CLI_INIT:
14592       e->command = "dahdi destroy channel";
14593       e->usage =
14594          "Usage: dahdi destroy channel <chan num>\n"
14595          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14596       return NULL;
14597    case CLI_GENERATE:
14598       return NULL;
14599    }
14600    if (a->argc != 4)
14601       return CLI_SHOWUSAGE;
14602 
14603    channel = atoi(a->argv[3]);
14604    ret = dahdi_destroy_channel_bynum(channel);
14605    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14606 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

11056 {
11057    struct dahdi_pvt *cur;
11058 
11059    ast_mutex_lock(&iflock);
11060    for (cur = iflist; cur; cur = cur->next) {
11061       if (cur->channel == channel) {
11062          int x = DAHDI_FLASH;
11063 
11064          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11065          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11066 
11067          destroy_channel(cur, 1);
11068          ast_mutex_unlock(&iflock);
11069          ast_module_unref(ast_module_info->self);
11070          return RESULT_SUCCESS;
11071       }
11072    }
11073    ast_mutex_unlock(&iflock);
11074    return RESULT_FAILURE;
11075 }

static int dahdi_devicestate ( void *  data  )  [static]

Definition at line 13424 of file chan_dahdi.c.

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

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

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

Definition at line 4317 of file chan_dahdi.c.

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

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

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

Definition at line 4371 of file chan_dahdi.c.

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

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

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

09554 {
09555    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09556       return analog_dnd(dahdichan->sig_pvt, flag);
09557    }
09558 
09559    if (flag == -1) {
09560       return dahdichan->dnd;
09561    }
09562 
09563    /* Do not disturb */
09564    dahdichan->dnd = flag;
09565    ast_verb(3, "%s DND on channel %d\n",
09566          flag? "Enabled" : "Disabled",
09567          dahdichan->channel);
09568    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09569          "Channel: DAHDI/%d\r\n"
09570          "Status: %s\r\n", dahdichan->channel,
09571          flag? "enabled" : "disabled");
09572 
09573    return 0;
09574 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

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

15434 {
15435    if (p) {
15436       switch (mode) {
15437       case TRANSFER:
15438          p->fake_event = DAHDI_EVENT_WINKFLASH;
15439          break;
15440       case HANGUP:
15441          p->fake_event = DAHDI_EVENT_ONHOOK;
15442          break;
15443       default:
15444          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15445       }
15446    }
15447    return 0;
15448 }

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

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

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

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

Definition at line 6752 of file chan_dahdi.c.

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

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

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

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

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

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

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

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

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

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

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

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

Definition at line 7645 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), analog_ss_thread(), ast_party_caller::ani, ast_party_caller::ani2, dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), ast_channel::caller, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), dahdi_pvt::cid_name, cid_name, dahdi_pvt::cid_num, cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_handle_dtmf(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_sig_pri_lib_handles(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), ast_party_caller::id, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_party_id::name, ast_channel::name, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_party_id::number, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, sig_pri_span::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, sig_pri_span::pri, dahdi_pvt::pri, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI_CALL_LEVEL_PROCEEDING, sig_pri_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), ast_frame::src, ast_party_name::str, ast_party_number::str, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), update_conf(), ast_party_name::valid, ast_party_number::valid, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

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

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

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

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

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

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

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

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

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

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

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

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

Definition at line 6975 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

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

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

Definition at line 3635 of file chan_dahdi.c.

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

Referenced by wakeup_sub().

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

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

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

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

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

static int dahdi_new_pri_nobch_channel ( struct sig_pri_span pri  )  [static]

Definition at line 12938 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4166 of file chan_dahdi.c.

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

Referenced by alloc_sub(), and duplicate_pseudo().

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

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

Definition at line 13734 of file chan_dahdi.c.

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

Referenced by load_module().

13735 {
13736    int x, y;
13737    int dchan = -1, span = -1;
13738    int dchancount = 0;
13739 
13740    if (pri) {
13741       for (x = 0; x < NUM_SPANS; x++) {
13742          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13743             if (pris[x].pri.dchans[y])
13744                dchancount++;
13745 
13746             if (pris[x].pri.dchans[y] == pri)
13747                dchan = y;
13748          }
13749          if (dchan >= 0) {
13750             span = x;
13751             break;
13752          }
13753          dchancount = 0;
13754       }
13755       if ((dchancount > 1) && (span > -1))
13756          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
13757       else if (span > -1)
13758          ast_log(LOG_ERROR, "%d %s", span+1, s);
13759       else
13760          ast_log(LOG_ERROR, "%s", s);
13761    } else
13762       ast_log(LOG_ERROR, "%s", s);
13763 
13764    ast_mutex_lock(&pridebugfdlock);
13765 
13766    if (pridebugfd >= 0) {
13767       if (write(pridebugfd, s, strlen(s)) < 0) {
13768          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13769       }
13770    }
13771 
13772    ast_mutex_unlock(&pridebugfdlock);
13773 }

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

Definition at line 13692 of file chan_dahdi.c.

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

Referenced by load_module().

13693 {
13694    int x, y;
13695    int dchan = -1, span = -1, dchancount = 0;
13696 
13697    if (pri) {
13698       for (x = 0; x < NUM_SPANS; x++) {
13699          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13700             if (pris[x].pri.dchans[y])
13701                dchancount++;
13702 
13703             if (pris[x].pri.dchans[y] == pri)
13704                dchan = y;
13705          }
13706          if (dchan >= 0) {
13707             span = x;
13708             break;
13709          }
13710          dchancount = 0;
13711       }
13712       if (dchancount > 1 && (span > -1))
13713          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
13714       else if (span > -1)
13715          ast_verbose("%d %s", span+1, s);
13716       else
13717          ast_verbose("%s", s);
13718    } else
13719       ast_verbose("%s", s);
13720 
13721    ast_mutex_lock(&pridebugfdlock);
13722 
13723    if (pridebugfd >= 0) {
13724       if (write(pridebugfd, s, strlen(s)) < 0) {
13725          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13726       }
13727    }
13728 
13729    ast_mutex_unlock(&pridebugfdlock);
13730 }

static void dahdi_pri_update_span_devstate ( struct sig_pri_span pri  )  [static]

Definition at line 3174 of file chan_dahdi.c.

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

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

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

Definition at line 6492 of file chan_dahdi.c.

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

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

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

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

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

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

Definition at line 4121 of file chan_dahdi.c.

References AST_ALAW.

04122 {
04123    return AST_ALAW(sample);
04124 }

static int dahdi_r2_answer ( struct dahdi_pvt p  )  [static]

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

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

static int dahdi_r2_cause_to_ast_cause ( openr2_call_disconnect_cause_t  cause  )  [static]

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

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

static void dahdi_r2_destroy_links ( void   )  [static]

Definition at line 11776 of file chan_dahdi.c.

References ast_free, AST_PTHREADT_NULL, r2links, and r2links_count.

Referenced by __unload_module(), and dahdi_restart().

11777 {
11778    int i = 0;
11779    if (!r2links) {
11780       return;
11781    }
11782    for (; i < r2links_count; i++) {
11783       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11784          pthread_cancel(r2links[i]->r2master);
11785          pthread_join(r2links[i]->r2master, NULL);
11786          openr2_context_delete(r2links[i]->protocol_context);
11787       }
11788       ast_free(r2links[i]);
11789    }
11790    ast_free(r2links);
11791    r2links = NULL;
11792    r2links_count = 0;
11793 }

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

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

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

static openr2_calling_party_category_t dahdi_r2_get_channel_category ( struct ast_channel c  )  [static]

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

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

static struct dahdi_mfcr2* dahdi_r2_get_link ( void   )  [static]

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

11797 {
11798    struct dahdi_mfcr2 *new_r2link = NULL;
11799    struct dahdi_mfcr2 **new_r2links = NULL;
11800    /* this function is called just when starting up and no monitor threads have been launched,
11801       no need to lock monitored_count member */
11802    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
11803       new_r2link = ast_calloc(1, sizeof(**r2links));
11804       if (!new_r2link) {
11805          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11806          return NULL;
11807       }
11808       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
11809       if (!new_r2links) {
11810          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11811          ast_free(new_r2link);
11812          return NULL;
11813       }
11814       r2links = new_r2links;
11815       new_r2link->r2master = AST_PTHREADT_NULL;
11816       r2links[r2links_count] = new_r2link;
11817       r2links_count++;
11818       ast_log(LOG_DEBUG, "Created new R2 link!\n");
11819    }
11820    return r2links[r2links_count - 1];
11821 }

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

Definition at line 4126 of file chan_dahdi.c.

References AST_LIN2A.

04127 {
04128    return AST_LIN2A(sample);
04129 }

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

Definition at line 4085 of file chan_dahdi.c.

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

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

static void dahdi_r2_on_billing_pulse_received ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4095 of file chan_dahdi.c.

References ast_verbose.

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

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

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

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

static void dahdi_r2_on_call_answered ( openr2_chan_t *  r2chan  )  [static]

Definition at line 3919 of file chan_dahdi.c.

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

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

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

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

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

static void dahdi_r2_on_call_end ( openr2_chan_t *  r2chan  )  [static]

Definition at line 3867 of file chan_dahdi.c.

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

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

static void dahdi_r2_on_call_init ( openr2_chan_t *  r2chan  )  [static]

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

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

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

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

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

Definition at line 3926 of file chan_dahdi.c.

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

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

References CHAN_TAG, and dahdi_r2_write_log().

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

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

References CONTEXT_TAG, and dahdi_r2_write_log().

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

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

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

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

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

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

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

static void dahdi_r2_on_line_blocked ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4020 of file chan_dahdi.c.

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

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

static void dahdi_r2_on_line_idle ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4029 of file chan_dahdi.c.

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

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

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

Definition at line 3781 of file chan_dahdi.c.

References ast_log(), and LOG_ERROR.

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

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

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

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

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

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

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

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

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

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

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

Definition at line 8641 of file chan_dahdi.c.

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

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

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

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

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

static int dahdi_restart ( void   )  [static]

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

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

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

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

14749 {
14750    switch (cmd) {
14751    case CLI_INIT:
14752       e->command = "dahdi restart";
14753       e->usage =
14754          "Usage: dahdi restart\n"
14755          "  Restarts the DAHDI channels: destroys them all and then\n"
14756          "  re-reads them from chan_dahdi.conf.\n"
14757          "  Note that this will STOP any running CALL on DAHDI channels.\n"
14758          "";
14759       return NULL;
14760    case CLI_GENERATE:
14761       return NULL;
14762    }
14763    if (a->argc != 2)
14764       return CLI_SHOWUSAGE;
14765 
14766    if (dahdi_restart() != 0)
14767       return CLI_FAILURE;
14768    return CLI_SUCCESS;
14769 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 5779 of file chan_dahdi.c.

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

Referenced by load_module().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2486 of file chan_dahdi.c.

Referenced by my_new_pri_ast_channel(), and my_pri_open_media().

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

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

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

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

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

Definition at line 6533 of file chan_dahdi.c.

References ast_check_hangup(), ast_debug, ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_DIGIT_DETECT, AST_OPTION_ECHOCAN, AST_OPTION_FAX_DETECT, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, disable_dtmf_detect(), dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::dtmfrelax, enable_dtmf_detect(), errno, dahdi_pvt::law, len(), LOG_NOTICE, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, pp, READ_SIZE, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_channel_tech::type.

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

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

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

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

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

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

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

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

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

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

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

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

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

static char* dahdi_sig2str ( int  sig  )  [static]

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

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

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

Definition at line 1534 of file chan_dahdi.c.

References SIG_PRI_LIB_HANDLE_CASES.

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

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

static void dahdi_softhangup_all ( void   )  [static]

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

14609 {
14610    struct dahdi_pvt *p;
14611 retry:
14612    ast_mutex_lock(&iflock);
14613    for (p = iflist; p; p = p->next) {
14614       ast_mutex_lock(&p->lock);
14615       if (p->owner && !p->restartpending) {
14616          if (ast_channel_trylock(p->owner)) {
14617             if (option_debug > 2)
14618                ast_verbose("Avoiding deadlock\n");
14619             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14620             ast_mutex_unlock(&p->lock);
14621             ast_mutex_unlock(&iflock);
14622             goto retry;
14623          }
14624          if (option_debug > 2)
14625             ast_verbose("Softhanging up on %s\n", p->owner->name);
14626          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14627          p->restartpending = 1;
14628          num_restart_pending++;
14629          ast_channel_unlock(p->owner);
14630       }
14631       ast_mutex_unlock(&p->lock);
14632    }
14633    ast_mutex_unlock(&iflock);
14634 }

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

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

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

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

static void dahdi_unlink_pri_pvt ( struct dahdi_pvt pvt  )  [static]

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

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

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

Definition at line 17938 of file chan_dahdi.c.

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

17940 {
17941    int pseudo_fd = -1;
17942    struct dahdi_versioninfo vi = {
17943       .version = "Unknown",
17944       .echo_canceller = "Unknown"
17945    };
17946 
17947    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
17948       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
17949       return -1;
17950    }
17951 
17952    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
17953       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
17954    }
17955 
17956    close(pseudo_fd);
17957 
17958    ast_data_add_str(data_root, "value", vi.version);
17959    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
17960 
17961    return 0;
17962 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 479 of file chan_dahdi.c.

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

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

Definition at line 9526 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), and my_wink().

09527 {
09528    int j;
09529    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09530    for (;;)
09531    {
09532       /* set bits of interest */
09533       j = DAHDI_IOMUX_SIGEVENT;
09534       /* wait for some happening */
09535       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09536       /* exit loop if we have it */
09537       if (j & DAHDI_IOMUX_SIGEVENT) break;
09538    }
09539    /* get the event info */
09540    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09541    return 0;
09542 }

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

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

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

static enum analog_event dahdievent_to_analogevent ( int  event  )  [static]

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

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

static enum analog_sigtype dahdisig_to_analogsig ( int  sig  )  [static]

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

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

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

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

17546 {
17547    struct ast_cc_config_params *cc_params;
17548 
17549    cc_params = dest->chan.cc_params;
17550    *dest = *src;
17551    dest->chan.cc_params = cc_params;
17552    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17553 }

static void destroy_all_channels ( void   )  [static]

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

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

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

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

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

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

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

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

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

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

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

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

Definition at line 11894 of file chan_dahdi.c.

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

Referenced by build_channels().

11895 {
11896    struct stat stbuf;
11897    int      num;
11898 
11899    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
11900    if (stat(path, &stbuf) < 0) {
11901       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
11902       return -errno;
11903    }
11904    if (!S_ISCHR(stbuf.st_mode)) {
11905       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
11906       return -EINVAL;
11907    }
11908    num = minor(stbuf.st_rdev);
11909    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
11910    return num;
11911 
11912 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 4301 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

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

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 4840 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

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

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

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

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

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 4904 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

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

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

Definition at line 4860 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

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

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

Definition at line 15449 of file chan_dahdi.c.

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

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

15450 {
15451    struct dahdi_pvt *p;
15452 
15453    ast_mutex_lock(&iflock);
15454    for (p = iflist; p; p = p->next) {
15455       if (p->channel == channel) {
15456          break;
15457       }
15458    }
15459    ast_mutex_unlock(&iflock);
15460    return p;
15461 }

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

Definition at line 5588 of file chan_dahdi.c.

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

Referenced by destroy_dahdi_pvt().

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

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

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

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

Definition at line 7624 of file chan_dahdi.c.

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

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

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

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3676 of file chan_dahdi.c.

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

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

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

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

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

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

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

Definition at line 11077 of file chan_dahdi.c.

References analog_ss_thread(), ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, restore_conference(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, sig_pri_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), SUB_REAL, and dahdi_pvt::subs.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

14256 {
14257    switch (cmd) {
14258    case CLI_INIT:
14259       e->command = "mfcr2 show version";
14260       e->usage =
14261          "Usage: mfcr2 show version\n"
14262          "       Shows the version of the OpenR2 library being used.\n";
14263       return NULL;
14264    case CLI_GENERATE:
14265       return NULL;
14266    }
14267    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14268    return CLI_SUCCESS;
14269 }

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

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

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

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

Definition at line 14096 of file chan_dahdi.c.

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

14097 {
14098    switch (cmd) {
14099    case CLI_INIT:
14100       e->command = "pri service disable channel";
14101       e->usage =
14102          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14103          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14104          "  to remove a channel from service, with optional interface id\n"
14105          "  as agreed upon with remote switch operator\n";
14106       return NULL;
14107    case CLI_GENERATE:
14108       return NULL;
14109    }
14110    return handle_pri_service_generic(e, cmd, a, 2);
14111 }

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

Definition at line 14079 of file chan_dahdi.c.

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

14080 {
14081    switch (cmd) {
14082    case CLI_INIT:
14083       e->command = "pri service enable channel";
14084       e->usage =
14085          "Usage: pri service enable channel <channel> [<interface id>]\n"
14086          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14087          "  to restore a channel to service, with optional interface id\n"
14088          "  as agreed upon with remote switch operator\n";
14089       return NULL;
14090    case CLI_GENERATE:
14091       return NULL;
14092    }
14093    return handle_pri_service_generic(e, cmd, a, 0);
14094 }

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

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

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

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

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

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

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

Definition at line 14177 of file chan_dahdi.c.

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

14178 {
14179    int x;
14180    int span;
14181    int count=0;
14182    int debug;
14183 
14184    switch (cmd) {
14185    case CLI_INIT:
14186       e->command = "pri show debug";
14187       e->usage =
14188          "Usage: pri show debug\n"
14189          "  Show the debug state of pri spans\n";
14190       return NULL;
14191    case CLI_GENERATE:
14192       return NULL;
14193    }
14194 
14195    for (span = 0; span < NUM_SPANS; span++) {
14196       if (pris[span].pri.pri) {
14197          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14198             if (pris[span].pri.dchans[x]) {
14199                debug = pri_get_debug(pris[span].pri.dchans[x]);
14200                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" );
14201                count++;
14202             }
14203          }
14204       }
14205 
14206    }
14207    ast_mutex_lock(&pridebugfdlock);
14208    if (pridebugfd >= 0)
14209       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14210    ast_mutex_unlock(&pridebugfdlock);
14211 
14212    if (!count)
14213       ast_cli(a->fd, "No PRI running\n");
14214    return CLI_SUCCESS;
14215 }

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

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

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

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

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

14116 {
14117    int span;
14118 
14119    switch (cmd) {
14120    case CLI_INIT:
14121       e->command = "pri show spans";
14122       e->usage =
14123          "Usage: pri show spans\n"
14124          "       Displays PRI Information\n";
14125       return NULL;
14126    case CLI_GENERATE:
14127       return NULL;
14128    }
14129 
14130    if (a->argc != 3)
14131       return CLI_SHOWUSAGE;
14132 
14133    for (span = 0; span < NUM_SPANS; span++) {
14134       if (pris[span].pri.pri) {
14135          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14136       }
14137    }
14138    return CLI_SUCCESS;
14139 }

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

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

14220 {
14221    switch (cmd) {
14222    case CLI_INIT:
14223       e->command = "pri show version";
14224       e->usage =
14225          "Usage: pri show version\n"
14226          "Show libpri version information\n";
14227       return NULL;
14228    case CLI_GENERATE:
14229       return NULL;
14230    }
14231 
14232    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14233 
14234    return CLI_SUCCESS;
14235 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

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

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

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

12808 {
12809 #if defined(HAVE_PRI)
12810    if (0 < span) {
12811       /* The channel must be on the specified PRI span. */
12812       if (!p->pri || p->pri->span != span) {
12813          return 0;
12814       }
12815       if (!groupmatch && channelmatch == -1) {
12816          /* Match any group since it only needs to be on the PRI span. */
12817          *groupmatched = 1;
12818          return 1;
12819       }
12820    }
12821 #endif   /* defined(HAVE_PRI) */
12822    /* check group matching */
12823    if (groupmatch) {
12824       if ((p->group & groupmatch) != groupmatch)
12825          /* Doesn't match the specified group, try the next one */
12826          return 0;
12827       *groupmatched = 1;
12828    }
12829    /* Check to see if we have a channel match */
12830    if (channelmatch != -1) {
12831       if (p->channel != channelmatch)
12832          /* Doesn't match the specified channel, try the next one */
12833          return 0;
12834       *channelmatched = 1;
12835    }
12836 
12837    return 1;
12838 }

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

Definition at line 4605 of file chan_dahdi.c.

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

Referenced by conf_del().

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

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

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

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

static int load_module ( void   )  [static]

Definition at line 17985 of file chan_dahdi.c.

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

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

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

Definition at line 13611 of file chan_dahdi.c.

References ast_log(), LOG_DEBUG, and SUB_REAL.

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

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

Definition at line 11928 of file chan_dahdi.c.

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

Referenced by build_channels().

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

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

Definition at line 461 of file chan_dahdi.c.

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

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

static int mwi_send_init ( struct dahdi_pvt pvt  )  [static]

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

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

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

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

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

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

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

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

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

Definition at line 10715 of file chan_dahdi.c.

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

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

static void my_all_subchannels_hungup ( void *  pvt  )  [static]

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

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

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

Definition at line 2605 of file chan_dahdi.c.

References alloc_sub(), and analogsub_to_dahdisub().

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

static void my_answer_polarityswitch ( void *  pvt  )  [static]

Definition at line 2843 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

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

static int my_callwait ( void *  pvt  )  [static]

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

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

static void my_cancel_cidspill ( void *  pvt  )  [static]

Definition at line 2277 of file chan_dahdi.c.

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

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

static int my_check_confirmanswer ( void *  pvt  )  [static]

Definition at line 2260 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

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

static int my_check_for_conference ( void *  pvt  )  [static]

Definition at line 2437 of file chan_dahdi.c.

References check_for_conference().

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

static int my_check_waitingfordt ( void *  pvt  )  [static]

Definition at line 2243 of file chan_dahdi.c.

References dahdi_pvt::waitingfordt.

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

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

Definition at line 2387 of file chan_dahdi.c.

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

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

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

Definition at line 2377 of file chan_dahdi.c.

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

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

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

Definition at line 2367 of file chan_dahdi.c.

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

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

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

Definition at line 2286 of file chan_dahdi.c.

References dahdi_confmute().

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

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

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

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

static void my_deadlock_avoidance_private ( void *  pvt  )  [static]

Definition at line 2103 of file chan_dahdi.c.

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

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

static void my_decrease_ss_count ( void   )  [static]

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

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

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

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

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

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

static int my_dsp_reset_and_flush_digits ( void *  pvt  )  [static]

Definition at line 1953 of file chan_dahdi.c.

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

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

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

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

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

static int my_flash ( void *  pvt  )  [static]

Definition at line 2802 of file chan_dahdi.c.

References SUB_REAL, and dahdi_pvt::subs.

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

static void my_get_and_handle_alarms ( void *  pvt  )  [static]

Definition at line 2135 of file chan_dahdi.c.

References get_alarms(), and handle_alarms().

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

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

Definition at line 1672 of file chan_dahdi.c.

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

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

static int my_get_event ( void *  pvt  )  [static]

Definition at line 2735 of file chan_dahdi.c.

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

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

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

Definition at line 2305 of file chan_dahdi.c.

References dahdi_pvt::dialstring.

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

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

Definition at line 2144 of file chan_dahdi.c.

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

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

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

Definition at line 2153 of file chan_dahdi.c.

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

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

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

Definition at line 9507 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

09508 {
09509    char c;
09510 
09511    *str = 0; /* start with empty output buffer */
09512    for (;;)
09513    {
09514       /* Wait for the first digit (up to specified ms). */
09515       c = ast_waitfordigit(chan, ms);
09516       /* if timeout, hangup or error, return as such */
09517       if (c < 1)
09518          return c;
09519       *str++ = c;
09520       *str = 0;
09521       if (strchr(term, c))
09522          return 1;
09523    }
09524 }

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

Definition at line 2997 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

static void my_hangup_polarityswitch ( void *  pvt  )  [static]

Definition at line 2854 of file chan_dahdi.c.

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

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

static int my_has_voicemail ( void *  pvt  )  [static]

Definition at line 2614 of file chan_dahdi.c.

References has_voicemail().

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

static void my_increase_ss_count ( void   )  [static]

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

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

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

static int my_is_off_hook ( void *  pvt  )  [static]

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

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

static void my_lock_private ( void *  pvt  )  [static]

Definition at line 2091 of file chan_dahdi.c.

References ast_mutex_lock, and dahdi_pvt::lock.

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

static void my_module_ref ( void   )  [static]

Definition at line 3243 of file chan_dahdi.c.

References ast_module_ref().

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

static void my_module_unref ( void   )  [static]

Definition at line 3257 of file chan_dahdi.c.

References ast_module_unref().

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

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

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

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

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

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

static int my_off_hook ( void *  pvt  )  [static]

Definition at line 2811 of file chan_dahdi.c.

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

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

static int my_on_hook ( void *  pvt  )  [static]

Definition at line 2932 of file chan_dahdi.c.

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

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

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

Definition at line 2621 of file chan_dahdi.c.

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

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

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

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

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

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

Definition at line 3127 of file chan_dahdi.c.

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

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

static void my_pri_open_media ( void *  p  )  [static]

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

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

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

Definition at line 3020 of file chan_dahdi.c.

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

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

static int my_ring ( void *  pvt  )  [static]

Definition at line 2795 of file chan_dahdi.c.

References dahdi_ring_phone().

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

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

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

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

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

Definition at line 2176 of file chan_dahdi.c.

References dahdi_pvt::inalarm.

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

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

Definition at line 2160 of file chan_dahdi.c.

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

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

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

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

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

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

Definition at line 2270 of file chan_dahdi.c.

References dahdi_pvt::callwaiting.

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

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

Definition at line 2254 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

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

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

Definition at line 2183 of file chan_dahdi.c.

References dahdi_pvt::dialing.

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

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

Definition at line 2191 of file chan_dahdi.c.

References dahdi_pvt::digital.

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

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

Definition at line 3075 of file chan_dahdi.c.

References ast_copy_string(), and dahdi_pvt::dnid.

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

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

Definition at line 2781 of file chan_dahdi.c.

References dahdi_disable_ec(), and dahdi_enable_ec().

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

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

Definition at line 2125 of file chan_dahdi.c.

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

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

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

Definition at line 2113 of file chan_dahdi.c.

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

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

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

Definition at line 2817 of file chan_dahdi.c.

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

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

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

Definition at line 2298 of file chan_dahdi.c.

References dahdi_pvt::owner.

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

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

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

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

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

Definition at line 2292 of file chan_dahdi.c.

References dahdi_pvt::pulsedial.

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

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

Definition at line 3094 of file chan_dahdi.c.

References ast_copy_string(), and dahdi_pvt::rdnis.

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

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

Definition at line 2226 of file chan_dahdi.c.

References dahdi_pvt::ringt.

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

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

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

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

static int my_start ( void *  pvt  )  [static]

Definition at line 2869 of file chan_dahdi.c.

References SUB_REAL, and dahdi_pvt::subs.

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

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

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

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

static void my_start_polarityswitch ( void *  pvt  )  [static]

Definition at line 2834 of file chan_dahdi.c.

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

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

static int my_stop_callwait ( void *  pvt  )  [static]

Definition at line 1871 of file chan_dahdi.c.

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

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

static int my_stop_cid_detect ( void *  pvt  )  [static]

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

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

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

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

static int my_train_echocanceller ( void *  pvt  )  [static]

Definition at line 2907 of file chan_dahdi.c.

References dahdi_train_ec().

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

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

Definition at line 2596 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and unalloc_sub().

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

static void my_unlock_private ( void *  pvt  )  [static]

Definition at line 2097 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pvt::lock.

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

static int my_wait_event ( void *  pvt  )  [static]

Definition at line 2728 of file chan_dahdi.c.

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

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

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

Definition at line 2003 of file chan_dahdi.c.

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

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

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

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

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

Definition at line 6821 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write().

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

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

Definition at line 16305 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

16306 {
16307    char *p;
16308 
16309    if ((p = strrchr(chanstr, '!')) == NULL) {
16310       *subdir = NULL;
16311       return chanstr;
16312    }
16313    *p++ = '\0';
16314    string_replace(chanstr, '!', '/');
16315    *subdir = chanstr;
16316    return p;
16317 }

static int prepare_pri ( struct dahdi_pri pri  )  [static]

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

13778 {
13779    int i, res, x;
13780    struct dahdi_params p;
13781    struct dahdi_bufferinfo bi;
13782    struct dahdi_spaninfo si;
13783 
13784    pri->pri.calls = &dahdi_pri_callbacks;
13785 
13786    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
13787       if (!pri->dchannels[i])
13788          break;
13789       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
13790       x = pri->dchannels[i];
13791       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
13792          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13793          return -1;
13794       }
13795       memset(&p, 0, sizeof(p));
13796       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
13797       if (res) {
13798          dahdi_close_pri_fd(pri, i);
13799          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13800          return -1;
13801       }
13802       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13803          dahdi_close_pri_fd(pri, i);
13804          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13805          return -1;
13806       }
13807       memset(&si, 0, sizeof(si));
13808       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
13809       if (res) {
13810          dahdi_close_pri_fd(pri, i);
13811          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13812       }
13813       if (!si.alarms) {
13814          pri_event_noalarm(&pri->pri, i, 1);
13815       } else {
13816          pri_event_alarm(&pri->pri, i, 1);
13817       }
13818       memset(&bi, 0, sizeof(bi));
13819       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13820       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13821       bi.numbufs = 32;
13822       bi.bufsize = 1024;
13823       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
13824          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13825          dahdi_close_pri_fd(pri, i);
13826          return -1;
13827       }
13828       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
13829    }
13830    return 0;
13831 }

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

Definition at line 11737 of file chan_dahdi.c.

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

Referenced by setup_dahdi_int().

11738 {
11739    if (pris[span].mastertrunkgroup) {
11740       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);
11741       return -1;
11742    }
11743    pris[span].mastertrunkgroup = trunkgroup;
11744    pris[span].prilogicalspan = logicalspan;
11745    return 0;
11746 }

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

Definition at line 11674 of file chan_dahdi.c.

References ast_log(), NUM_SPANS, and pris.

Referenced by setup_dahdi_int().

11675 {
11676    struct dahdi_spaninfo si;
11677    struct dahdi_params p;
11678    int fd;
11679    int span;
11680    int ospan=0;
11681    int x,y;
11682    for (x = 0; x < NUM_SPANS; x++) {
11683       if (pris[x].pri.trunkgroup == trunkgroup) {
11684          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11685          return -1;
11686       }
11687    }
11688    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11689       if (!channels[y])
11690          break;
11691       memset(&si, 0, sizeof(si));
11692       memset(&p, 0, sizeof(p));
11693       fd = open("/dev/dahdi/channel", O_RDWR);
11694       if (fd < 0) {
11695          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11696          return -1;
11697       }
11698       x = channels[y];
11699       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11700          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11701          close(fd);
11702          return -1;
11703       }
11704       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11705          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11706          return -1;
11707       }
11708       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11709          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11710          close(fd);
11711          return -1;
11712       }
11713       span = p.spanno - 1;
11714       if (pris[span].pri.trunkgroup) {
11715          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11716          close(fd);
11717          return -1;
11718       }
11719       if (pris[span].pri.pvts[0]) {
11720          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11721          close(fd);
11722          return -1;
11723       }
11724       if (!y) {
11725          pris[span].pri.trunkgroup = trunkgroup;
11726          ospan = span;
11727       }
11728       pris[ospan].dchannels[y] = channels[y];
11729       pris[span].pri.span = span + 1;
11730       close(fd);
11731    }
11732    return 0;
11733 }

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

Definition at line 11628 of file chan_dahdi.c.

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

11629 {
11630    int x;
11631    int trunkgroup;
11632    /* Get appropriate trunk group if there is one */
11633    trunkgroup = pris[*span].mastertrunkgroup;
11634    if (trunkgroup) {
11635       /* Select a specific trunk group */
11636       for (x = 0; x < NUM_SPANS; x++) {
11637          if (pris[x].pri.trunkgroup == trunkgroup) {
11638             *span = x;
11639             return 0;
11640          }
11641       }
11642       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11643       *span = -1;
11644    } else {
11645       if (pris[*span].pri.trunkgroup) {
11646          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);
11647          *span = -1;
11648       } else if (pris[*span].mastertrunkgroup) {
11649          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11650          *span = -1;
11651       } else {
11652          if (si->totalchans == 31) {
11653             /* E1 */
11654             pris[*span].dchannels[0] = 16 + offset;
11655          } else if (si->totalchans == 24) {
11656             /* T1 or J1 */
11657             pris[*span].dchannels[0] = 24 + offset;
11658          } else if (si->totalchans == 3) {
11659             /* BRI */
11660             pris[*span].dchannels[0] = 3 + offset;
11661          } else {
11662             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);
11663             *span = -1;
11664             return 0;
11665          }
11666          pris[*span].pri.span = *span + 1;
11667       }
11668    }
11669    return 0;
11670 }

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

Definition at line 16448 of file chan_dahdi.c.

References ast_copy_string(), ast_jb_read_conf(), ast_log(), build_channels(), dahdi_chan_conf::chan, global_jbconf, ast_variable::lineno, MAX_CHANLIST_LEN, ast_variable::name, ast_variable::next, dahdi_pvt::parkinglot, PROC_DAHDI_OPT_NOCHAN, and ast_variable::value.

Referenced by setup_dahdi_int().

16449 {
16450    struct dahdi_pvt *tmp;
16451    int y;
16452    int found_pseudo = 0;
16453    char dahdichan[MAX_CHANLIST_LEN] = {};
16454 
16455    for (; v; v = v->next) {
16456       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16457          continue;
16458 
16459       /* must have parkinglot in confp before build_channels is called */
16460       if (!strcasecmp(v->name, "parkinglot")) {
16461          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16462       }
16463 
16464       /* Create the interface list */
16465       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16466          if (options & PROC_DAHDI_OPT_NOCHAN) {
16467             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16468             continue;
16469          }
16470          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16471             if (confp->ignore_failed_channels) {
16472                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16473                continue;
16474             } else {
16475                return -1;
16476             }
16477          }
16478          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16479       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16480          confp->ignore_failed_channels = ast_true(v->value);
16481       } else if (!strcasecmp(v->name, "buffers")) {
16482          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16483             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16484             confp->chan.buf_no = numbufs;
16485             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16486          }
16487       } else if (!strcasecmp(v->name, "faxbuffers")) {
16488          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16489             confp->chan.usefaxbuffers = 1;
16490          }
16491       } else if (!strcasecmp(v->name, "dahdichan")) {
16492          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16493       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16494          usedistinctiveringdetection = ast_true(v->value);
16495       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16496          distinctiveringaftercid = ast_true(v->value);
16497       } else if (!strcasecmp(v->name, "dring1context")) {
16498          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16499       } else if (!strcasecmp(v->name, "dring2context")) {
16500          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16501       } else if (!strcasecmp(v->name, "dring3context")) {
16502          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16503       } else if (!strcasecmp(v->name, "dring1range")) {
16504          confp->chan.drings.ringnum[0].range = atoi(v->value);
16505       } else if (!strcasecmp(v->name, "dring2range")) {
16506          confp->chan.drings.ringnum[1].range = atoi(v->value);
16507       } else if (!strcasecmp(v->name, "dring3range")) {
16508          confp->chan.drings.ringnum[2].range = atoi(v->value);
16509       } else if (!strcasecmp(v->name, "dring1")) {
16510          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]);
16511       } else if (!strcasecmp(v->name, "dring2")) {
16512          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]);
16513       } else if (!strcasecmp(v->name, "dring3")) {
16514          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]);
16515       } else if (!strcasecmp(v->name, "usecallerid")) {
16516          confp->chan.use_callerid = ast_true(v->value);
16517       } else if (!strcasecmp(v->name, "cidsignalling")) {
16518          if (!strcasecmp(v->value, "bell"))
16519             confp->chan.cid_signalling = CID_SIG_BELL;
16520          else if (!strcasecmp(v->value, "v23"))
16521             confp->chan.cid_signalling = CID_SIG_V23;
16522          else if (!strcasecmp(v->value, "dtmf"))
16523             confp->chan.cid_signalling = CID_SIG_DTMF;
16524          else if (!strcasecmp(v->value, "smdi"))
16525             confp->chan.cid_signalling = CID_SIG_SMDI;
16526          else if (!strcasecmp(v->value, "v23_jp"))
16527             confp->chan.cid_signalling = CID_SIG_V23_JP;
16528          else if (ast_true(v->value))
16529             confp->chan.cid_signalling = CID_SIG_BELL;
16530       } else if (!strcasecmp(v->name, "cidstart")) {
16531          if (!strcasecmp(v->value, "ring"))
16532             confp->chan.cid_start = CID_START_RING;
16533          else if (!strcasecmp(v->value, "polarity_in"))
16534             confp->chan.cid_start = CID_START_POLARITY_IN;
16535          else if (!strcasecmp(v->value, "polarity"))
16536             confp->chan.cid_start = CID_START_POLARITY;
16537          else if (!strcasecmp(v->value, "dtmf"))
16538             confp->chan.cid_start = CID_START_DTMF_NOALERT;
16539          else if (ast_true(v->value))
16540             confp->chan.cid_start = CID_START_RING;
16541       } else if (!strcasecmp(v->name, "threewaycalling")) {
16542          confp->chan.threewaycalling = ast_true(v->value);
16543       } else if (!strcasecmp(v->name, "cancallforward")) {
16544          confp->chan.cancallforward = ast_true(v->value);
16545       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16546          if (ast_true(v->value))
16547             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16548          else
16549             confp->chan.dtmfrelax = 0;
16550       } else if (!strcasecmp(v->name, "mailbox")) {
16551          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16552       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16553          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16554             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16555          }
16556       } else if (!strcasecmp(v->name, "adsi")) {
16557          confp->chan.adsi = ast_true(v->value);
16558       } else if (!strcasecmp(v->name, "usesmdi")) {
16559          confp->chan.use_smdi = ast_true(v->value);
16560       } else if (!strcasecmp(v->name, "smdiport")) {
16561          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16562       } else if (!strcasecmp(v->name, "transfer")) {
16563          confp->chan.transfer = ast_true(v->value);
16564       } else if (!strcasecmp(v->name, "canpark")) {
16565          confp->chan.canpark = ast_true(v->value);
16566       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16567          confp->chan.echocanbridged = ast_true(v->value);
16568       } else if (!strcasecmp(v->name, "busydetect")) {
16569          confp->chan.busydetect = ast_true(v->value);
16570       } else if (!strcasecmp(v->name, "busycount")) {
16571          confp->chan.busycount = atoi(v->value);
16572       } else if (!strcasecmp(v->name, "silencethreshold")) {
16573          confp->chan.silencethreshold = atoi(v->value);
16574       } else if (!strcasecmp(v->name, "busycompare")) {
16575          confp->chan.busycompare = ast_true(v->value);
16576       } else if (!strcasecmp(v->name, "busypattern")) {
16577          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
16578             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16579          }
16580          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
16581          if (count == 1)
16582             confp->chan.busyquietlength = 0;
16583          else if (count < 1)
16584             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
16585       } else if (!strcasecmp(v->name, "busyfuzziness")) {
16586          confp->chan.busyfuzziness = atoi(v->value);
16587       } else if (!strcasecmp(v->name, "callprogress")) {
16588          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16589          if (ast_true(v->value))
16590             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16591       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16592          confp->chan.waitfordialtone = atoi(v->value);
16593       } else if (!strcasecmp(v->name, "faxdetect")) {
16594          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16595          if (!strcasecmp(v->value, "incoming")) {
16596             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16597          } else if (!strcasecmp(v->value, "outgoing")) {
16598             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16599          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16600             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16601       } else if (!strcasecmp(v->name, "echocancel")) {
16602          process_echocancel(confp, v->value, v->lineno);
16603       } else if (!strcasecmp(v->name, "echotraining")) {
16604          if (sscanf(v->value, "%30d", &y) == 1) {
16605             if ((y < 10) || (y > 4000)) {
16606                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16607             } else {
16608                confp->chan.echotraining = y;
16609             }
16610          } else if (ast_true(v->value)) {
16611             confp->chan.echotraining = 400;
16612          } else
16613             confp->chan.echotraining = 0;
16614       } else if (!strcasecmp(v->name, "hidecallerid")) {
16615          confp->chan.hidecallerid = ast_true(v->value);
16616       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16617          confp->chan.hidecalleridname = ast_true(v->value);
16618       } else if (!strcasecmp(v->name, "pulsedial")) {
16619          confp->chan.pulse = ast_true(v->value);
16620       } else if (!strcasecmp(v->name, "callreturn")) {
16621          confp->chan.callreturn = ast_true(v->value);
16622       } else if (!strcasecmp(v->name, "callwaiting")) {
16623          confp->chan.callwaiting = ast_true(v->value);
16624       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16625          confp->chan.callwaitingcallerid = ast_true(v->value);
16626       } else if (!strcasecmp(v->name, "context")) {
16627          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16628       } else if (!strcasecmp(v->name, "language")) {
16629          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16630       } else if (!strcasecmp(v->name, "progzone")) {
16631          ast_copy_string(progzone, v->value, sizeof(progzone));
16632       } else if (!strcasecmp(v->name, "mohinterpret")
16633          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16634          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16635       } else if (!strcasecmp(v->name, "mohsuggest")) {
16636          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16637       } else if (!strcasecmp(v->name, "parkinglot")) {
16638          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16639       } else if (!strcasecmp(v->name, "stripmsd")) {
16640          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16641          confp->chan.stripmsd = atoi(v->value);
16642       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16643          numbufs = atoi(v->value);
16644       } else if (!strcasecmp(v->name, "group")) {
16645          confp->chan.group = ast_get_group(v->value);
16646       } else if (!strcasecmp(v->name, "callgroup")) {
16647          if (!strcasecmp(v->value, "none"))
16648             confp->chan.callgroup = 0;
16649          else
16650             confp->chan.callgroup = ast_get_group(v->value);
16651       } else if (!strcasecmp(v->name, "pickupgroup")) {
16652          if (!strcasecmp(v->value, "none"))
16653             confp->chan.pickupgroup = 0;
16654          else
16655             confp->chan.pickupgroup = ast_get_group(v->value);
16656       } else if (!strcasecmp(v->name, "setvar")) {
16657          char *varname = ast_strdupa(v->value), *varval = NULL;
16658          struct ast_variable *tmpvar;
16659          if (varname && (varval = strchr(varname, '='))) {
16660             *varval++ = '\0';
16661             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16662                tmpvar->next = confp->chan.vars;
16663                confp->chan.vars = tmpvar;
16664             }
16665          }
16666       } else if (!strcasecmp(v->name, "immediate")) {
16667          confp->chan.immediate = ast_true(v->value);
16668       } else if (!strcasecmp(v->name, "transfertobusy")) {
16669          confp->chan.transfertobusy = ast_true(v->value);
16670       } else if (!strcasecmp(v->name, "mwimonitor")) {
16671          confp->chan.mwimonitor_neon = 0;
16672          confp->chan.mwimonitor_fsk = 0;
16673          confp->chan.mwimonitor_rpas = 0;
16674          if (strcasestr(v->value, "fsk")) {
16675             confp->chan.mwimonitor_fsk = 1;
16676          }
16677          if (strcasestr(v->value, "rpas")) {
16678             confp->chan.mwimonitor_rpas = 1;
16679          }
16680          if (strcasestr(v->value, "neon")) {
16681             confp->chan.mwimonitor_neon = 1;
16682          }
16683          /* If set to true or yes, assume that simple fsk is desired */
16684          if (ast_true(v->value)) {
16685             confp->chan.mwimonitor_fsk = 1;
16686          }
16687       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16688          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16689             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16690          }
16691       } else if (!strcasecmp(v->name, "rxgain")) {
16692          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16693             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16694          }
16695       } else if (!strcasecmp(v->name, "txgain")) {
16696          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16697             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16698          }
16699       } else if (!strcasecmp(v->name, "txdrc")) {
16700          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
16701             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
16702          }
16703       } else if (!strcasecmp(v->name, "rxdrc")) {
16704          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
16705             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
16706          }
16707       } else if (!strcasecmp(v->name, "tonezone")) {
16708          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16709             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16710          }
16711       } else if (!strcasecmp(v->name, "callerid")) {
16712          if (!strcasecmp(v->value, "asreceived")) {
16713             confp->chan.cid_num[0] = '\0';
16714             confp->chan.cid_name[0] = '\0';
16715          } else {
16716             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16717          }
16718       } else if (!strcasecmp(v->name, "fullname")) {
16719          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16720       } else if (!strcasecmp(v->name, "cid_number")) {
16721          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16722       } else if (!strcasecmp(v->name, "cid_tag")) {
16723          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
16724       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16725          confp->chan.dahditrcallerid = ast_true(v->value);
16726       } else if (!strcasecmp(v->name, "restrictcid")) {
16727          confp->chan.restrictcid = ast_true(v->value);
16728       } else if (!strcasecmp(v->name, "usecallingpres")) {
16729          confp->chan.use_callingpres = ast_true(v->value);
16730       } else if (!strcasecmp(v->name, "accountcode")) {
16731          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16732       } else if (!strcasecmp(v->name, "amaflags")) {
16733          y = ast_cdr_amaflags2int(v->value);
16734          if (y < 0)
16735             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16736          else
16737             confp->chan.amaflags = y;
16738       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16739          confp->chan.polarityonanswerdelay = atoi(v->value);
16740       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16741          confp->chan.answeronpolarityswitch = ast_true(v->value);
16742       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16743          confp->chan.hanguponpolarityswitch = ast_true(v->value);
16744       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16745          confp->chan.sendcalleridafter = atoi(v->value);
16746       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16747          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16748       } else if (ast_cc_is_config_param(v->name)) {
16749          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
16750       } else if (!strcasecmp(v->name, "mwisendtype")) {
16751 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
16752          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
16753             mwisend_rpas = 1;
16754          } else {
16755             mwisend_rpas = 0;
16756          }
16757 #else
16758          /* Default is fsk, to turn it off you must specify nofsk */
16759          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16760          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
16761             confp->chan.mwisend_fsk = 0;
16762          } else {             /* Default FSK */
16763             confp->chan.mwisend_fsk = 1;
16764          }
16765          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
16766             confp->chan.mwisend_rpas = 1;
16767          } else {
16768             confp->chan.mwisend_rpas = 0;
16769          }
16770          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
16771             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16772          }
16773          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
16774             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16775          }
16776          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
16777             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16778          }
16779 #endif
16780       } else if (reload != 1) {
16781           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16782             int orig_radio = confp->chan.radio;
16783             int orig_outsigmod = confp->chan.outsigmod;
16784             int orig_auto = confp->is_sig_auto;
16785 
16786             confp->chan.radio = 0;
16787             confp->chan.outsigmod = -1;
16788             confp->is_sig_auto = 0;
16789             if (!strcasecmp(v->value, "em")) {
16790                confp->chan.sig = SIG_EM;
16791             } else if (!strcasecmp(v->value, "em_e1")) {
16792                confp->chan.sig = SIG_EM_E1;
16793             } else if (!strcasecmp(v->value, "em_w")) {
16794                confp->chan.sig = SIG_EMWINK;
16795             } else if (!strcasecmp(v->value, "fxs_ls")) {
16796                confp->chan.sig = SIG_FXSLS;
16797             } else if (!strcasecmp(v->value, "fxs_gs")) {
16798                confp->chan.sig = SIG_FXSGS;
16799             } else if (!strcasecmp(v->value, "fxs_ks")) {
16800                confp->chan.sig = SIG_FXSKS;
16801             } else if (!strcasecmp(v->value, "fxo_ls")) {
16802                confp->chan.sig = SIG_FXOLS;
16803             } else if (!strcasecmp(v->value, "fxo_gs")) {
16804                confp->chan.sig = SIG_FXOGS;
16805             } else if (!strcasecmp(v->value, "fxo_ks")) {
16806                confp->chan.sig = SIG_FXOKS;
16807             } else if (!strcasecmp(v->value, "fxs_rx")) {
16808                confp->chan.sig = SIG_FXSKS;
16809                confp->chan.radio = 1;
16810             } else if (!strcasecmp(v->value, "fxo_rx")) {
16811                confp->chan.sig = SIG_FXOLS;
16812                confp->chan.radio = 1;
16813             } else if (!strcasecmp(v->value, "fxs_tx")) {
16814                confp->chan.sig = SIG_FXSLS;
16815                confp->chan.radio = 1;
16816             } else if (!strcasecmp(v->value, "fxo_tx")) {
16817                confp->chan.sig = SIG_FXOGS;
16818                confp->chan.radio = 1;
16819             } else if (!strcasecmp(v->value, "em_rx")) {
16820                confp->chan.sig = SIG_EM;
16821                confp->chan.radio = 1;
16822             } else if (!strcasecmp(v->value, "em_tx")) {
16823                confp->chan.sig = SIG_EM;
16824                confp->chan.radio = 1;
16825             } else if (!strcasecmp(v->value, "em_rxtx")) {
16826                confp->chan.sig = SIG_EM;
16827                confp->chan.radio = 2;
16828             } else if (!strcasecmp(v->value, "em_txrx")) {
16829                confp->chan.sig = SIG_EM;
16830                confp->chan.radio = 2;
16831             } else if (!strcasecmp(v->value, "sf")) {
16832                confp->chan.sig = SIG_SF;
16833             } else if (!strcasecmp(v->value, "sf_w")) {
16834                confp->chan.sig = SIG_SFWINK;
16835             } else if (!strcasecmp(v->value, "sf_featd")) {
16836                confp->chan.sig = SIG_FEATD;
16837             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16838                confp->chan.sig = SIG_FEATDMF;
16839             } else if (!strcasecmp(v->value, "sf_featb")) {
16840                confp->chan.sig = SIG_SF_FEATB;
16841             } else if (!strcasecmp(v->value, "sf")) {
16842                confp->chan.sig = SIG_SF;
16843             } else if (!strcasecmp(v->value, "sf_rx")) {
16844                confp->chan.sig = SIG_SF;
16845                confp->chan.radio = 1;
16846             } else if (!strcasecmp(v->value, "sf_tx")) {
16847                confp->chan.sig = SIG_SF;
16848                confp->chan.radio = 1;
16849             } else if (!strcasecmp(v->value, "sf_rxtx")) {
16850                confp->chan.sig = SIG_SF;
16851                confp->chan.radio = 2;
16852             } else if (!strcasecmp(v->value, "sf_txrx")) {
16853                confp->chan.sig = SIG_SF;
16854                confp->chan.radio = 2;
16855             } else if (!strcasecmp(v->value, "featd")) {
16856                confp->chan.sig = SIG_FEATD;
16857             } else if (!strcasecmp(v->value, "featdmf")) {
16858                confp->chan.sig = SIG_FEATDMF;
16859             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16860                confp->chan.sig = SIG_FEATDMF_TA;
16861             } else if (!strcasecmp(v->value, "e911")) {
16862                confp->chan.sig = SIG_E911;
16863             } else if (!strcasecmp(v->value, "fgccama")) {
16864                confp->chan.sig = SIG_FGC_CAMA;
16865             } else if (!strcasecmp(v->value, "fgccamamf")) {
16866                confp->chan.sig = SIG_FGC_CAMAMF;
16867             } else if (!strcasecmp(v->value, "featb")) {
16868                confp->chan.sig = SIG_FEATB;
16869 #ifdef HAVE_PRI
16870             } else if (!strcasecmp(v->value, "pri_net")) {
16871                confp->chan.sig = SIG_PRI;
16872                confp->pri.pri.nodetype = PRI_NETWORK;
16873             } else if (!strcasecmp(v->value, "pri_cpe")) {
16874                confp->chan.sig = SIG_PRI;
16875                confp->pri.pri.nodetype = PRI_CPE;
16876             } else if (!strcasecmp(v->value, "bri_cpe")) {
16877                confp->chan.sig = SIG_BRI;
16878                confp->pri.pri.nodetype = PRI_CPE;
16879             } else if (!strcasecmp(v->value, "bri_net")) {
16880                confp->chan.sig = SIG_BRI;
16881                confp->pri.pri.nodetype = PRI_NETWORK;
16882             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16883                confp->chan.sig = SIG_BRI_PTMP;
16884                confp->pri.pri.nodetype = PRI_CPE;
16885             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16886 #if defined(HAVE_PRI_CALL_HOLD)
16887                confp->chan.sig = SIG_BRI_PTMP;
16888                confp->pri.pri.nodetype = PRI_NETWORK;
16889 #else
16890                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
16891 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
16892 #endif
16893 #if defined(HAVE_SS7)
16894             } else if (!strcasecmp(v->value, "ss7")) {
16895                confp->chan.sig = SIG_SS7;
16896 #endif   /* defined(HAVE_SS7) */
16897 #ifdef HAVE_OPENR2
16898             } else if (!strcasecmp(v->value, "mfcr2")) {
16899                confp->chan.sig = SIG_MFCR2;
16900 #endif
16901             } else if (!strcasecmp(v->value, "auto")) {
16902                confp->is_sig_auto = 1;
16903             } else {
16904                confp->chan.outsigmod = orig_outsigmod;
16905                confp->chan.radio = orig_radio;
16906                confp->is_sig_auto = orig_auto;
16907                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16908             }
16909           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16910             if (!strcasecmp(v->value, "em")) {
16911                confp->chan.outsigmod = SIG_EM;
16912             } else if (!strcasecmp(v->value, "em_e1")) {
16913                confp->chan.outsigmod = SIG_EM_E1;
16914             } else if (!strcasecmp(v->value, "em_w")) {
16915                confp->chan.outsigmod = SIG_EMWINK;
16916             } else if (!strcasecmp(v->value, "sf")) {
16917                confp->chan.outsigmod = SIG_SF;
16918             } else if (!strcasecmp(v->value, "sf_w")) {
16919                confp->chan.outsigmod = SIG_SFWINK;
16920             } else if (!strcasecmp(v->value, "sf_featd")) {
16921                confp->chan.outsigmod = SIG_FEATD;
16922             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16923                confp->chan.outsigmod = SIG_FEATDMF;
16924             } else if (!strcasecmp(v->value, "sf_featb")) {
16925                confp->chan.outsigmod = SIG_SF_FEATB;
16926             } else if (!strcasecmp(v->value, "sf")) {
16927                confp->chan.outsigmod = SIG_SF;
16928             } else if (!strcasecmp(v->value, "featd")) {
16929                confp->chan.outsigmod = SIG_FEATD;
16930             } else if (!strcasecmp(v->value, "featdmf")) {
16931                confp->chan.outsigmod = SIG_FEATDMF;
16932             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16933                confp->chan.outsigmod = SIG_FEATDMF_TA;
16934             } else if (!strcasecmp(v->value, "e911")) {
16935                confp->chan.outsigmod = SIG_E911;
16936             } else if (!strcasecmp(v->value, "fgccama")) {
16937                confp->chan.outsigmod = SIG_FGC_CAMA;
16938             } else if (!strcasecmp(v->value, "fgccamamf")) {
16939                confp->chan.outsigmod = SIG_FGC_CAMAMF;
16940             } else if (!strcasecmp(v->value, "featb")) {
16941                confp->chan.outsigmod = SIG_FEATB;
16942             } else {
16943                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16944             }
16945 #ifdef HAVE_PRI
16946          } else if (!strcasecmp(v->name, "pridialplan")) {
16947             if (!strcasecmp(v->value, "national")) {
16948                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
16949             } else if (!strcasecmp(v->value, "unknown")) {
16950                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
16951             } else if (!strcasecmp(v->value, "private")) {
16952                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
16953             } else if (!strcasecmp(v->value, "international")) {
16954                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16955             } else if (!strcasecmp(v->value, "local")) {
16956                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
16957             } else if (!strcasecmp(v->value, "dynamic")) {
16958                confp->pri.pri.dialplan = -1;
16959             } else if (!strcasecmp(v->value, "redundant")) {
16960                confp->pri.pri.dialplan = -2;
16961             } else {
16962                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16963             }
16964          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16965             if (!strcasecmp(v->value, "national")) {
16966                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16967             } else if (!strcasecmp(v->value, "unknown")) {
16968                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
16969             } else if (!strcasecmp(v->value, "private")) {
16970                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
16971             } else if (!strcasecmp(v->value, "international")) {
16972                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16973             } else if (!strcasecmp(v->value, "local")) {
16974                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
16975             } else if (!strcasecmp(v->value, "dynamic")) {
16976                confp->pri.pri.localdialplan = -1;
16977             } else if (!strcasecmp(v->value, "redundant")) {
16978                confp->pri.pri.localdialplan = -2;
16979             } else {
16980                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16981             }
16982          } else if (!strcasecmp(v->name, "switchtype")) {
16983             if (!strcasecmp(v->value, "national"))
16984                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
16985             else if (!strcasecmp(v->value, "ni1"))
16986                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
16987             else if (!strcasecmp(v->value, "dms100"))
16988                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
16989             else if (!strcasecmp(v->value, "4ess"))
16990                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
16991             else if (!strcasecmp(v->value, "5ess"))
16992                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
16993             else if (!strcasecmp(v->value, "euroisdn"))
16994                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16995             else if (!strcasecmp(v->value, "qsig"))
16996                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
16997             else {
16998                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16999                return -1;
17000             }
17001          } else if (!strcasecmp(v->name, "msn")) {
17002             ast_copy_string(confp->pri.pri.msn_list, v->value,
17003                sizeof(confp->pri.pri.msn_list));
17004          } else if (!strcasecmp(v->name, "nsf")) {
17005             if (!strcasecmp(v->value, "sdn"))
17006                confp->pri.pri.nsf = PRI_NSF_SDN;
17007             else if (!strcasecmp(v->value, "megacom"))
17008                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17009             else if (!strcasecmp(v->value, "tollfreemegacom"))
17010                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17011             else if (!strcasecmp(v->value, "accunet"))
17012                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17013             else if (!strcasecmp(v->value, "none"))
17014                confp->pri.pri.nsf = PRI_NSF_NONE;
17015             else {
17016                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17017                confp->pri.pri.nsf = PRI_NSF_NONE;
17018             }
17019          } else if (!strcasecmp(v->name, "priindication")) {
17020             if (!strcasecmp(v->value, "outofband"))
17021                confp->chan.priindication_oob = 1;
17022             else if (!strcasecmp(v->value, "inband"))
17023                confp->chan.priindication_oob = 0;
17024             else
17025                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17026                   v->value, v->lineno);
17027          } else if (!strcasecmp(v->name, "priexclusive")) {
17028             confp->chan.priexclusive = ast_true(v->value);
17029          } else if (!strcasecmp(v->name, "internationalprefix")) {
17030             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17031          } else if (!strcasecmp(v->name, "nationalprefix")) {
17032             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17033          } else if (!strcasecmp(v->name, "localprefix")) {
17034             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17035          } else if (!strcasecmp(v->name, "privateprefix")) {
17036             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17037          } else if (!strcasecmp(v->name, "unknownprefix")) {
17038             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17039          } else if (!strcasecmp(v->name, "resetinterval")) {
17040             if (!strcasecmp(v->value, "never"))
17041                confp->pri.pri.resetinterval = -1;
17042             else if (atoi(v->value) >= 60)
17043                confp->pri.pri.resetinterval = atoi(v->value);
17044             else
17045                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17046                   v->value, v->lineno);
17047          } else if (!strcasecmp(v->name, "minunused")) {
17048             confp->pri.pri.minunused = atoi(v->value);
17049          } else if (!strcasecmp(v->name, "minidle")) {
17050             confp->pri.pri.minidle = atoi(v->value);
17051          } else if (!strcasecmp(v->name, "idleext")) {
17052             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17053          } else if (!strcasecmp(v->name, "idledial")) {
17054             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17055          } else if (!strcasecmp(v->name, "overlapdial")) {
17056             if (ast_true(v->value)) {
17057                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17058             } else if (!strcasecmp(v->value, "incoming")) {
17059                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17060             } else if (!strcasecmp(v->value, "outgoing")) {
17061                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17062             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17063                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17064             } else {
17065                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17066             }
17067 #ifdef HAVE_PRI_PROG_W_CAUSE
17068          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17069             if (!strcasecmp(v->value, "logical")) {
17070                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17071             } else if (!strcasecmp(v->value, "physical")) {
17072                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17073             } else {
17074                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17075             }
17076 #endif
17077          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17078             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17079 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17080          } else if (!strcasecmp(v->name, "service_message_support")) {
17081             /* assuming switchtype for this channel group has been configured already */
17082             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17083                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17084                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17085                confp->pri.pri.enable_service_message_support = 1;
17086             } else {
17087                confp->pri.pri.enable_service_message_support = 0;
17088             }
17089 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17090 #ifdef HAVE_PRI_INBANDDISCONNECT
17091          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17092             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17093 #endif
17094          } else if (!strcasecmp(v->name, "pritimer")) {
17095 #ifdef PRI_GETSET_TIMERS
17096             char tmp[20];
17097             char *timerc;
17098             char *c;
17099             int timer;
17100             int timeridx;
17101 
17102             ast_copy_string(tmp, v->value, sizeof(tmp));
17103             c = tmp;
17104             timerc = strsep(&c, ",");
17105             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17106                timeridx = pri_timer2idx(timerc);
17107                timer = atoi(c);
17108                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17109                   ast_log(LOG_WARNING,
17110                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17111                      v->lineno);
17112                } else if (!timer) {
17113                   ast_log(LOG_WARNING,
17114                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17115                      c, timerc, v->lineno);
17116                } else {
17117                   confp->pri.pri.pritimers[timeridx] = timer;
17118                }
17119             } else {
17120                ast_log(LOG_WARNING,
17121                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17122                   v->value, v->lineno);
17123             }
17124 #endif /* PRI_GETSET_TIMERS */
17125          } else if (!strcasecmp(v->name, "facilityenable")) {
17126             confp->pri.pri.facilityenable = ast_true(v->value);
17127 #if defined(HAVE_PRI_AOC_EVENTS)
17128          } else if (!strcasecmp(v->name, "aoc_enable")) {
17129             confp->pri.pri.aoc_passthrough_flag = 0;
17130             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17131                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17132             }
17133             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17134                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17135             }
17136             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17137                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17138             }
17139          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17140             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17141 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17142 #if defined(HAVE_PRI_CALL_HOLD)
17143          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17144             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17145 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17146 #if defined(HAVE_PRI_CCSS)
17147          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17148             if (!strcasecmp(v->value, "global")) {
17149                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17150             } else if (!strcasecmp(v->value, "specific")) {
17151                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17152             } else {
17153                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17154             }
17155          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17156             if (!strcasecmp(v->value, "release")) {
17157                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17158             } else if (!strcasecmp(v->value, "retain")) {
17159                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17160             } else if (!strcasecmp(v->value, "do_not_care")) {
17161                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17162             } else {
17163                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17164             }
17165          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17166             if (!strcasecmp(v->value, "release")) {
17167                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17168             } else if (!strcasecmp(v->value, "retain")) {
17169                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17170             } else {
17171                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17172             }
17173 #endif   /* defined(HAVE_PRI_CCSS) */
17174 #if defined(HAVE_PRI_CALL_WAITING)
17175          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17176             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17177             if (confp->pri.pri.max_call_waiting_calls < 0) {
17178                /* Negative values are not allowed. */
17179                confp->pri.pri.max_call_waiting_calls = 0;
17180             }
17181          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17182             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17183 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17184 #if defined(HAVE_PRI_MWI)
17185          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17186             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17187                sizeof(confp->pri.pri.mwi_mailboxes));
17188 #endif   /* defined(HAVE_PRI_MWI) */
17189          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17190             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17191 #endif /* HAVE_PRI */
17192 #if defined(HAVE_SS7)
17193          } else if (!strcasecmp(v->name, "ss7type")) {
17194             if (!strcasecmp(v->value, "itu")) {
17195                cur_ss7type = SS7_ITU;
17196             } else if (!strcasecmp(v->value, "ansi")) {
17197                cur_ss7type = SS7_ANSI;
17198             } else
17199                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17200          } else if (!strcasecmp(v->name, "linkset")) {
17201             cur_linkset = atoi(v->value);
17202          } else if (!strcasecmp(v->name, "pointcode")) {
17203             cur_pointcode = parse_pointcode(v->value);
17204          } else if (!strcasecmp(v->name, "adjpointcode")) {
17205             cur_adjpointcode = parse_pointcode(v->value);
17206          } else if (!strcasecmp(v->name, "defaultdpc")) {
17207             cur_defaultdpc = parse_pointcode(v->value);
17208          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17209             cur_cicbeginswith = atoi(v->value);
17210          } else if (!strcasecmp(v->name, "networkindicator")) {
17211             if (!strcasecmp(v->value, "national"))
17212                cur_networkindicator = SS7_NI_NAT;
17213             else if (!strcasecmp(v->value, "national_spare"))
17214                cur_networkindicator = SS7_NI_NAT_SPARE;
17215             else if (!strcasecmp(v->value, "international"))
17216                cur_networkindicator = SS7_NI_INT;
17217             else if (!strcasecmp(v->value, "international_spare"))
17218                cur_networkindicator = SS7_NI_INT_SPARE;
17219             else
17220                cur_networkindicator = -1;
17221          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17222             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17223          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17224             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17225          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17226             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17227          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17228             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17229          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17230             if (!strcasecmp(v->value, "national")) {
17231                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17232             } else if (!strcasecmp(v->value, "international")) {
17233                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17234             } else if (!strcasecmp(v->value, "subscriber")) {
17235                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17236             } else if (!strcasecmp(v->value, "unknown")) {
17237                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17238             } else if (!strcasecmp(v->value, "dynamic")) {
17239                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17240             } else {
17241                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17242             }
17243          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17244             if (!strcasecmp(v->value, "national")) {
17245                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17246             } else if (!strcasecmp(v->value, "international")) {
17247                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17248             } else if (!strcasecmp(v->value, "subscriber")) {
17249                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17250             } else if (!strcasecmp(v->value, "unknown")) {
17251                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17252             } else if (!strcasecmp(v->value, "dynamic")) {
17253                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17254             } else {
17255                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17256             }
17257          } else if (!strcasecmp(v->name, "sigchan")) {
17258             int sigchan, res;
17259             sigchan = atoi(v->value);
17260             res = linkset_addsigchan(sigchan);
17261             if (res < 0)
17262                return -1;
17263 
17264          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17265             struct dahdi_ss7 *link;
17266             link = ss7_resolve_linkset(cur_linkset);
17267             if (!link) {
17268                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17269                return -1;
17270             }
17271             if (ast_true(v->value))
17272                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17273 #endif   /* defined(HAVE_SS7) */
17274 #ifdef HAVE_OPENR2
17275          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17276             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17277             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);
17278          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17279             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17280          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17281             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17282             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17283                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17284                confp->mfcr2.variant = OR2_VAR_ITU;
17285             }
17286          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17287             confp->mfcr2.mfback_timeout = atoi(v->value);
17288             if (!confp->mfcr2.mfback_timeout) {
17289                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17290                confp->mfcr2.mfback_timeout = -1;
17291             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17292                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17293             }
17294          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17295             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17296             if (confp->mfcr2.metering_pulse_timeout > 500) {
17297                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17298             }
17299          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17300             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17301          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17302             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17303          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17304             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17305          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17306             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17307          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17308             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17309          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17310             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17311          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17312             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17313 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17314          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17315             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17316 #endif
17317          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17318             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17319          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17320             confp->mfcr2.max_ani = atoi(v->value);
17321             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17322                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17323             }
17324          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17325             confp->mfcr2.max_dnis = atoi(v->value);
17326             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17327                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17328             }
17329          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17330             confp->mfcr2.category = openr2_proto_get_category(v->value);
17331             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17332                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17333                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17334                      v->value, v->lineno);
17335             }
17336          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17337             openr2_log_level_t tmplevel;
17338             char *clevel;
17339             char *logval = ast_strdupa(v->value);
17340             while (logval) {
17341                clevel = strsep(&logval,",");
17342                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17343                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17344                   continue;
17345                }
17346                confp->mfcr2.loglevel |= tmplevel;
17347             }
17348 #endif /* HAVE_OPENR2 */
17349          } else if (!strcasecmp(v->name, "cadence")) {
17350             /* setup to scan our argument */
17351             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17352             int i;
17353             struct dahdi_ring_cadence new_cadence;
17354             int cid_location = -1;
17355             int firstcadencepos = 0;
17356             char original_args[80];
17357             int cadence_is_ok = 1;
17358 
17359             ast_copy_string(original_args, v->value, sizeof(original_args));
17360             /* 16 cadences allowed (8 pairs) */
17361             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]);
17362 
17363             /* Cadence must be even (on/off) */
17364             if (element_count % 2 == 1) {
17365                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17366                cadence_is_ok = 0;
17367             }
17368 
17369             /* Ring cadences cannot be negative */
17370             for (i = 0; i < element_count; i++) {
17371                if (c[i] == 0) {
17372                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17373                   cadence_is_ok = 0;
17374                   break;
17375                } else if (c[i] < 0) {
17376                   if (i % 2 == 1) {
17377                      /* Silence duration, negative possibly okay */
17378                      if (cid_location == -1) {
17379                         cid_location = i;
17380                         c[i] *= -1;
17381                      } else {
17382                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17383                         cadence_is_ok = 0;
17384                         break;
17385                      }
17386                   } else {
17387                      if (firstcadencepos == 0) {
17388                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17389                                  /* duration will be passed negative to the DAHDI driver */
17390                      } else {
17391                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17392                         cadence_is_ok = 0;
17393                         break;
17394                      }
17395                   }
17396                }
17397             }
17398 
17399             /* Substitute our scanned cadence */
17400             for (i = 0; i < 16; i++) {
17401                new_cadence.ringcadence[i] = c[i];
17402             }
17403 
17404             if (cadence_is_ok) {
17405                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17406                if (element_count < 2) {
17407                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17408                } else {
17409                   if (cid_location == -1) {
17410                      /* user didn't say; default to first pause */
17411                      cid_location = 1;
17412                   } else {
17413                      /* convert element_index to cidrings value */
17414                      cid_location = (cid_location + 1) / 2;
17415                   }
17416                   /* ---we like their cadence; try to install it--- */
17417                   if (!user_has_defined_cadences++)
17418                      /* this is the first user-defined cadence; clear the default user cadences */
17419                      num_cadence = 0;
17420                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17421                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17422                   else {
17423                      cadences[num_cadence] = new_cadence;
17424                      cidrings[num_cadence++] = cid_location;
17425                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17426                   }
17427                }
17428             }
17429          } else if (!strcasecmp(v->name, "ringtimeout")) {
17430             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17431          } else if (!strcasecmp(v->name, "prewink")) {
17432             confp->timing.prewinktime = atoi(v->value);
17433          } else if (!strcasecmp(v->name, "preflash")) {
17434             confp->timing.preflashtime = atoi(v->value);
17435          } else if (!strcasecmp(v->name, "wink")) {
17436             confp->timing.winktime = atoi(v->value);
17437          } else if (!strcasecmp(v->name, "flash")) {
17438             confp->timing.flashtime = atoi(v->value);
17439          } else if (!strcasecmp(v->name, "start")) {
17440             confp->timing.starttime = atoi(v->value);
17441          } else if (!strcasecmp(v->name, "rxwink")) {
17442             confp->timing.rxwinktime = atoi(v->value);
17443          } else if (!strcasecmp(v->name, "rxflash")) {
17444             confp->timing.rxflashtime = atoi(v->value);
17445          } else if (!strcasecmp(v->name, "debounce")) {
17446             confp->timing.debouncetime = atoi(v->value);
17447          } else if (!strcasecmp(v->name, "toneduration")) {
17448             int toneduration;
17449             int ctlfd;
17450             int res;
17451             struct dahdi_dialparams dps;
17452 
17453             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17454             if (ctlfd == -1) {
17455                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17456                return -1;
17457             }
17458 
17459             toneduration = atoi(v->value);
17460             if (toneduration > -1) {
17461                memset(&dps, 0, sizeof(dps));
17462 
17463                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17464                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17465                if (res < 0) {
17466                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17467                   close(ctlfd);
17468                   return -1;
17469                }
17470             }
17471             close(ctlfd);
17472          } else if (!strcasecmp(v->name, "defaultcic")) {
17473             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17474          } else if (!strcasecmp(v->name, "defaultozz")) {
17475             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17476          } else if (!strcasecmp(v->name, "mwilevel")) {
17477             mwilevel = atoi(v->value);
17478          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17479             dtmfcid_level = atoi(v->value);
17480          } else if (!strcasecmp(v->name, "reportalarms")) {
17481             if (!strcasecmp(v->value, "all"))
17482                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17483             if (!strcasecmp(v->value, "none"))
17484                report_alarms = 0;
17485             else if (!strcasecmp(v->value, "channels"))
17486                report_alarms = REPORT_CHANNEL_ALARMS;
17487             else if (!strcasecmp(v->value, "spans"))
17488                report_alarms = REPORT_SPAN_ALARMS;
17489           }
17490       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17491          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17492    }
17493    if (dahdichan[0]) {
17494       /* The user has set 'dahdichan' */
17495       /*< \todo pass proper line number instead of 0 */
17496       if (build_channels(confp, dahdichan, reload, 0, &found_pseudo)) {
17497          return -1;
17498       }
17499    }
17500 
17501    /* mark the first channels of each DAHDI span to watch for their span alarms */
17502    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17503       if (!tmp->destroy && tmp->span != y) {
17504          tmp->manages_span_alarms = 1;
17505          y = tmp->span; 
17506       } else {
17507          tmp->manages_span_alarms = 0;
17508       }
17509    }
17510 
17511    /*< \todo why check for the pseudo in the per-channel section.
17512     * Any actual use for manual setup of the pseudo channel? */
17513    if (!found_pseudo && reload != 1) {
17514       /* use the default configuration for a channel, so
17515          that any settings from real configured channels
17516          don't "leak" into the pseudo channel config
17517       */
17518       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17519 
17520       if (conf.chan.cc_params) {
17521          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17522       } else {
17523          tmp = NULL;
17524       }
17525       if (tmp) {
17526          ast_verb(3, "Automatically generated pseudo channel\n");
17527       } else {
17528          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17529       }
17530       ast_cc_config_params_destroy(conf.chan.cc_params);
17531    }
17532    return 0;
17533 }

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

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

16393 {
16394    char *parse = ast_strdupa(data);
16395    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16396    unsigned int param_count;
16397    unsigned int x;
16398 
16399    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16400       return;
16401 
16402    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16403 
16404    /* first parameter is tap length, process it here */
16405 
16406    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16407 
16408    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16409       confp->chan.echocancel.head.tap_length = x;
16410    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16411       confp->chan.echocancel.head.tap_length = 128;
16412 
16413    /* now process any remaining parameters */
16414 
16415    for (x = 1; x < param_count; x++) {
16416       struct {
16417          char *name;
16418          char *value;
16419       } param;
16420 
16421       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16422          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16423          continue;
16424       }
16425 
16426       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16427          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16428          continue;
16429       }
16430 
16431       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16432 
16433       if (param.value) {
16434          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16435             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16436             continue;
16437          }
16438       }
16439       confp->chan.echocancel.head.param_count++;
16440    }
16441 }

static int reload ( void   )  [static]

Definition at line 18166 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

18167 {
18168    int res = 0;
18169 
18170    res = setup_dahdi(1);
18171    if (res) {
18172       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18173       return -1;
18174    }
18175    return 0;
18176 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

04680 {
04681    p->confno = -1;
04682    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04683    if (p->subs[SUB_REAL].dfd > -1) {
04684       struct dahdi_confinfo zi;
04685 
04686       memset(&zi, 0, sizeof(zi));
04687       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04688          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04689    }
04690    return 0;
04691 }

static int restart_monitor ( void   )  [static]

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

11602 {
11603    /* If we're supposed to be stopped -- stay stopped */
11604    if (monitor_thread == AST_PTHREADT_STOP)
11605       return 0;
11606    ast_mutex_lock(&monlock);
11607    if (monitor_thread == pthread_self()) {
11608       ast_mutex_unlock(&monlock);
11609       ast_log(LOG_WARNING, "Cannot kill myself\n");
11610       return -1;
11611    }
11612    if (monitor_thread != AST_PTHREADT_NULL) {
11613       /* Wake up the thread */
11614       pthread_kill(monitor_thread, SIGURG);
11615    } else {
11616       /* Start a new monitor */
11617       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11618          ast_mutex_unlock(&monlock);
11619          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11620          return -1;
11621       }
11622    }
11623    ast_mutex_unlock(&monlock);
11624    return 0;
11625 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

05093 {
05094    int res;
05095    if (p->saveconf.confmode) {
05096       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05097       p->saveconf.confmode = 0;
05098       if (res) {
05099          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05100          return -1;
05101       }
05102       ast_debug(1, "Restored conferencing\n");
05103    }
05104    return 0;
05105 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

05000 {
05001    int res;
05002 
05003    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05004    if (res) {
05005       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05006       return -1;
05007    }
05008 
05009    return 0;
05010 }

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

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

05983 {
05984    if (p->bufferoverrideinuse) {
05985       /* faxbuffers are in use, revert them */
05986       struct dahdi_bufferinfo bi = {
05987          .txbufpolicy = p->buf_policy,
05988          .rxbufpolicy = p->buf_policy,
05989          .bufsize = p->bufsize,
05990          .numbufs = p->buf_no
05991       };
05992       int bpres;
05993 
05994       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05995          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
05996       }
05997       p->bufferoverrideinuse = 0;
05998       return bpres;
05999    }
06000 
06001    return -1;
06002 }

static int save_conference ( struct dahdi_pvt p  )  [static]

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

05067 {
05068    struct dahdi_confinfo c;
05069    int res;
05070    if (p->saveconf.confmode) {
05071       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05072       return -1;
05073    }
05074    p->saveconf.chan = 0;
05075    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05076    if (res) {
05077       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05078       p->saveconf.confmode = 0;
05079       return -1;
05080    }
05081    memset(&c, 0, sizeof(c));
05082    c.confmode = DAHDI_CONF_NORMAL;
05083    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05084    if (res) {
05085       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05086       return -1;
05087    }
05088    ast_debug(1, "Disabled conferencing\n");
05089    return 0;
05090 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

05151 {
05152    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05153    int res;
05154    /* Take out of linear mode if necessary */
05155    if (p->subs[SUB_REAL].linear) {
05156       p->subs[SUB_REAL].linear = 0;
05157       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05158    }
05159    while (p->cidpos < p->cidlen) {
05160       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05161       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05162       if (res < 0) {
05163          if (errno == EAGAIN)
05164             return 0;
05165          else {
05166             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05167             return -1;
05168          }
05169       }
05170       if (!res)
05171          return 0;
05172       p->cidpos += res;
05173    }
05174    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05175    ast_free(p->cidspill);
05176    p->cidspill = NULL;
05177    if (p->callwaitcas) {
05178       /* Wait for CID/CW to expire */
05179       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05180       p->cid_suppress_expire = p->cidcwexpire;
05181    } else
05182       restore_conference(p);
05183    return 0;
05184 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

05108 {
05109    p->callwaitcas = 0;
05110    p->cidcwexpire = 0;
05111    p->cid_suppress_expire = 0;
05112    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05113       return -1;
05114    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05115    /* Make sure we account for the end */
05116    p->cidlen += READ_SIZE * 4;
05117    p->cidpos = 0;
05118    send_callerid(p);
05119    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05120    return 0;
05121 }

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

Definition at line 4980 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

04981 {
04982    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
04983 }

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

Definition at line 4963 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

04964 {
04965    struct dahdi_gains g;
04966    int res;
04967 
04968    memset(&g, 0, sizeof(g));
04969    res = ioctl(fd, DAHDI_GETGAINS, &g);
04970    if (res) {
04971       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04972       return res;
04973    }
04974 
04975    fill_rxgain(&g, gain, drc, law);
04976 
04977    return ioctl(fd, DAHDI_SETGAINS, &g);
04978 }

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

Definition at line 4946 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

04947 {
04948    struct dahdi_gains g;
04949    int res;
04950 
04951    memset(&g, 0, sizeof(g));
04952    res = ioctl(fd, DAHDI_GETGAINS, &g);
04953    if (res) {
04954       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04955       return res;
04956    }
04957 
04958    fill_txgain(&g, gain, drc, law);
04959 
04960    return ioctl(fd, DAHDI_SETGAINS, &g);
04961 }

static int setup_dahdi ( int  reload  )  [static]

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

17810 {
17811    int res;
17812    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
17813    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17814    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17815 
17816    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
17817       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
17818    } else {
17819       res = -1;
17820    }
17821    ast_cc_config_params_destroy(default_conf.chan.cc_params);
17822    ast_cc_config_params_destroy(base_conf.chan.cc_params);
17823    ast_cc_config_params_destroy(conf.chan.cc_params);
17824 
17825    return res;
17826 }

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

References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, deep_copy_dahdi_chan_conf(), default_jbconf, global_jbconf, ast_variable::lineno, LOG_NOTICE, mwimonitornotify, ast_variable::name, ast_variable::next, prepare_pri(), pri_create_spanmap(), pri_create_trunkgroup(), PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_start_pri(), and ast_variable::value.

Referenced by setup_dahdi().

17567 {
17568    struct ast_config *cfg;
17569    struct ast_config *ucfg;
17570    struct ast_variable *v;
17571    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17572    const char *cat;
17573    int res;
17574 
17575 #ifdef HAVE_PRI
17576    char *c;
17577    int spanno;
17578    int i;
17579    int logicalspan;
17580    int trunkgroup;
17581    int dchannels[SIG_PRI_NUM_DCHANS];
17582 #endif
17583 
17584    cfg = ast_config_load(config, config_flags);
17585 
17586    /* Error if we have no config file */
17587    if (!cfg) {
17588       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17589       return 0;
17590    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17591       ucfg = ast_config_load("users.conf", config_flags);
17592       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17593          return 0;
17594       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17595          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17596          return 0;
17597       }
17598       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17599       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17600          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17601          ast_config_destroy(ucfg);
17602          return 0;
17603       }
17604    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17605       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17606       return 0;
17607    } else {
17608       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17609       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17610          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17611          ast_config_destroy(cfg);
17612          return 0;
17613       }
17614    }
17615 
17616    /* It's a little silly to lock it, but we might as well just to be sure */
17617    ast_mutex_lock(&iflock);
17618 #ifdef HAVE_PRI
17619    if (reload != 1) {
17620       /* Process trunkgroups first */
17621       v = ast_variable_browse(cfg, "trunkgroups");
17622       while (v) {
17623          if (!strcasecmp(v->name, "trunkgroup")) {
17624             trunkgroup = atoi(v->value);
17625             if (trunkgroup > 0) {
17626                if ((c = strchr(v->value, ','))) {
17627                   i = 0;
17628                   memset(dchannels, 0, sizeof(dchannels));
17629                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
17630                      dchannels[i] = atoi(c + 1);
17631                      if (dchannels[i] < 0) {
17632                         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);
17633                      } else
17634                         i++;
17635                      c = strchr(c + 1, ',');
17636                   }
17637                   if (i) {
17638                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17639                         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);
17640                   } else
17641                         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");
17642                   } else
17643                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17644                } else
17645                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17646             } else
17647                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17648          } else if (!strcasecmp(v->name, "spanmap")) {
17649             spanno = atoi(v->value);
17650             if (spanno > 0) {
17651                if ((c = strchr(v->value, ','))) {
17652                   trunkgroup = atoi(c + 1);
17653                   if (trunkgroup > 0) {
17654                      if ((c = strchr(c + 1, ',')))
17655                         logicalspan = atoi(c + 1);
17656                      else
17657                         logicalspan = 0;
17658                      if (logicalspan >= 0) {
17659                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17660                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17661                      } else
17662                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17663                      } else
17664                         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);
17665                   } else
17666                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17667                } else
17668                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17669             } else
17670                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17671          } else {
17672             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17673          }
17674          v = v->next;
17675       }
17676    }
17677 #endif
17678 
17679    /* Copy the default jb config over global_jbconf */
17680    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17681 
17682    mwimonitornotify[0] = '\0';
17683 
17684    v = ast_variable_browse(cfg, "channels");
17685    if ((res = process_dahdi(base_conf, "", v, reload, 0))) {
17686       ast_mutex_unlock(&iflock);
17687       ast_config_destroy(cfg);
17688       if (ucfg) {
17689          ast_config_destroy(ucfg);
17690       }
17691       return res;
17692    }
17693 
17694    /* Now get configuration from all normal sections in chan_dahdi.conf: */
17695    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17696       /* [channels] and [trunkgroups] are used. Let's also reserve
17697        * [globals] and [general] for future use
17698        */
17699       if (!strcasecmp(cat, "general") ||
17700          !strcasecmp(cat, "trunkgroups") ||
17701          !strcasecmp(cat, "globals") ||
17702          !strcasecmp(cat, "channels")) {
17703          continue;
17704       }
17705 
17706       /* Copy base_conf to conf. */
17707       deep_copy_dahdi_chan_conf(conf, base_conf);
17708 
17709       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17710          ast_mutex_unlock(&iflock);
17711          ast_config_destroy(cfg);
17712          if (ucfg) {
17713             ast_config_destroy(ucfg);
17714          }
17715          return res;
17716       }
17717    }
17718 
17719    ast_config_destroy(cfg);
17720 
17721    if (ucfg) {
17722       const char *chans;
17723 
17724       /* Reset base_conf, so things dont leak from dahdi_chan.conf */
17725       deep_copy_dahdi_chan_conf(base_conf, default_conf);
17726       process_dahdi(base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17727 
17728       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17729          if (!strcasecmp(cat, "general")) {
17730             continue;
17731          }
17732 
17733          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17734 
17735          if (ast_strlen_zero(chans)) {
17736             continue;
17737          }
17738 
17739          /* Copy base_conf to conf. */
17740          deep_copy_dahdi_chan_conf(conf, base_conf);
17741 
17742          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17743             ast_config_destroy(ucfg);
17744             ast_mutex_unlock(&iflock);
17745             return res;
17746          }
17747       }
17748       ast_config_destroy(ucfg);
17749    }
17750    ast_mutex_unlock(&iflock);
17751 
17752 #ifdef HAVE_PRI
17753    if (reload != 1) {
17754       int x;
17755       for (x = 0; x < NUM_SPANS; x++) {
17756          if (pris[x].pri.pvts[0]) {
17757             prepare_pri(pris + x);
17758             if (sig_pri_start_pri(&pris[x].pri)) {
17759                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17760                return -1;
17761             } else
17762                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17763          }
17764       }
17765    }
17766 #endif
17767 #if defined(HAVE_SS7)
17768    if (reload != 1) {
17769       int x;
17770       for (x = 0; x < NUM_SPANS; x++) {
17771          if (linksets[x].ss7.ss7) {
17772             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
17773             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
17774                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17775                return -1;
17776             } else
17777                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17778          }
17779       }
17780    }
17781 #endif   /* defined(HAVE_SS7) */
17782 #ifdef HAVE_OPENR2
17783    if (reload != 1) {
17784       int x;
17785       for (x = 0; x < r2links_count; x++) {
17786          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17787             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17788             return -1;
17789          } else {
17790             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17791          }
17792       }
17793    }
17794 #endif
17795    /* And start the monitor for the first time */
17796    restart_monitor();
17797    return 0;
17798 }

static int sig_pri_tone_to_dahditone ( enum sig_pri_tone  tone  )  [static]

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

02974 {
02975    switch (tone) {
02976    case SIG_PRI_TONE_RINGTONE:
02977       return DAHDI_TONE_RINGTONE;
02978    case SIG_PRI_TONE_STUTTER:
02979       return DAHDI_TONE_STUTTER;
02980    case SIG_PRI_TONE_CONGESTION:
02981       return DAHDI_TONE_CONGESTION;
02982    case SIG_PRI_TONE_DIALTONE:
02983       return DAHDI_TONE_DIALTONE;
02984    case SIG_PRI_TONE_DIALRECALL:
02985       return DAHDI_TONE_DIALRECALL;
02986    case SIG_PRI_TONE_INFO:
02987       return DAHDI_TONE_INFO;
02988    case SIG_PRI_TONE_BUSY:
02989       return DAHDI_TONE_BUSY;
02990    default:
02991       return -1;
02992    }
02993 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 11877 of file chan_dahdi.c.

11878 {
11879    return sigtype;
11880 }

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

Definition at line 16296 of file chan_dahdi.c.

Referenced by parse_spanchan().

16297 {
16298    for (; *str; str++) {
16299       if (*str == char1) {
16300          *str = char2;
16301       }
16302    }
16303 }

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

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

04139 {
04140    int tchan;
04141    int tinthreeway;
04142    struct ast_channel *towner;
04143 
04144    ast_debug(1, "Swapping %d and %d\n", a, b);
04145 
04146    tchan = p->subs[a].chan;
04147    towner = p->subs[a].owner;
04148    tinthreeway = p->subs[a].inthreeway;
04149 
04150    p->subs[a].chan = p->subs[b].chan;
04151    p->subs[a].owner = p->subs[b].owner;
04152    p->subs[a].inthreeway = p->subs[b].inthreeway;
04153 
04154    p->subs[b].chan = tchan;
04155    p->subs[b].owner = towner;
04156    p->subs[b].inthreeway = tinthreeway;
04157 
04158    if (p->subs[a].owner)
04159       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04160    if (p->subs[b].owner)
04161       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04162    wakeup_sub(p, a);
04163    wakeup_sub(p, b);
04164 }

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

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

04285 {
04286    if (!x) {
04287       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04288       return -1;
04289    }
04290    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04291    dahdi_close_sub(p, x);
04292    p->subs[x].linear = 0;
04293    p->subs[x].chan = 0;
04294    p->subs[x].owner = NULL;
04295    p->subs[x].inthreeway = 0;
04296    p->polarity = POLARITY_IDLE;
04297    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04298    return 0;
04299 }

static int unload_module ( void   )  [static]

Definition at line 16280 of file chan_dahdi.c.

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

16281 {
16282 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16283    int y;
16284 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16285 #ifdef HAVE_PRI
16286    for (y = 0; y < NUM_SPANS; y++)
16287       ast_mutex_destroy(&pris[y].pri.lock);
16288 #endif
16289 #if defined(HAVE_SS7)
16290    for (y = 0; y < NUM_SPANS; y++)
16291       ast_mutex_destroy(&linksets[y].ss7.lock);
16292 #endif   /* defined(HAVE_SS7) */
16293    return __unload_module();
16294 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

04694 {
04695    int needconf = 0;
04696    int x;
04697    int useslavenative;
04698    struct dahdi_pvt *slave = NULL;
04699 
04700    useslavenative = isslavenative(p, &slave);
04701    /* Start with the obvious, general stuff */
04702    for (x = 0; x < 3; x++) {
04703       /* Look for three way calls */
04704       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04705          conf_add(p, &p->subs[x], x, 0);
04706          needconf++;
04707       } else {
04708          conf_del(p, &p->subs[x], x);
04709       }
04710    }
04711    /* If we have a slave, add him to our conference now. or DAX
04712       if this is slave native */
04713    for (x = 0; x < MAX_SLAVES; x++) {
04714       if (p->slaves[x]) {
04715          if (useslavenative)
04716             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04717          else {
04718             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04719             needconf++;
04720          }
04721       }
04722    }
04723    /* If we're supposed to be in there, do so now */
04724    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04725       if (useslavenative)
04726          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04727       else {
04728          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04729          needconf++;
04730       }
04731    }
04732    /* If we have a master, add ourselves to his conference */
04733    if (p->master) {
04734       if (isslavenative(p->master, NULL)) {
04735          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04736       } else {
04737          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04738       }
04739    }
04740    if (!needconf) {
04741       /* Nobody is left (or should be left) in our conference.
04742          Kill it. */
04743       p->confno = -1;
04744    }
04745    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04746    return 0;
04747 }

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

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

03652 {
03653    dahdi_lock_sub_owner(p, a);
03654    if (p->subs[a].owner) {
03655       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03656       ast_channel_unlock(p->subs[a].owner);
03657    }
03658 }


Variable Documentation

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

Definition at line 18188 of file chan_dahdi.c.

int alarm

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

Referenced by mwi_send_process_buffer().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 18188 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

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

Referenced by handle_dahdi_show_cadences().

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

Definition at line 320 of file chan_dahdi.c.

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

Definition at line 5840 of file chan_dahdi.c.

struct analog_callback dahdi_analog_callbacks [static]

Definition at line 3529 of file chan_dahdi.c.

struct ast_data_handler dahdi_channels_data_provider [static]

Initial value:

Definition at line 17969 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

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

Referenced by load_module().

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 14574 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct sig_pri_callback dahdi_pri_callbacks [static]

Definition at line 3269 of file chan_dahdi.c.

Referenced by prepare_pri().

struct ast_cli_entry dahdi_pri_cli[] [static]

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

openr2_transcoder_interface_t dahdi_r2_transcode_iface [static]

Initial value:

Definition at line 4131 of file chan_dahdi.c.

char* dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility" [static]

Definition at line 5777 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 5750 of file chan_dahdi.c.

struct ast_data_handler dahdi_status_data_provider [static]

Initial value:

Definition at line 17964 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 269 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 393 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 394 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 407 of file chan_dahdi.c.

int dtmfcid_level = 256 [static]

Definition at line 412 of file chan_dahdi.c.

const char* const events[] [static]

Definition at line 4408 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

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

Referenced by analog_ss_thread(), and mgcp_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 277 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 436 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 1297 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 1296 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 433 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 257 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 430 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 448 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 444 of file chan_dahdi.c.

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

int mwilevel = 512 [static]

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

Referenced by notify_message(), and setup_dahdi_int().

char* name

Definition at line 4432 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 363 of file chan_dahdi.c.

Referenced by handle_dahdi_show_cadences(), and my_set_cadence().

int num_restart_pending = 0 [static]

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

char parkinglot[AST_MAX_EXTENSION] = "" [static]

Default parking lot for this channel

Definition at line 396 of file chan_dahdi.c.

Referenced by __find_callno(), ast_iax2_new(), build_parkinglot(), build_peer(), build_user(), builtin_atxfer(), check_access(), check_peer_ok(), copy_parkinglot(), create_addr_from_peer(), dahdi_new(), find_parkinglot(), find_parkinglot_by_exten_cb(), find_parkinglot_by_position_cb(), findparkinglotname(), func_channel_write_real(), gtalk_load_config(), gtalk_new(), park_exec_full(), park_space_reserve(), parkinglot_addref(), parkinglot_cmp_cb(), parkinglot_hash_cb(), parkinglot_is_marked_cb(), parkinglot_markall_cb(), parkinglot_unref(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), skinny_new(), and store_config_core().

int pridebugfd = -1 [static]

Definition at line 419 of file chan_dahdi.c.

Referenced by dahdi_pri_error(), dahdi_pri_message(), and handle_pri_set_debug_file().

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

Definition at line 439 of file chan_dahdi.c.

Referenced by dahdi_pri_error(), dahdi_pri_message(), and handle_pri_set_debug_file().

char pridebugfilename[1024] = "" [static]

Definition at line 420 of file chan_dahdi.c.

Referenced by handle_pri_set_debug_file().

struct dahdi_pri pris[NUM_SPANS] [static]

Definition at line 576 of file chan_dahdi.c.

Referenced by complete_span_helper(), dahdi_devicestate(), dahdi_pri_error(), dahdi_pri_message(), dahdi_restart(), destroy_all_channels(), handle_pri_debug(), handle_pri_service_generic(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), prepare_pri(), pri_create_spanmap(), pri_create_trunkgroup(), and pri_resolve_span().

char progzone[10] = "" [static]

Definition at line 404 of file chan_dahdi.c.

Referenced by dahdi_new().

struct dahdi_mfcr2** r2links [static]

Definition at line 561 of file chan_dahdi.c.

Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().

int r2links_count = 0 [static]

Definition at line 563 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 416 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 451 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 509 of file chan_dahdi.c.

struct dahdi_pvt* round_robin[32] [static]

Round robin search locations.

Definition at line 3598 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 449 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 452 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 450 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 609 of file chan_dahdi.c.

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

const char tdesc[] [static]

Definition at line 299 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 406 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 364 of file chan_dahdi.c.


Generated on Mon Jun 27 16:51:05 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7