Asterisk - The Open Source Telephony Project  GIT-master-93d0901
Data Structures | Macros | Functions | Variables
chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <sys/sysmacros.h>
#include <signal.h>
#include <sys/stat.h>
#include <math.h>
#include "sig_analog.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/pickup.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/mwi.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/devicestate.h"
#include "asterisk/paths.h"
#include "asterisk/ccss.h"
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/parking.h"
#include "asterisk/format_cache.h"
#include "chan_dahdi.h"
#include "dahdi/bridge_native_dahdi.h"
Include dependency graph for chan_dahdi.c:

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_starting_point
 
struct  mwi_thread_data
 

Macros

#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 CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
 
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID. More...
 
#define DEFAULT_DIALTONE_DETECT_TIMEOUT   ((10000 * 8) / READ_SIZE)
 
#define DEFAULT_RINGT   ((8000 * 8) / READ_SIZE)
 
#define END_SILENCE_LEN   400
 
#define FORMAT   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
 
#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
 
#define FORMAT2   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
 
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
 
#define gen_pvt_field_callback(type, field)
 
#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 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. More...
 
#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 READ_SIZE   160
 
#define REPORT_CHANNEL_ALARMS   1
 
#define REPORT_SPAN_ALARMS   2
 
#define sig2str   dahdi_sig2str
 
#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */
 
#define TRAILER_MS   5
 
#define TRANSFER   0
 

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)
 
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 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)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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)
 
static int bump_gains (struct dahdi_pvt *p)
 
static int calc_energy (const unsigned char *buf, int len, struct ast_format *law)
 
static int canmatch_featurecode (const char *pickupexten, const char *exten)
 
static int check_for_conference (struct dahdi_pvt *p)
 
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)
 
static void dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan)
 
static int dahdi_answer (struct ast_channel *ast)
 
static int dahdi_call (struct ast_channel *ast, const 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(). More...
 
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
 
static void dahdi_close (int fd)
 
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
 
void dahdi_conf_update (struct dahdi_pvt *p)
 
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
 
static int dahdi_create_channel_range (int start, int end)
 
static char * dahdi_create_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void dahdi_destroy_channel_range (int start, int end)
 
static char * dahdi_destroy_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_devicestate (const char *data)
 
static int dahdi_dial_str (struct dahdi_pvt *pvt, int operation, const char *dial_str)
 
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 int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel More...
 
void dahdi_dtmf_detect_disable (struct dahdi_pvt *p)
 
void dahdi_dtmf_detect_enable (struct dahdi_pvt *p)
 
void dahdi_ec_disable (struct dahdi_pvt *p)
 
void dahdi_ec_enable (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. More...
 
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_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx)
 
void dahdi_master_slave_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
 
void dahdi_master_slave_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
 
static struct ast_channeldahdi_new (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
 
static struct ast_channeldahdi_new_callid_clean (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
 
static int dahdi_open (char *fn)
 
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 struct ast_framedahdi_read (struct ast_channel *ast)
 
static struct ast_channeldahdi_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *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_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_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 void dahdi_softhangup_all (void)
 
static void dahdi_train_ec (struct dahdi_pvt *p)
 
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events. More...
 
static int dahdi_wink (struct dahdi_pvt *p, int index)
 
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
 
static struct ast_manager_event_blobdahdichannel_to_ami (struct stasis_message *msg)
 
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 digit_to_dtmfindex (char digit)
 
static void * do_monitor (void *data)
 
static int drc_sample (int sample, float drc)
 
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
 
static const char * event2str (int event)
 
static void fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law)
 
static void fill_txgain (struct dahdi_gains *g, float gain, float drc, int law)
 
static struct dahdi_pvtfind_channel (int channel)
 
static struct dahdi_pvtfind_channel_from_str (const char *channel)
 
static struct dahdi_pvtfind_next_iface_in_span (struct dahdi_pvt *cur)
 
 gen_pvt_field_callback (int, firstdigit_timeout)
 
 gen_pvt_field_callback (int, interdigit_timeout)
 
 gen_pvt_field_callback (int, matchdigit_timeout)
 
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 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)
 Load the module. More...
 
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
 
static void monitor_pfds_clean (void *arg)
 
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_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
 
static void my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
 
static void my_hangup_polarityswitch (void *pvt)
 
static int my_has_voicemail (void *pvt)
 
static int my_have_progressdetect (void *pvt)
 
static void my_increase_ss_count (void)
 
static int my_is_dialing (void *pvt, enum analog_sub sub)
 
static int my_is_off_hook (void *pvt)
 
static void my_lock_private (void *pvt)
 
static struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, 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 int my_ring (void *pvt)
 
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
 
static void my_set_alarm (void *pvt, int in_alarm)
 
static void my_set_cadence (void *pvt, int *cid_rings, struct ast_channel *ast)
 
static void my_set_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 int my_set_echocanceller (void *pvt, int enable)
 
static void my_set_inthreeway (void *pvt, enum analog_sub sub, int inthreeway)
 
static int my_set_linear_mode (void *pvt, enum analog_sub sub, int linear_mode)
 
static void my_set_needringing (void *pvt, int value)
 
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
 
static void my_set_outgoing (void *pvt, int is_outgoing)
 
static void my_set_polarity (void *pvt, int value)
 
static void my_set_pulsedial (void *pvt, int flag)
 
static void my_set_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, int thereornot)
 Send MWI state change. More...
 
static int parse_buffers_policy (const char *parse, int *num_buffers, int *policy)
 
static void parse_busy_pattern (struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
 
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 void publish_channel_alarm (int channel, const char *alarm_txt)
 
static void publish_channel_alarm_clear (int channel)
 
static void publish_dahdichannel (struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
 Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages. More...
 
static void publish_dnd_state (int channel, const char *status)
 
static void publish_span_alarm (int span, const char *alarm_txt)
 
static void publish_span_alarm_clear (int span)
 
static void release_doomed_pris (void)
 
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 set_hwgain (int fd, float gain, int tx_direction)
 
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 sigtype_to_signalling (int sigtype)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (dahdichannel_type,.to_ami=dahdichannel_to_ami,)
 
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 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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "ccss", .optional_modules = "res_smdi", }
 
struct {
   int   alarm
 
   char *   name
 
alarms []
 
struct analog_callback analog_callbacks
 
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
 
static const 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. More...
 
static const char config [] = "chan_dahdi.conf"
 
static struct ast_cli_entry dahdi_cli []
 
static struct ast_channel_tech dahdi_tech
 
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 struct ast_jb_conf global_jbconf
 
static int has_pseudo
 
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, 0} }
 Protect the interface list (of dahdi_pvt's) More...
 
static const char *const lbostr []
 
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. More...
 
static ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. More...
 
static int mwilevel = 512
 
static char mwimonitornotify [PATH_MAX] = ""
 
static int mwisend_rpas = 0
 
static int num_cadence = 4
 
static int num_restart_pending = 0
 
static int numbufs = 4
 
static char progzone [10] = ""
 
static int report_alarms = REPORT_CHANNEL_ALARMS
 
static ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base. More...
 
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, 0} }
 
const char *const subnames []
 
static const char tdesc [] = "DAHDI Telephony"
 
static int usedistinctiveringdetection = 0
 
static int user_has_defined_cadences = 0
 

Detailed Description

DAHDI for Pseudo TDM.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

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.

Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.

Macro Definition Documentation

◆ ASCII_BYTES_PER_CHAR

#define ASCII_BYTES_PER_CHAR   80

◆ AST_LAW

#define AST_LAW (   p)    (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)

Definition at line 521 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 561 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_INCOMING

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 560 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_OUTGOING

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 559 of file chan_dahdi.c.

◆ CALLPROGRESS_PROGRESS

#define CALLPROGRESS_PROGRESS   1

Definition at line 558 of file chan_dahdi.c.

◆ CALLWAITING_REPEAT_SAMPLES

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

10,000 ms

Definition at line 679 of file chan_dahdi.c.

◆ CALLWAITING_SILENT_SAMPLES

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

300 ms

Definition at line 678 of file chan_dahdi.c.

◆ CALLWAITING_SUPPRESS_SAMPLES

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

100 ms

Definition at line 680 of file chan_dahdi.c.

◆ CANBUSYDETECT

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

Definition at line 593 of file chan_dahdi.c.

◆ CANPROGRESSDETECT

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

Definition at line 594 of file chan_dahdi.c.

◆ CHAN_PSEUDO

#define CHAN_PSEUDO   -2

Definition at line 556 of file chan_dahdi.c.

◆ CIDCW_EXPIRE_SAMPLES

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

500 ms

Definition at line 681 of file chan_dahdi.c.

◆ DEFAULT_CIDRINGS

#define DEFAULT_CIDRINGS   1

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

Note
Define ZHONE_HACK to cause us to go off hook and then back on hook when the user hangs up to reset the state machine so ring works properly. This is used to be able to support kewlstart by putting the zhone in groundstart mode since their forward disconnect supervision is entirely broken even though their documentation says it isn't and their support is entirely unwilling to provide any assistance with their channel banks even though their web site says they support their products for life.

Definition at line 519 of file chan_dahdi.c.

◆ DEFAULT_DIALTONE_DETECT_TIMEOUT

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

10,000 ms

Definition at line 684 of file chan_dahdi.c.

◆ DEFAULT_RINGT

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

8,000 ms

Definition at line 683 of file chan_dahdi.c.

◆ END_SILENCE_LEN

#define END_SILENCE_LEN   400

◆ FORMAT [1/2]

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

◆ FORMAT [2/2]

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

◆ FORMAT2 [1/2]

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

◆ FORMAT2 [2/2]

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

◆ gen_pvt_field_callback

#define gen_pvt_field_callback (   type,
  field 
)
Value:
static type my_get_##field(void *pvt) \
{ \
struct dahdi_pvt *p = pvt; \
return p->field; \
}
static const char type[]
Definition: chan_ooh323.c:109

Definition at line 3326 of file chan_dahdi.c.

◆ GET_CHANNEL

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

Definition at line 1057 of file chan_dahdi.c.

◆ HANGUP

#define HANGUP   1

Definition at line 16207 of file chan_dahdi.c.

◆ HEADER_LEN

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

◆ HEADER_MS

#define HEADER_MS   50

◆ ISTRUNK

#define ISTRUNK (   p)
Value:
((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
(p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
#define SIG_FXSLS
Definition: chan_dahdi.h:747
#define SIG_FXSKS
Definition: chan_dahdi.h:749
#define SIG_FXSGS
Definition: chan_dahdi.h:748
#define SIG_PRI
Definition: chan_dahdi.h:761

Definition at line 590 of file chan_dahdi.c.

◆ MASK_AVAIL

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 675 of file chan_dahdi.c.

◆ MASK_INUSE

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 676 of file chan_dahdi.c.

◆ MAX_CHANLIST_LEN

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

◆ MIN_MS_SINCE_FLASH

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

Definition at line 682 of file chan_dahdi.c.

◆ NEED_MFDETECT

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

Definition at line 525 of file chan_dahdi.c.

◆ NUM_CADENCE_MAX

#define NUM_CADENCE_MAX   25

Definition at line 563 of file chan_dahdi.c.

◆ NUM_SPANS

#define NUM_SPANS   32

Definition at line 553 of file chan_dahdi.c.

◆ POLARITY_IDLE

#define POLARITY_IDLE   0

Definition at line 792 of file chan_dahdi.c.

◆ POLARITY_REV

#define POLARITY_REV   1

Definition at line 793 of file chan_dahdi.c.

◆ PROC_DAHDI_OPT_NOCHAN

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 17831 of file chan_dahdi.c.

◆ PROC_DAHDI_OPT_NOWARN

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 17833 of file chan_dahdi.c.

◆ READ_SIZE

#define READ_SIZE   160

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

Definition at line 673 of file chan_dahdi.c.

◆ REPORT_CHANNEL_ALARMS

#define REPORT_CHANNEL_ALARMS   1

Definition at line 615 of file chan_dahdi.c.

◆ REPORT_SPAN_ALARMS

#define REPORT_SPAN_ALARMS   2

Definition at line 616 of file chan_dahdi.c.

◆ sig2str

#define sig2str   dahdi_sig2str

Definition at line 4437 of file chan_dahdi.c.

◆ SMDI_MD_WAIT_TIMEOUT

#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */

Definition at line 482 of file chan_dahdi.c.

◆ TRAILER_MS

#define TRAILER_MS   5

◆ TRANSFER

#define TRANSFER   0

Definition at line 16206 of file chan_dahdi.c.

Function Documentation

◆ __dahdi_exception()

static struct ast_frame* __dahdi_exception ( struct ast_channel ast)
static

Definition at line 8249 of file chan_dahdi.c.

8250 {
8251  int res;
8252  int idx;
8253  struct ast_frame *f;
8254  int usedindex = -1;
8255  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8256 
8257  if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8258  idx = SUB_REAL;
8259  }
8260 
8261  p->subs[idx].f.frametype = AST_FRAME_NULL;
8262  p->subs[idx].f.datalen = 0;
8263  p->subs[idx].f.samples = 0;
8264  p->subs[idx].f.mallocd = 0;
8265  p->subs[idx].f.offset = 0;
8266  p->subs[idx].f.subclass.integer = 0;
8267  p->subs[idx].f.delivery = ast_tv(0,0);
8268  p->subs[idx].f.src = "dahdi_exception";
8269  p->subs[idx].f.data.ptr = NULL;
8270 
8271 
8272  if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8273  /* If nobody owns us, absorb the event appropriately, otherwise
8274  we loop indefinitely. This occurs when, during call waiting, the
8275  other end hangs up our channel so that it no longer exists, but we
8276  have neither FLASH'd nor ONHOOK'd to signify our desire to
8277  change to the other channel. */
8278  if (p->fake_event) {
8279  res = p->fake_event;
8280  p->fake_event = 0;
8281  } else
8282  res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8283  /* Switch to real if there is one and this isn't something really silly... */
8284  if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8285  (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8286  ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8287  p->owner = p->subs[SUB_REAL].owner;
8288  if (p->owner) {
8289  ast_queue_unhold(p->owner);
8290  }
8291  p->subs[SUB_REAL].needunhold = 1;
8292  }
8293  switch (res) {
8294  case DAHDI_EVENT_ONHOOK:
8295  dahdi_ec_disable(p);
8296  if (p->owner) {
8297  ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8298  dahdi_ring_phone(p);
8299  p->callwaitingrepeat = 0;
8300  p->cidcwexpire = 0;
8301  p->cid_suppress_expire = 0;
8302  } else
8303  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8304  dahdi_conf_update(p);
8305  break;
8306  case DAHDI_EVENT_RINGOFFHOOK:
8307  dahdi_ec_enable(p);
8308  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8309  if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8310  p->subs[SUB_REAL].needanswer = 1;
8311  p->dialing = 0;
8312  }
8313  break;
8314  case DAHDI_EVENT_HOOKCOMPLETE:
8315  case DAHDI_EVENT_RINGERON:
8316  case DAHDI_EVENT_RINGEROFF:
8317  /* Do nothing */
8318  break;
8319  case DAHDI_EVENT_WINKFLASH:
8320  p->flashtime = ast_tvnow();
8321  if (p->owner) {
8322  ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8323  if (ast_channel_state(p->owner) != AST_STATE_UP) {
8324  /* Answer if necessary */
8325  usedindex = dahdi_get_index(p->owner, p, 0);
8326  if (usedindex > -1) {
8327  p->subs[usedindex].needanswer = 1;
8328  }
8330  }
8331  p->callwaitingrepeat = 0;
8332  p->cidcwexpire = 0;
8333  p->cid_suppress_expire = 0;
8334  ast_queue_unhold(p->owner);
8335  p->subs[SUB_REAL].needunhold = 1;
8336  } else
8337  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8338  dahdi_conf_update(p);
8339  break;
8340  default:
8341  ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8342  }
8343  f = &p->subs[idx].f;
8344  return f;
8345  }
8346  if (!(p->radio || (p->oprmode < 0)))
8347  ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8348  /* If it's not us, return NULL immediately */
8349  if (ast != p->owner) {
8350  if (p->owner) {
8351  ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8352  }
8353  f = &p->subs[idx].f;
8354  return f;
8355  }
8356 
8357  f = dahdi_handle_event(ast);
8358  if (!f) {
8359  const char *name = ast_strdupa(ast_channel_name(ast));
8360 
8361  /* Tell the CDR this DAHDI device hung up */
8362  ast_mutex_unlock(&p->lock);
8363  ast_channel_unlock(ast);
8364  ast_set_hangupsource(ast, name, 0);
8365  ast_channel_lock(ast);
8366  ast_mutex_lock(&p->lock);
8367  }
8368  return f;
8369 }
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
static struct ast_frame * dahdi_handle_event(struct ast_channel *ast)
Definition: chan_dahdi.c:7354
static int dahdi_ring_phone(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7069
char * name
Definition: chan_dahdi.c:4343
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:4904
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4620
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4565
static const char * event2str(int event)
Definition: chan_dahdi.c:4364
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4692
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:652
#define SUB_REAL
Definition: chan_dahdi.h:57
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:843
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_fd(const struct ast_channel *chan, int which)
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Definition: channel.c:2498
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1210
#define ast_channel_unlock(chan)
Definition: channel.h:2923
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_UP
Definition: channelstate.h:42
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7469
@ AST_FRAME_NULL
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:451
#define ast_verb(level,...)
Definition: logger.h:462
#define LOG_WARNING
Definition: logger.h:275
#define NULL
Definition: resample.c:96
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
struct timeval delivery
enum ast_frame_type frametype
const char * src
union ast_frame::@253 data
int cid_suppress_expire
Definition: chan_dahdi.h:564
struct timeval flashtime
Definition: chan_dahdi.h:653
int oprmode
Definition: chan_dahdi.h:150
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
struct ast_channel * owner
Definition: chan_dahdi.h:127
int fake_event
Holding place for event injected from outside normal operation.
Definition: chan_dahdi.h:683
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
int cidcwexpire
Definition: chan_dahdi.h:563
int callwaitingrepeat
Definition: chan_dahdi.h:562
ast_mutex_t lock
Definition: chan_dahdi.h:125
int channel
Definition: chan_dahdi.h:554
unsigned int dialing
TRUE if in the process of dialing digits or sending something.
Definition: chan_dahdi.h:250
unsigned int needanswer
Definition: chan_dahdi.h:86
unsigned int needunhold
Definition: chan_dahdi.h:89
struct ast_frame f
Definition: chan_dahdi.h:82
struct ast_channel * owner
Definition: chan_dahdi.h:79
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226

References ast_channel_fd(), ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_debug, AST_FRAME_NULL, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_queue_unhold(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_conf_update(), dahdi_ec_disable(), dahdi_ec_enable(), dahdi_get_event(), dahdi_get_index, dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, event2str(), dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::flashtime, ast_frame::frametype, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_WARNING, ast_frame::mallocd, name, dahdi_subchannel::needanswer, dahdi_subchannel::needunhold, NULL, 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, and dahdi_pvt::subs.

Referenced by dahdi_exception(), and dahdi_read().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 19896 of file chan_dahdi.c.

◆ __unload_module()

static int __unload_module ( void  )
static

Definition at line 17510 of file chan_dahdi.c.

17511 {
17512  struct dahdi_pvt *p;
17513 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17514  int i, j;
17515 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17516 
17517 #ifdef HAVE_PRI
17518  for (i = 0; i < NUM_SPANS; i++) {
17519  if (pris[i].pri.master != AST_PTHREADT_NULL) {
17520  pthread_cancel(pris[i].pri.master);
17521  pthread_kill(pris[i].pri.master, SIGURG);
17522  }
17523  }
17524  ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17525  ast_unregister_application(dahdi_send_keypad_facility_app);
17526 #ifdef HAVE_PRI_PROG_W_CAUSE
17527  ast_unregister_application(dahdi_send_callrerouting_facility_app);
17528 #endif
17529 #endif
17530 #if defined(HAVE_SS7)
17531  for (i = 0; i < NUM_SPANS; i++) {
17532  if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17533  pthread_cancel(linksets[i].ss7.master);
17534  pthread_kill(linksets[i].ss7.master, SIGURG);
17535  }
17536  }
17537  ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17538 #endif /* defined(HAVE_SS7) */
17539 #if defined(HAVE_OPENR2)
17540  dahdi_r2_destroy_links();
17541  ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17542  ast_unregister_application(dahdi_accept_r2_call_app);
17543 #endif
17544 
17546  ast_manager_unregister("DAHDIDialOffhook");
17547  ast_manager_unregister("DAHDIHangup");
17548  ast_manager_unregister("DAHDITransfer");
17549  ast_manager_unregister("DAHDIDNDoff");
17550  ast_manager_unregister("DAHDIDNDon");
17551  ast_manager_unregister("DAHDIShowChannels");
17552  ast_manager_unregister("DAHDIRestart");
17553 #if defined(HAVE_PRI)
17554  ast_manager_unregister("PRIShowSpans");
17555  ast_manager_unregister("PRIDebugSet");
17556  ast_manager_unregister("PRIDebugFileSet");
17557  ast_manager_unregister("PRIDebugFileUnset");
17558 #endif /* defined(HAVE_PRI) */
17560 
17561  /* Hangup all interfaces if they have an owner */
17563  for (p = iflist; p; p = p->next) {
17564  if (p->owner)
17566  }
17568 
17571  pthread_cancel(monitor_thread);
17572  pthread_kill(monitor_thread, SIGURG);
17573  pthread_join(monitor_thread, NULL);
17574  }
17577 
17579 
17580 #if defined(HAVE_PRI)
17581  for (i = 0; i < NUM_SPANS; i++) {
17582  if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17583  pthread_join(pris[i].pri.master, NULL);
17584  }
17585  for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17586  dahdi_close_pri_fd(&(pris[i]), j);
17587  }
17588  sig_pri_stop_pri(&pris[i].pri);
17589  }
17590 #if defined(HAVE_PRI_CCSS)
17591  ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17592  ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17593 #endif /* defined(HAVE_PRI_CCSS) */
17594  sig_pri_unload();
17595 #endif
17596 
17597 #if defined(HAVE_SS7)
17598  for (i = 0; i < NUM_SPANS; i++) {
17599  if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17600  pthread_join(linksets[i].ss7.master, NULL);
17601  }
17602  for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17603  dahdi_close_ss7_fd(&(linksets[i]), j);
17604  }
17605  if (linksets[i].ss7.ss7) {
17606  ss7_destroy(linksets[i].ss7.ss7);
17607  linksets[i].ss7.ss7 = NULL;
17608  }
17609  }
17610 #endif /* defined(HAVE_SS7) */
17612 
17614 
17617  STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
17618  return 0;
17619 }
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
void dahdi_native_unload(void)
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1218
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1255
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
Definition: chan_dahdi.c:625
#define NUM_SPANS
Definition: chan_dahdi.c:553
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:801
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:641
static ast_mutex_t monlock
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing some...
Definition: chan_dahdi.c:636
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1034
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16192
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
Definition: chan_dahdi.c:640
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5635
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1143
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2470
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define AST_PTHREADT_STOP
Definition: lock.h:67
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
void sig_pri_unload(void)
#define SIG_PRI_NUM_DCHANS
Definition: sig_pri.h:239
void sig_pri_stop_pri(struct sig_pri_span *pri)
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
struct ast_format_cap * capabilities
Definition: channel.h:632
struct dahdi_pvt * next
Definition: chan_dahdi.h:168
#define ARRAY_LEN(a)
Definition: utils.h:661

References ao2_cleanup, ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), ast_channel_tech::capabilities, dahdi_cli, dahdi_native_unload(), dahdi_tech, destroy_all_channels(), iflist, iflock, sig_pri_span::master, sig_ss7_linkset::master, monitor_thread, monlock, dahdi_pvt::next, NULL, NUM_SPANS, dahdi_pvt::owner, SIG_PRI_NUM_DCHANS, sig_pri_stop_pri(), sig_pri_unload(), SIG_SS7_NUM_DCHANS, sig_ss7_linkset::ss7, ss_thread_complete, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module(), and unload_module().

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 19896 of file chan_dahdi.c.

◆ _dahdi_get_index()

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

Definition at line 3415 of file chan_dahdi.c.

3416 {
3417  int res;
3418  if (p->subs[SUB_REAL].owner == ast)
3419  res = 0;
3420  else if (p->subs[SUB_CALLWAIT].owner == ast)
3421  res = 1;
3422  else if (p->subs[SUB_THREEWAY].owner == ast)
3423  res = 2;
3424  else {
3425  res = -1;
3426  if (!nullok)
3428  "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3429  ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3430  }
3431  return res;
3432 }
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58

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

◆ action_dahdidialoffhook()

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

Definition at line 16344 of file chan_dahdi.c.

16345 {
16346  struct dahdi_pvt *p;
16347  const char *channel = astman_get_header(m, "DAHDIChannel");
16348  const char *number = astman_get_header(m, "Number");
16349  int i;
16350 
16351  if (ast_strlen_zero(channel)) {
16352  astman_send_error(s, m, "No channel specified");
16353  return 0;
16354  }
16355  if (ast_strlen_zero(number)) {
16356  astman_send_error(s, m, "No number specified");
16357  return 0;
16358  }
16360  if (!p) {
16361  astman_send_error(s, m, "No such channel");
16362  return 0;
16363  }
16364  if (!p->owner) {
16365  astman_send_error(s, m, "Channel does not have it's owner");
16366  return 0;
16367  }
16368  for (i = 0; i < strlen(number); i++) {
16369  struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16370  dahdi_queue_frame(p, &f);
16371  }
16372  astman_send_ack(s, m, "DAHDIDialOffhook");
16373  return 0;
16374 }
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3472
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16248
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:2820
#define AST_FRAME_DTMF
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Number structure.
Definition: app_followme.c:154

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

Referenced by load_module().

◆ action_dahdidndoff()

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

Definition at line 16279 of file chan_dahdi.c.

16280 {
16281  struct dahdi_pvt *p;
16282  const char *channel = astman_get_header(m, "DAHDIChannel");
16283 
16284  if (ast_strlen_zero(channel)) {
16285  astman_send_error(s, m, "No channel specified");
16286  return 0;
16287  }
16289  if (!p) {
16290  astman_send_error(s, m, "No such channel");
16291  return 0;
16292  }
16293  dahdi_dnd(p, 0);
16294  astman_send_ack(s, m, "DND Disabled");
16295  return 0;
16296 }
static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
Definition: chan_dahdi.c:9434

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

Referenced by load_module().

◆ action_dahdidndon()

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

Definition at line 16260 of file chan_dahdi.c.

16261 {
16262  struct dahdi_pvt *p;
16263  const char *channel = astman_get_header(m, "DAHDIChannel");
16264 
16265  if (ast_strlen_zero(channel)) {
16266  astman_send_error(s, m, "No channel specified");
16267  return 0;
16268  }
16270  if (!p) {
16271  astman_send_error(s, m, "No such channel");
16272  return 0;
16273  }
16274  dahdi_dnd(p, 1);
16275  astman_send_ack(s, m, "DND Enabled");
16276  return 0;
16277 }

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

Referenced by load_module().

◆ action_dahdirestart()

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

Definition at line 15534 of file chan_dahdi.c.

15535 {
15536  if (dahdi_restart() != 0) {
15537  astman_send_error(s, m, "Failed rereading DAHDI configuration");
15538  return 1;
15539  }
15540  astman_send_ack(s, m, "DAHDIRestart: Success");
15541  return 0;
15542 }
static int dahdi_restart(void)
Definition: chan_dahdi.c:15396

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

Referenced by load_module().

◆ action_dahdishowchannels()

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

Definition at line 16376 of file chan_dahdi.c.

16377 {
16378  struct dahdi_pvt *tmp = NULL;
16379  const char *id = astman_get_header(m, "ActionID");
16380  const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16381  char idText[256];
16382  int channels = 0;
16383  int dahdichanquery;
16384 
16385  if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16386  /* Not numeric string. */
16387  dahdichanquery = -1;
16388  }
16389 
16390  idText[0] = '\0';
16391  if (!ast_strlen_zero(id)) {
16392  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16393  }
16394 
16395  astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16396 
16398 
16399  for (tmp = iflist; tmp; tmp = tmp->next) {
16400  if (tmp->channel > 0) {
16401  int alm;
16402 
16403  /* If a specific channel is queried for, only deliver status for that channel */
16404  if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16405  continue;
16406 
16407  alm = get_alarms(tmp);
16408  channels++;
16409  if (tmp->owner) {
16410  /* Add data if we have a current call */
16411  astman_append(s,
16412  "Event: DAHDIShowChannels\r\n"
16413  "DAHDIChannel: %d\r\n"
16414  "Channel: %s\r\n"
16415  "Uniqueid: %s\r\n"
16416  "AccountCode: %s\r\n"
16417  "Signalling: %s\r\n"
16418  "SignallingCode: %d\r\n"
16419  "Context: %s\r\n"
16420  "DND: %s\r\n"
16421  "Alarm: %s\r\n"
16422  "Description: %s\r\n"
16423  "%s"
16424  "\r\n",
16425  tmp->channel,
16426  ast_channel_name(tmp->owner),
16427  ast_channel_uniqueid(tmp->owner),
16428  ast_channel_accountcode(tmp->owner),
16429  sig2str(tmp->sig),
16430  tmp->sig,
16431  tmp->context,
16432  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16433  alarm2str(alm),
16434  tmp->description, idText);
16435  } else {
16436  astman_append(s,
16437  "Event: DAHDIShowChannels\r\n"
16438  "DAHDIChannel: %d\r\n"
16439  "Signalling: %s\r\n"
16440  "SignallingCode: %d\r\n"
16441  "Context: %s\r\n"
16442  "DND: %s\r\n"
16443  "Alarm: %s\r\n"
16444  "Description: %s\r\n"
16445  "%s"
16446  "\r\n",
16447  tmp->channel, sig2str(tmp->sig), tmp->sig,
16448  tmp->context,
16449  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16450  alarm2str(alm),
16451  tmp->description, idText);
16452  }
16453  }
16454  }
16455 
16457 
16458  astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16459  astman_append(s, "Items: %d\r\n", channels);
16461  return 0;
16462 }
static int tmp()
Definition: bt_open.c:389
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4354
#define sig2str
Definition: chan_dahdi.c:4437
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7172
const char * ast_channel_accountcode(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
static struct channel_usage channels
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080

References alarm2str(), ast_channel_accountcode(), ast_channel_name(), ast_channel_uniqueid(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), channels, dahdi_dnd(), get_alarms(), iflist, iflock, NULL, sig2str, and tmp().

Referenced by load_module().

◆ action_transfer()

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

Definition at line 16298 of file chan_dahdi.c.

16299 {
16300  struct dahdi_pvt *p;
16301  const char *channel = astman_get_header(m, "DAHDIChannel");
16302 
16303  if (ast_strlen_zero(channel)) {
16304  astman_send_error(s, m, "No channel specified");
16305  return 0;
16306  }
16308  if (!p) {
16309  astman_send_error(s, m, "No such channel");
16310  return 0;
16311  }
16312  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16313  astman_send_error(s, m, "Channel signaling is not analog");
16314  return 0;
16315  }
16317  astman_send_ack(s, m, "DAHDITransfer");
16318  return 0;
16319 }
#define TRANSFER
Definition: chan_dahdi.c:16206
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16209
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:802

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

Referenced by load_module().

◆ action_transferhangup()

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

Definition at line 16321 of file chan_dahdi.c.

16322 {
16323  struct dahdi_pvt *p;
16324  const char *channel = astman_get_header(m, "DAHDIChannel");
16325 
16326  if (ast_strlen_zero(channel)) {
16327  astman_send_error(s, m, "No channel specified");
16328  return 0;
16329  }
16331  if (!p) {
16332  astman_send_error(s, m, "No such channel");
16333  return 0;
16334  }
16335  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16336  astman_send_error(s, m, "Channel signaling is not analog");
16337  return 0;
16338  }
16340  astman_send_ack(s, m, "DAHDIHangup");
16341  return 0;
16342 }
#define HANGUP
Definition: chan_dahdi.c:16207

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

Referenced by load_module().

◆ alarm2str()

static char* alarm2str ( int  alm)
static

Definition at line 4354 of file chan_dahdi.c.

4355 {
4356  int x;
4357  for (x = 0; x < ARRAY_LEN(alarms); x++) {
4358  if (alarms[x].alarm & alm)
4359  return alarms[x].name;
4360  }
4361  return alm ? "Unknown Alarm" : "No Alarm";
4362 }
int alarm
Definition: chan_dahdi.c:4342
static struct @104 alarms[]

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

◆ alloc_sub()

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

Definition at line 4149 of file chan_dahdi.c.

4150 {
4151  struct dahdi_bufferinfo bi;
4152  int res;
4153  if (p->subs[x].dfd >= 0) {
4154  ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4155  return -1;
4156  }
4157 
4158  p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4159  if (p->subs[x].dfd <= -1) {
4160  ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4161  return -1;
4162  }
4163 
4164  res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4165  if (!res) {
4166  bi.txbufpolicy = p->buf_policy;
4167  bi.rxbufpolicy = p->buf_policy;
4168  bi.numbufs = p->buf_no;
4169  res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4170  if (res < 0) {
4171  ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4172  }
4173  } else
4174  ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4175 
4176  if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4177  ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4178  dahdi_close_sub(p, x);
4179  p->subs[x].dfd = -1;
4180  return -1;
4181  }
4182  ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4183  return 0;
4184 }
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4068
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4121
const char *const subnames[]
Definition: chan_dahdi.c:795
int errno
int buf_policy
Definition: chan_dahdi.h:140
int buf_no
Definition: chan_dahdi.h:139

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(), dahdi_handle_event(), and my_allocate_sub().

◆ analog_ss_thread()

static void * analog_ss_thread ( void *  data)
static

Definition at line 9480 of file chan_dahdi.c.

9481 {
9482  struct ast_channel *chan = data;
9483  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9484  char exten[AST_MAX_EXTENSION] = "";
9485  char exten2[AST_MAX_EXTENSION] = "";
9486  unsigned char buf[256];
9487  char dtmfcid[300];
9488  char dtmfbuf[300];
9489  struct callerid_state *cs = NULL;
9490  char *name = NULL, *number = NULL;
9491  int distMatches;
9492  int curRingData[3];
9493  int receivedRingT;
9494  int counter1;
9495  int counter;
9496  int samples = 0;
9497  struct ast_smdi_md_message *smdi_msg = NULL;
9498  int flags = 0;
9499  int i;
9500  int timeout;
9501  int getforward = 0;
9502  char *s1, *s2;
9503  int len = 0;
9504  int res;
9505  int idx;
9506  RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
9507  const char *pickupexten;
9508 
9510  ss_thread_count++;
9512  /* in the bizarre case where the channel has become a zombie before we
9513  even get started here, abort safely
9514  */
9515  if (!p) {
9516  ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9517  ast_hangup(chan);
9518  goto quit;
9519  }
9520  ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
9521  idx = dahdi_get_index(chan, p, 1);
9522  if (idx < 0) {
9523  ast_log(LOG_WARNING, "Huh?\n");
9524  ast_hangup(chan);
9525  goto quit;
9526  }
9527 
9528  ast_channel_lock(chan);
9529  pickup_cfg = ast_get_chan_features_pickup_config(chan);
9530  if (!pickup_cfg) {
9531  ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9532  pickupexten = "";
9533  } else {
9534  pickupexten = ast_strdupa(pickup_cfg->pickupexten);
9535  }
9536  ast_channel_unlock(chan);
9537 
9538  if (p->dsp)
9539  ast_dsp_digitreset(p->dsp);
9540  switch (p->sig) {
9541  case SIG_FEATD:
9542  case SIG_FEATDMF:
9543  case SIG_FEATDMF_TA:
9544  case SIG_E911:
9545  case SIG_FGC_CAMAMF:
9546  case SIG_FEATB:
9547  case SIG_EMWINK:
9548  case SIG_SF_FEATD:
9549  case SIG_SF_FEATDMF:
9550  case SIG_SF_FEATB:
9551  case SIG_SFWINK:
9552  if (dahdi_wink(p, idx))
9553  goto quit;
9554  /* Fall through */
9555  case SIG_EM:
9556  case SIG_EM_E1:
9557  case SIG_SF:
9558  case SIG_FGC_CAMA:
9559  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9560  if (p->dsp)
9561  ast_dsp_digitreset(p->dsp);
9562  /* set digit mode appropriately */
9563  if (p->dsp) {
9564  if (NEED_MFDETECT(p))
9566  else
9568  }
9569  memset(dtmfbuf, 0, sizeof(dtmfbuf));
9570  /* Wait for the first digit only if immediate=no */
9571  if (!p->immediate)
9572  /* Wait for the first digit (up to 5 seconds). */
9573  res = ast_waitfordigit(chan, 5000);
9574  else
9575  res = 0;
9576  if (res > 0) {
9577  /* save first char */
9578  dtmfbuf[0] = res;
9579  switch (p->sig) {
9580  case SIG_FEATD:
9581  case SIG_SF_FEATD:
9582  res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9583  if (res > 0)
9584  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9585  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9586  break;
9587  case SIG_FEATDMF_TA:
9588  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9589  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9590  if (dahdi_wink(p, idx)) goto quit;
9591  dtmfbuf[0] = 0;
9592  /* Wait for the first digit (up to 5 seconds). */
9593  res = ast_waitfordigit(chan, 5000);
9594  if (res <= 0) break;
9595  dtmfbuf[0] = res;
9596  /* fall through intentionally */
9597  case SIG_FEATDMF:
9598  case SIG_E911:
9599  case SIG_FGC_CAMAMF:
9600  case SIG_SF_FEATDMF:
9601  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9602  /* if international caca, do it again to get real ANO */
9603  if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
9604  {
9605  if (dahdi_wink(p, idx)) goto quit;
9606  dtmfbuf[0] = 0;
9607  /* Wait for the first digit (up to 5 seconds). */
9608  res = ast_waitfordigit(chan, 5000);
9609  if (res <= 0) break;
9610  dtmfbuf[0] = res;
9611  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9612  }
9613  if (res > 0) {
9614  /* if E911, take off hook */
9615  if (p->sig == SIG_E911)
9616  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9617  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
9618  }
9619  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9620  break;
9621  case SIG_FEATB:
9622  case SIG_SF_FEATB:
9623  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9624  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9625  break;
9626  case SIG_EMWINK:
9627  /* if we received a '*', we are actually receiving Feature Group D
9628  dial syntax, so use that mode; otherwise, fall through to normal
9629  mode
9630  */
9631  if (res == '*') {
9632  res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9633  if (res > 0)
9634  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9635  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9636  break;
9637  }
9638  default:
9639  /* If we got the first digit, get the rest */
9640  len = 1;
9641  dtmfbuf[len] = '\0';
9642  while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9643  if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9644  timeout = p->matchdigit_timeout;
9645  } else {
9646  timeout = p->interdigit_timeout;
9647  }
9648  res = ast_waitfordigit(chan, timeout);
9649  if (res < 0) {
9650  ast_debug(1, "waitfordigit returned < 0...\n");
9651  ast_hangup(chan);
9652  goto quit;
9653  } else if (res) {
9654  dtmfbuf[len++] = res;
9655  dtmfbuf[len] = '\0';
9656  } else {
9657  break;
9658  }
9659  }
9660  break;
9661  }
9662  }
9663  if (res == -1) {
9664  ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
9665  ast_hangup(chan);
9666  goto quit;
9667  } else if (res < 0) {
9668  ast_debug(1, "Got hung up before digits finished\n");
9669  ast_hangup(chan);
9670  goto quit;
9671  }
9672 
9673  if (p->sig == SIG_FGC_CAMA) {
9674  char anibuf[100];
9675 
9676  if (ast_safe_sleep(chan,1000) == -1) {
9677  ast_hangup(chan);
9678  goto quit;
9679  }
9680  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9682  res = my_getsigstr(chan, anibuf, "#", 10000);
9683  if ((res > 0) && (strlen(anibuf) > 2)) {
9684  if (anibuf[strlen(anibuf) - 1] == '#')
9685  anibuf[strlen(anibuf) - 1] = 0;
9686  ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
9687  }
9689  }
9690 
9691  ast_copy_string(exten, dtmfbuf, sizeof(exten));
9692  if (ast_strlen_zero(exten))
9693  ast_copy_string(exten, "s", sizeof(exten));
9694  if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
9695  /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
9696  if (exten[0] == '*') {
9697  char *stringp=NULL;
9698  ast_copy_string(exten2, exten, sizeof(exten2));
9699  /* Parse out extension and callerid */
9700  stringp=exten2 +1;
9701  s1 = strsep(&stringp, "*");
9702  s2 = strsep(&stringp, "*");
9703  if (s2) {
9704  if (!ast_strlen_zero(p->cid_num))
9705  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9706  else
9707  ast_set_callerid(chan, s1, NULL, s1);
9708  ast_copy_string(exten, s2, sizeof(exten));
9709  } else
9710  ast_copy_string(exten, s1, sizeof(exten));
9711  } else if (p->sig == SIG_FEATD)
9712  ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
9713  }
9714  if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
9715  if (exten[0] == '*') {
9716  char *stringp=NULL;
9717  ast_copy_string(exten2, exten, sizeof(exten2));
9718  /* Parse out extension and callerid */
9719  stringp=exten2 +1;
9720  s1 = strsep(&stringp, "#");
9721  s2 = strsep(&stringp, "#");
9722  if (s2) {
9723  if (!ast_strlen_zero(p->cid_num))
9724  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9725  else
9726  if (*(s1 + 2))
9727  ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
9728  ast_copy_string(exten, s2 + 1, sizeof(exten));
9729  } else
9730  ast_copy_string(exten, s1 + 2, sizeof(exten));
9731  } else
9732  ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
9733  }
9734  if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
9735  if (exten[0] == '*') {
9736  char *stringp=NULL;
9737  ast_copy_string(exten2, exten, sizeof(exten2));
9738  /* Parse out extension and callerid */
9739  stringp=exten2 +1;
9740  s1 = strsep(&stringp, "#");
9741  s2 = strsep(&stringp, "#");
9742  if (s2 && (*(s2 + 1) == '0')) {
9743  if (*(s2 + 2))
9744  ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
9745  }
9746  if (s1) ast_copy_string(exten, s1, sizeof(exten));
9747  else ast_copy_string(exten, "911", sizeof(exten));
9748  } else
9749  ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
9750  }
9751  if (p->sig == SIG_FEATB) {
9752  if (exten[0] == '*') {
9753  char *stringp=NULL;
9754  ast_copy_string(exten2, exten, sizeof(exten2));
9755  /* Parse out extension and callerid */
9756  stringp=exten2 +1;
9757  s1 = strsep(&stringp, "#");
9758  ast_copy_string(exten, exten2 + 1, sizeof(exten));
9759  } else
9760  ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
9761  }
9762  if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
9763  dahdi_wink(p, idx);
9764  /* some switches require a minimum guard time between
9765  the last FGD wink and something that answers
9766  immediately. This ensures it */
9767  if (ast_safe_sleep(chan, 100)) {
9768  ast_hangup(chan);
9769  goto quit;
9770  }
9771  }
9772  dahdi_ec_enable(p);
9773  if (NEED_MFDETECT(p)) {
9774  if (p->dsp) {
9775  if (!p->hardwaredtmf)
9777  else {
9778  ast_dsp_free(p->dsp);
9779  p->dsp = NULL;
9780  }
9781  }
9782  }
9783 
9784  if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
9785  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
9787  if (p->dsp) ast_dsp_digitreset(p->dsp);
9788  res = ast_pbx_run(chan);
9789  if (res) {
9790  ast_log(LOG_WARNING, "PBX exited non-zero\n");
9791  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9792  }
9793  goto quit;
9794  } else {
9795  ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
9796  sleep(2);
9797  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
9798  if (res < 0)
9799  ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
9800  else
9801  sleep(1);
9802  res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
9803  if (res >= 0)
9804  ast_waitstream(chan, "");
9805  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9806  ast_hangup(chan);
9807  goto quit;
9808  }
9809  break;
9810  case SIG_FXOLS:
9811  case SIG_FXOGS:
9812  case SIG_FXOKS:
9813  /* Read the first digit */
9814  timeout = p->firstdigit_timeout;
9815  /* If starting a threeway call, never timeout on the first digit so someone
9816  can use flash-hook as a "hold" feature */
9817  if (p->subs[SUB_THREEWAY].owner)
9818  timeout = INT_MAX;
9819  while (len < AST_MAX_EXTENSION-1) {
9820  int is_exten_parking = 0;
9821 
9822  /* Read digit unless it's supposed to be immediate, in which case the
9823  only answer is 's' */
9824  if (p->immediate)
9825  res = 's';
9826  else
9827  res = ast_waitfordigit(chan, timeout);
9828  timeout = 0;
9829  if (res < 0) {
9830  ast_debug(1, "waitfordigit returned < 0...\n");
9831  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9832  ast_hangup(chan);
9833  goto quit;
9834  } else if (res) {
9835  ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
9836  exten[len++]=res;
9837  exten[len] = '\0';
9838  }
9840  tone_zone_play_tone(p->subs[idx].dfd, -1);
9841  } else {
9842  tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
9843  }
9845  is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
9846  }
9847  if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
9848  if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
9849  if (getforward) {
9850  /* Record this as the forwarding extension */
9852  ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
9853  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9854  if (res)
9855  break;
9856  usleep(500000);
9857  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9858  sleep(1);
9859  memset(exten, 0, sizeof(exten));
9860  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
9861  len = 0;
9862  getforward = 0;
9863  } else {
9864  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9865  ast_channel_lock(chan);
9867  if (!ast_strlen_zero(p->cid_num)) {
9868  if (!p->hidecallerid)
9869  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9870  else
9871  ast_set_callerid(chan, NULL, NULL, p->cid_num);
9872  }
9873  if (!ast_strlen_zero(p->cid_name)) {
9874  if (!p->hidecallerid)
9875  ast_set_callerid(chan, NULL, p->cid_name, NULL);
9876  }
9878  ast_channel_unlock(chan);
9879  dahdi_ec_enable(p);
9880  res = ast_pbx_run(chan);
9881  if (res) {
9882  ast_log(LOG_WARNING, "PBX exited non-zero\n");
9883  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9884  }
9885  goto quit;
9886  }
9887  } else {
9888  /* It's a match, but they just typed a digit, and there is an ambiguous match,
9889  so just set the timeout to matchdigit_timeout and wait some more */
9890  timeout = p->matchdigit_timeout;
9891  }
9892  } else if (res == 0) {
9893  ast_debug(1, "not enough digits (and no ambiguous match)...\n");
9894  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9895  dahdi_wait_event(p->subs[idx].dfd);
9896  ast_hangup(chan);
9897  goto quit;
9898  } else if (p->callwaiting && !strcmp(exten, "*70")) {
9899  ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
9900  /* Disable call waiting if enabled */
9901  p->callwaiting = 0;
9902  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9903  if (res) {
9904  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
9905  ast_channel_name(chan), strerror(errno));
9906  }
9907  len = 0;
9908  ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
9909  memset(exten, 0, sizeof(exten));
9910  timeout = p->firstdigit_timeout;
9911 
9912  } else if (!strcmp(exten, pickupexten)) {
9913  /* Scan all channels and see if there are any
9914  * ringing channels that have call groups
9915  * that equal this channels pickup group
9916  */
9917  if (idx == SUB_REAL) {
9918  /* Switch us from Third call to Call Wait */
9919  if (p->subs[SUB_THREEWAY].owner) {
9920  /* If you make a threeway call and the *8# a call, it should actually
9921  look like a callwait */
9922  alloc_sub(p, SUB_CALLWAIT);
9925  }
9926  dahdi_ec_enable(p);
9927  if (ast_pickup_call(chan)) {
9928  ast_debug(1, "No call pickup possible...\n");
9929  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9930  dahdi_wait_event(p->subs[idx].dfd);
9931  }
9932  ast_hangup(chan);
9933  goto quit;
9934  } else {
9935  ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
9936  ast_hangup(chan);
9937  goto quit;
9938  }
9939 
9940  } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
9941  ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
9942  /* Disable Caller*ID if enabled */
9943  p->hidecallerid = 1;
9948  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9949  if (res) {
9950  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
9951  ast_channel_name(chan), strerror(errno));
9952  }
9953  len = 0;
9954  memset(exten, 0, sizeof(exten));
9955  timeout = p->firstdigit_timeout;
9956  } else if (p->callreturn && !strcmp(exten, "*69")) {
9957  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9958  break;
9959  } else if (!strcmp(exten, "*78")) {
9960  dahdi_dnd(p, 1);
9961  /* Do not disturb */
9962  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9963  getforward = 0;
9964  memset(exten, 0, sizeof(exten));
9965  len = 0;
9966  } else if (!strcmp(exten, "*79")) {
9967  dahdi_dnd(p, 0);
9968  /* Do not disturb */
9969  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9970  getforward = 0;
9971  memset(exten, 0, sizeof(exten));
9972  len = 0;
9973  } else if (p->cancallforward && !strcmp(exten, "*72")) {
9974  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9975  getforward = 1;
9976  memset(exten, 0, sizeof(exten));
9977  len = 0;
9978  } else if (p->cancallforward && !strcmp(exten, "*73")) {
9979  ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
9980  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9981  memset(p->call_forward, 0, sizeof(p->call_forward));
9982  getforward = 0;
9983  memset(exten, 0, sizeof(exten));
9984  len = 0;
9985  } else if ((p->transfer || p->canpark) && is_exten_parking
9986  && p->subs[SUB_THREEWAY].owner) {
9987  struct ast_bridge_channel *bridge_channel;
9988 
9989  /*
9990  * This is a three way call, the main call being a real channel,
9991  * and we're parking the first call.
9992  */
9994  bridge_channel = ast_channel_get_bridge_channel(p->subs[SUB_THREEWAY].owner);
9996  if (bridge_channel) {
9998  /*
9999  * Swap things around between the three-way and real call so we
10000  * can hear where the channel got parked.
10001  */
10002  ast_mutex_lock(&p->lock);
10003  p->owner = p->subs[SUB_THREEWAY].owner;
10005  ast_mutex_unlock(&p->lock);
10006 
10007  ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10008  ast_hangup(chan);
10009  ao2_ref(bridge_channel, -1);
10010  goto quit;
10011  }
10012  ao2_ref(bridge_channel, -1);
10013  }
10014  break;
10015  } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10016  ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10017  /* Enable Caller*ID if enabled */
10018  p->hidecallerid = 0;
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  ast_channel_name(chan), strerror(errno));
10024  }
10025  len = 0;
10026  memset(exten, 0, sizeof(exten));
10027  timeout = p->firstdigit_timeout;
10028  } else if (!strcmp(exten, "*0")) {
10029  struct ast_channel *nbridge =
10030  p->subs[SUB_THREEWAY].owner;
10031  struct dahdi_pvt *pbridge = NULL;
10032  RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10033 
10034  /* set up the private struct of the bridged one, if any */
10035  if (nbridge && bridged) {
10036  pbridge = ast_channel_tech_pvt(bridged);
10037  }
10038  if (nbridge && pbridge &&
10039  (ast_channel_tech(nbridge) == &dahdi_tech) &&
10040  (ast_channel_tech(bridged) == &dahdi_tech) &&
10041  ISTRUNK(pbridge)) {
10042  int func = DAHDI_FLASH;
10043  /* Clear out the dial buffer */
10044  p->dop.dialstr[0] = '\0';
10045  /* flash hookswitch */
10046  if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10047  ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10048  ast_channel_name(nbridge), strerror(errno));
10049  }
10052  p->owner = p->subs[SUB_REAL].owner;
10054  ast_hangup(chan);
10055  goto quit;
10056  } else {
10057  tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10058  dahdi_wait_event(p->subs[idx].dfd);
10059  tone_zone_play_tone(p->subs[idx].dfd, -1);
10062  p->owner = p->subs[SUB_REAL].owner;
10063  ast_hangup(chan);
10064  goto quit;
10065  }
10066  } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10067  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10068  && !canmatch_featurecode(pickupexten, exten)) {
10069  ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10070  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10071  ast_channel_context(chan));
10072  break;
10073  }
10074  if (!timeout)
10075  timeout = p->interdigit_timeout;
10077  tone_zone_play_tone(p->subs[idx].dfd, -1);
10078  }
10079  break;
10080  case SIG_FXSLS:
10081  case SIG_FXSGS:
10082  case SIG_FXSKS:
10083  /* check for SMDI messages */
10084  if (p->use_smdi && p->smdi_iface) {
10086 
10087  if (smdi_msg != NULL) {
10088  ast_channel_exten_set(chan, smdi_msg->fwd_st);
10089 
10090  if (smdi_msg->type == 'B')
10091  pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10092  else if (smdi_msg->type == 'N')
10093  pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10094 
10095  ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10096  } else {
10097  ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10098  }
10099  }
10100 
10101  if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10102  number = smdi_msg->calling_st;
10103 
10104  /* If we want caller id, we're in a prering state due to a polarity reversal
10105  * and we're set to use a polarity reversal to trigger the start of caller id,
10106  * grab the caller id and wait for ringing to start... */
10107  } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10109  /* If set to use DTMF CID signalling, listen for DTMF */
10110  if (p->cid_signalling == CID_SIG_DTMF) {
10111  int k = 0;
10112  int off_ms;
10113  struct timeval start = ast_tvnow();
10114  int ms;
10115  cs = NULL;
10116  ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10117  dahdi_setlinear(p->subs[idx].dfd, 0);
10118  /*
10119  * We are the only party interested in the Rx stream since
10120  * we have not answered yet. We don't need or even want DTMF
10121  * emulation. The DTMF digits can come so fast that emulation
10122  * can drop some of them.
10123  */
10124  ast_channel_lock(chan);
10126  ast_channel_unlock(chan);
10127  off_ms = 4000;/* This is a typical OFF time between rings. */
10128  for (;;) {
10129  struct ast_frame *f;
10130 
10131  ms = ast_remaining_ms(start, off_ms);
10132  res = ast_waitfor(chan, ms);
10133  if (res <= 0) {
10134  /*
10135  * We do not need to restore the dahdi_setlinear()
10136  * or AST_FLAG_END_DTMF_ONLY flag settings since we
10137  * are hanging up the channel.
10138  */
10139  ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10140  "Exiting simple switch\n");
10141  ast_hangup(chan);
10142  goto quit;
10143  }
10144  f = ast_read(chan);
10145  if (!f)
10146  break;
10147  if (f->frametype == AST_FRAME_DTMF) {
10148  if (k < ARRAY_LEN(dtmfbuf) - 1) {
10149  dtmfbuf[k++] = f->subclass.integer;
10150  }
10151  ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10152  start = ast_tvnow();
10153  }
10154  ast_frfree(f);
10155  if (ast_channel_state(chan) == AST_STATE_RING ||
10157  break; /* Got ring */
10158  }
10159  ast_channel_lock(chan);
10161  ast_channel_unlock(chan);
10162  dtmfbuf[k] = '\0';
10163  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10164  /* Got cid and ring. */
10165  ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10166  callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10167  ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10168  /* If first byte is NULL, we have no cid */
10169  if (!ast_strlen_zero(dtmfcid))
10170  number = dtmfcid;
10171  else
10172  number = NULL;
10173  /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10174  } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10175  cs = callerid_new(p->cid_signalling);
10176  if (cs) {
10177  int off_ms;
10178  struct timeval start;
10179  int ms;
10180  samples = 0;
10181 #if 1
10182  bump_gains(p);
10183 #endif
10184  /* Take out of linear mode for Caller*ID processing */
10185  dahdi_setlinear(p->subs[idx].dfd, 0);
10186 
10187  /* First we wait and listen for the Caller*ID */
10188  for (;;) {
10189  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10190  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10191  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10192  callerid_free(cs);
10193  ast_hangup(chan);
10194  goto quit;
10195  }
10196  if (i & DAHDI_IOMUX_SIGEVENT) {
10197  res = dahdi_get_event(p->subs[idx].dfd);
10198  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10199  if (res == DAHDI_EVENT_NOALARM) {
10200  p->inalarm = 0;
10201  }
10202 
10203  if (p->cid_signalling == CID_SIG_V23_JP) {
10204  if (res == DAHDI_EVENT_RINGBEGIN) {
10205  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10206  usleep(1);
10207  }
10208  } else {
10209  res = 0;
10210  break;
10211  }
10212  } else if (i & DAHDI_IOMUX_READ) {
10213  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10214  if (res < 0) {
10215  if (errno != ELAST) {
10216  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10217  callerid_free(cs);
10218  ast_hangup(chan);
10219  goto quit;
10220  }
10221  break;
10222  }
10223  samples += res;
10224 
10225  if (p->cid_signalling == CID_SIG_V23_JP) {
10226  res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10227  } else {
10228  res = callerid_feed(cs, buf, res, AST_LAW(p));
10229  }
10230  if (res < 0) {
10231  /*
10232  * The previous diagnostic message output likely
10233  * explains why it failed.
10234  */
10236  "Failed to decode CallerID on channel '%s'\n",
10237  ast_channel_name(chan));
10238  break;
10239  } else if (res)
10240  break;
10241  else if (samples > (8000 * 10))
10242  break;
10243  }
10244  }
10245  if (res == 1) {
10246  callerid_get(cs, &name, &number, &flags);
10247  ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10248  }
10249 
10250  if (p->cid_signalling == CID_SIG_V23_JP) {
10251  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10252  usleep(1);
10253  }
10254 
10255  /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10256  start = ast_tvnow();
10257  off_ms = 4000;/* This is a typical OFF time between rings. */
10258  for (;;) {
10259  struct ast_frame *f;
10260 
10261  ms = ast_remaining_ms(start, off_ms);
10262  res = ast_waitfor(chan, ms);
10263  if (res <= 0) {
10264  ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10265  "Exiting simple switch\n");
10266  ast_hangup(chan);
10267  goto quit;
10268  }
10269  if (!(f = ast_read(chan))) {
10270  ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10271  ast_hangup(chan);
10272  goto quit;
10273  }
10274  ast_frfree(f);
10275  if (ast_channel_state(chan) == AST_STATE_RING ||
10277  break; /* Got ring */
10278  }
10279 
10280  /* We must have a ring by now, so, if configured, lets try to listen for
10281  * distinctive ringing */
10282  if (p->usedistinctiveringdetection) {
10283  len = 0;
10284  distMatches = 0;
10285  /* Clear the current ring data array so we don't have old data in it. */
10286  for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10287  curRingData[receivedRingT] = 0;
10288  receivedRingT = 0;
10289  counter = 0;
10290  counter1 = 0;
10291  /* Check to see if context is what it should be, if not set to be. */
10292  if (strcmp(p->context,p->defcontext) != 0) {
10293  ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10295  }
10296 
10297  for (;;) {
10298  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10299  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10300  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10301  callerid_free(cs);
10302  ast_hangup(chan);
10303  goto quit;
10304  }
10305  if (i & DAHDI_IOMUX_SIGEVENT) {
10306  res = dahdi_get_event(p->subs[idx].dfd);
10307  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10308  if (res == DAHDI_EVENT_NOALARM) {
10309  p->inalarm = 0;
10310  }
10311  res = 0;
10312  /* Let us detect distinctive ring */
10313 
10314  curRingData[receivedRingT] = p->ringt;
10315 
10316  if (p->ringt < p->ringt_base/2)
10317  break;
10318  /* Increment the ringT counter so we can match it against
10319  values in chan_dahdi.conf for distinctive ring */
10320  if (++receivedRingT == ARRAY_LEN(curRingData))
10321  break;
10322  } else if (i & DAHDI_IOMUX_READ) {
10323  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10324  if (res < 0) {
10325  if (errno != ELAST) {
10326  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10327  callerid_free(cs);
10328  ast_hangup(chan);
10329  goto quit;
10330  }
10331  break;
10332  }
10333  if (p->ringt > 0) {
10334  if (!(--p->ringt)) {
10335  res = -1;
10336  break;
10337  }
10338  }
10339  }
10340  }
10341  /* this only shows up if you have n of the dring patterns filled in */
10342  ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10343  for (counter = 0; counter < 3; counter++) {
10344  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10345  channel */
10346  distMatches = 0;
10347  for (counter1 = 0; counter1 < 3; counter1++) {
10348  ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10349  if (p->drings.ringnum[counter].ring[counter1] == -1) {
10350  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10351  curRingData[counter1]);
10352  distMatches++;
10353  } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10354  curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10355  ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10356  (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10357  (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10358  distMatches++;
10359  }
10360  }
10361 
10362  if (distMatches == 3) {
10363  /* The ring matches, set the context to whatever is for distinctive ring.. */
10364  ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10366  ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10367  break;
10368  }
10369  }
10370  }
10371  /* Restore linear mode (if appropriate) for Caller*ID processing */
10372  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10373 #if 1
10374  restore_gains(p);
10375 #endif
10376  } else
10377  ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10378  } else {
10379  ast_log(LOG_WARNING, "Channel %s in prering "
10380  "state, but I have nothing to do. "
10381  "Terminating simple switch, should be "
10382  "restarted by the actual ring.\n",
10383  ast_channel_name(chan));
10384  ast_hangup(chan);
10385  goto quit;
10386  }
10387  } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10388  if (p->cid_signalling == CID_SIG_DTMF) {
10389  int k = 0;
10390  int off_ms;
10391  struct timeval start;
10392  int ms;
10393  cs = NULL;
10394  dahdi_setlinear(p->subs[idx].dfd, 0);
10395  off_ms = 2000;
10396  start = ast_tvnow();
10397  for (;;) {
10398  struct ast_frame *f;
10399 
10400  ms = ast_remaining_ms(start, off_ms);
10401  res = ast_waitfor(chan, ms);
10402  if (res <= 0) {
10403  ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10404  "Exiting simple switch\n");
10405  ast_hangup(chan);
10406  goto quit;
10407  }
10408  f = ast_read(chan);
10409  if (!f) {
10410  /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10411  ast_hangup(chan);
10412  goto quit;
10413  }
10414  if (f->frametype == AST_FRAME_DTMF) {
10415  dtmfbuf[k++] = f->subclass.integer;
10416  ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10417  start = ast_tvnow();
10418  }
10419  ast_frfree(f);
10420 
10421  if (p->ringt_base == p->ringt)
10422  break;
10423  }
10424  dtmfbuf[k] = '\0';
10425  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10426  /* Got cid and ring. */
10427  callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10428  ast_debug(1, "CID is '%s', flags %d\n",
10429  dtmfcid, flags);
10430  /* If first byte is NULL, we have no cid */
10431  if (!ast_strlen_zero(dtmfcid))
10432  number = dtmfcid;
10433  else
10434  number = NULL;
10435  /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10436  } else {
10437  /* FSK Bell202 callerID */
10438  cs = callerid_new(p->cid_signalling);
10439  if (cs) {
10440 #if 1
10441  bump_gains(p);
10442 #endif
10443  samples = 0;
10444  len = 0;
10445  distMatches = 0;
10446  /* Clear the current ring data array so we don't have old data in it. */
10447  for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10448  curRingData[receivedRingT] = 0;
10449  receivedRingT = 0;
10450  counter = 0;
10451  counter1 = 0;
10452  /* Check to see if context is what it should be, if not set to be. */
10453  if (strcmp(p->context,p->defcontext) != 0) {
10454  ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10456  }
10457 
10458  /* Take out of linear mode for Caller*ID processing */
10459  dahdi_setlinear(p->subs[idx].dfd, 0);
10460  for (;;) {
10461  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10462  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10463  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10464  callerid_free(cs);
10465  ast_hangup(chan);
10466  goto quit;
10467  }
10468  if (i & DAHDI_IOMUX_SIGEVENT) {
10469  res = dahdi_get_event(p->subs[idx].dfd);
10470  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10471  if (res == DAHDI_EVENT_NOALARM) {
10472  p->inalarm = 0;
10473  }
10474  /* If we get a PR event, they hung up while processing calerid */
10475  if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10476  ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10477  p->polarity = POLARITY_IDLE;
10478  callerid_free(cs);
10479  ast_hangup(chan);
10480  goto quit;
10481  }
10482  res = 0;
10483  /* Let us detect callerid when the telco uses distinctive ring */
10484 
10485  curRingData[receivedRingT] = p->ringt;
10486 
10487  if (p->ringt < p->ringt_base/2)
10488  break;
10489  /* Increment the ringT counter so we can match it against
10490  values in chan_dahdi.conf for distinctive ring */
10491  if (++receivedRingT == ARRAY_LEN(curRingData))
10492  break;
10493  } else if (i & DAHDI_IOMUX_READ) {
10494  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10495  if (res < 0) {
10496  if (errno != ELAST) {
10497  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10498  callerid_free(cs);
10499  ast_hangup(chan);
10500  goto quit;
10501  }
10502  break;
10503  }
10504  if (p->ringt > 0) {
10505  if (!(--p->ringt)) {
10506  res = -1;
10507  break;
10508  }
10509  }
10510  samples += res;
10511  res = callerid_feed(cs, buf, res, AST_LAW(p));
10512  if (res < 0) {
10513  /*
10514  * The previous diagnostic message output likely
10515  * explains why it failed.
10516  */
10518  "Failed to decode CallerID on channel '%s'\n",
10519  ast_channel_name(chan));
10520  break;
10521  } else if (res)
10522  break;
10523  else if (samples > (8000 * 10))
10524  break;
10525  }
10526  }
10527  if (res == 1) {
10528  callerid_get(cs, &name, &number, &flags);
10529  ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10530  }
10531  if (distinctiveringaftercid == 1) {
10532  /* Clear the current ring data array so we don't have old data in it. */
10533  for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10534  curRingData[receivedRingT] = 0;
10535  }
10536  receivedRingT = 0;
10537  ast_verb(3, "Detecting post-CID distinctive ring\n");
10538  for (;;) {
10539  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10540  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10541  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10542  callerid_free(cs);
10543  ast_hangup(chan);
10544  goto quit;
10545  }
10546  if (i & DAHDI_IOMUX_SIGEVENT) {
10547  res = dahdi_get_event(p->subs[idx].dfd);
10548  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10549  if (res == DAHDI_EVENT_NOALARM) {
10550  p->inalarm = 0;
10551  }
10552  res = 0;
10553  /* Let us detect callerid when the telco uses distinctive ring */
10554 
10555  curRingData[receivedRingT] = p->ringt;
10556 
10557  if (p->ringt < p->ringt_base/2)
10558  break;
10559  /* Increment the ringT counter so we can match it against
10560  values in chan_dahdi.conf for distinctive ring */
10561  if (++receivedRingT == ARRAY_LEN(curRingData))
10562  break;
10563  } else if (i & DAHDI_IOMUX_READ) {
10564  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10565  if (res < 0) {
10566  if (errno != ELAST) {
10567  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10568  callerid_free(cs);
10569  ast_hangup(chan);
10570  goto quit;
10571  }
10572  break;
10573  }
10574  if (p->ringt > 0) {
10575  if (!(--p->ringt)) {
10576  res = -1;
10577  break;
10578  }
10579  }
10580  }
10581  }
10582  }
10583  if (p->usedistinctiveringdetection) {
10584  /* this only shows up if you have n of the dring patterns filled in */
10585  ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10586 
10587  for (counter = 0; counter < 3; counter++) {
10588  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10589  channel */
10590  /* this only shows up if you have n of the dring patterns filled in */
10591  ast_verb(3, "Checking %d,%d,%d\n",
10592  p->drings.ringnum[counter].ring[0],
10593  p->drings.ringnum[counter].ring[1],
10594  p->drings.ringnum[counter].ring[2]);
10595  distMatches = 0;
10596  for (counter1 = 0; counter1 < 3; counter1++) {
10597  ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10598  if (p->drings.ringnum[counter].ring[counter1] == -1) {
10599  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10600  curRingData[counter1]);
10601  distMatches++;
10602  }
10603  else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10604  curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10605  ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10606  (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10607  (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10608  distMatches++;
10609  }
10610  }
10611  if (distMatches == 3) {
10612  /* The ring matches, set the context to whatever is for distinctive ring.. */
10613  ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10615  ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10616  break;
10617  }
10618  }
10619  }
10620  /* Restore linear mode (if appropriate) for Caller*ID processing */
10621  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10622 #if 1
10623  restore_gains(p);
10624 #endif
10625  if (res < 0) {
10626  ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
10627  }
10628  } else
10629  ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10630  }
10631  } else
10632  cs = NULL;
10633 
10634  if (number)
10637 
10638  ao2_cleanup(smdi_msg);
10639 
10640  if (cs)
10641  callerid_free(cs);
10642 
10643  my_handle_notify_message(chan, p, flags, -1);
10644 
10645  ast_channel_lock(chan);
10647  ast_channel_rings_set(chan, 1);
10648  ast_channel_unlock(chan);
10649  p->ringt = p->ringt_base;
10650  res = ast_pbx_run(chan);
10651  if (res) {
10652  ast_hangup(chan);
10653  ast_log(LOG_WARNING, "PBX exited non-zero\n");
10654  }
10655  goto quit;
10656  default:
10657  ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10658  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10659  if (res < 0)
10660  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10661  }
10662  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10663  if (res < 0)
10664  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10665  ast_hangup(chan);
10666 quit:
10668  ss_thread_count--;
10671  return NULL;
10672 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define CID_SIG_V23_JP
Definition: callerid.h:62
#define CID_SIG_SMDI
Definition: callerid.h:63
int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:306
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
Definition: callerid.c:734
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:947
#define CID_SIG_DTMF
Definition: callerid.h:61
#define CID_SIG_V23
Definition: callerid.h:60
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:545
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
Definition: callerid.c:201
#define CID_START_RING
Definition: callerid.h:65
#define CID_START_POLARITY
Definition: callerid.h:66
void callerid_get(struct callerid_state *cid, char **number, char **name, int *flags)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:188
#define CID_START_POLARITY_IN
Definition: callerid.h:67
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
Definition: callerid.c:129
#define CID_START_DTMF_NOALERT
Definition: callerid.h:68
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:122
static ast_mutex_t ss_thread_lock
Definition: chan_dahdi.c:642
static int restore_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4891
static int unalloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4186
static int dahdi_wink(struct dahdi_pvt *p, int index)
Definition: chan_dahdi.c:9387
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition: chan_dahdi.c:661
static int canmatch_featurecode(const char *pickupexten, const char *exten)
Definition: chan_dahdi.c:9453
static int distinctiveringaftercid
Definition: chan_dahdi.c:608
static int bump_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4877
#define AST_LAW(p)
Definition: chan_dahdi.c:521
static int dahdi_setlinear(int dfd, int linear)
Definition: chan_dahdi.c:4143
static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
Definition: chan_dahdi.c:3291
static int alloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4149
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
Definition: chan_dahdi.c:525
static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
Definition: chan_dahdi.c:9368
#define SMDI_MD_WAIT_TIMEOUT
Definition: chan_dahdi.c:482
static void swap_subs(struct dahdi_pvt *p, int a, int b)
Definition: chan_dahdi.c:4040
#define ISTRUNK(p)
Definition: chan_dahdi.c:590
#define POLARITY_IDLE
Definition: chan_dahdi.c:792
#define POLARITY_REV
Definition: chan_dahdi.c:793
static int ss_thread_count
Definition: chan_dahdi.c:644
#define SIG_FEATB
Definition: chan_dahdi.h:742
#define SIG_FGC_CAMA
Definition: chan_dahdi.h:745
#define SIG_SFWINK
Definition: chan_dahdi.h:754
#define SIG_EMWINK
Definition: chan_dahdi.h:739
#define SIG_SF_FEATB
Definition: chan_dahdi.h:757
#define SIG_FXOGS
Definition: chan_dahdi.h:751
#define SIG_SF_FEATDMF
Definition: chan_dahdi.h:756
#define SIG_FXOKS
Definition: chan_dahdi.h:752
#define SIG_FGC_CAMAMF
Definition: chan_dahdi.h:746
#define SIG_FEATDMF
Definition: chan_dahdi.h:741
#define SIG_EM_E1
Definition: chan_dahdi.h:758
#define SIG_SF_FEATD
Definition: chan_dahdi.h:755
#define SIG_FEATD
Definition: chan_dahdi.h:740
#define SIG_FEATDMF_TA
Definition: chan_dahdi.h:744
#define SIG_FXOLS
Definition: chan_dahdi.h:750
#define SIG_E911
Definition: chan_dahdi.h:743
#define SIG_EM
Definition: chan_dahdi.h:738
#define SIG_SF
Definition: chan_dahdi.h:753
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3176
void ast_channel_rings_set(struct ast_channel *chan, int value)
void ast_party_name_init(struct ast_party_name *init)
Initialize the given name structure.
Definition: channel.c:1585
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1638
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2542
const char * ast_channel_context(const struct ast_channel *chan)
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3163
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4292
void ast_party_name_free(struct ast_party_name *doomed)
Destroy the party name contents.
Definition: channel.c:1632
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7417
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
const char * ast_channel_language(const struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10768
@ AST_FLAG_END_DTMF_ONLY
Definition: channel.h:1007
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
Definition: channel.c:1685
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1568
#define AST_MAX_EXTENSION
Definition: channel.h:134
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10750
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_PRERING
Definition: channelstate.h:45
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1773
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1800
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1847
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1265
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1791
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
#define ast_frfree(fr)
#define ast_cond_signal(cond)
Definition: lock.h:201
#define LOG_ERROR
Definition: logger.h:286
#define LOG_NOTICE
Definition: logger.h:264
int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
Perform a blind transfer to a parking extension.
Definition: parking.c:143
int ast_parking_is_exten_park(const char *context, const char *exten)
Determine if the context/exten is a "parking" extension.
Definition: parking.c:179
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4753
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4173
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4188
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch)
Definition: pbx.c:4193
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:199
struct ast_smdi_md_message * ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout)
Get the next SMDI message from the queue.
Definition: res_smdi.c:539
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:404
Structure that contains information regarding a channel in a bridge.
struct ast_channel * chan
Main Channel structure associated with a channel.
const char * data
Configuration relating to call pickup.
unsigned int flags
An SMDI message desk message.
Definition: smdi.h:65
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:70
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:69
struct ringContextData ringContext[3]
Definition: chan_dahdi.h:71
struct distRingData ringnum[3]
Definition: chan_dahdi.h:70
unsigned int immediate
TRUE if the channel should be answered immediately without attempting to gather any digits.
Definition: chan_dahdi.h:300
struct dahdi_distRings drings
Distinctive Ring data.
Definition: chan_dahdi.h:454
unsigned int canpark
TRUE if support for call parking is enabled.
Definition: chan_dahdi.h:235
struct dahdi_dialoperation dop
DAHDI dial operation command struct for ioctl() call.
Definition: chan_dahdi.h:657
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
Definition: chan_dahdi.h:495
int ringt
Ring timeout timer??
Definition: chan_dahdi.h:572
int interdigit_timeout
Time (ms) to detect following digits (in an analog phone)
Definition: chan_dahdi.h:646
unsigned int usedistinctiveringdetection
TRUE if distinctive rings are to be detected.
Definition: chan_dahdi.h:376
int dtmfrelax
Definition: chan_dahdi.h:681
unsigned int callwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
Definition: chan_dahdi.h:218
unsigned int hanguponpolarityswitch
TRUE if the call will be considered "hung up" on a polarity reversal.
Definition: chan_dahdi.h:277
char call_forward[AST_MAX_EXTENSION]
Accumulated call forwarding number.
Definition: chan_dahdi.h:665
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: chan_dahdi.h:286
unsigned int callreturn
TRUE if call return is enabled. (*69, if your dialplan doesn't catch this first)
Definition: chan_dahdi.h:211
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: chan_dahdi.h:448
int ringt_base
Ring timeout base.
Definition: chan_dahdi.h:577
int cid_start
Definition: chan_dahdi.h:558
char defcontext[AST_MAX_CONTEXT]
Default distinctive ring context.
Definition: chan_dahdi.h:469
struct ast_dsp * dsp
Opaque DSP configuration structure.
Definition: chan_dahdi.h:655
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:460
unsigned int cancallforward
TRUE if support for call forwarding enabled. Dial *72 to enable call forwarding. Dial *73 to disable ...
Definition: chan_dahdi.h:230
unsigned int hardwaredtmf
TRUE if DTMF detection needs to be done by hardware.
Definition: chan_dahdi.h:279
int firstdigit_timeout
Time (ms) to detect first digit (in an analog phone)
Definition: chan_dahdi.h:641
int cid_signalling
Definition: chan_dahdi.h:557
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:355
unsigned int inalarm
TRUE if in an alarm condition.
Definition: chan_dahdi.h:302
char cid_name[AST_MAX_EXTENSION]
Caller ID name from an incoming call.
Definition: chan_dahdi.h:504
int matchdigit_timeout
Time (ms) to wait, in case of ambiguous match (in an analog phone)
Definition: chan_dahdi.h:651
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: chan_dahdi.h:363
int polarity
Current line interface polarity. POLARITY_IDLE, POLARITY_REV.
Definition: chan_dahdi.h:697
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: chan_dahdi.h:451
unsigned int linear
Definition: chan_dahdi.h:90
int ring[3]
Definition: chan_dahdi.h:63
char contextData[AST_MAX_CONTEXT]
Definition: chan_dahdi.h:67
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2179
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:936
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

References alloc_sub(), ao2_cleanup, ao2_ref, ARRAY_LEN, ast_canmatch_extension(), ast_channel_bridge_peer(), ast_channel_caller(), ast_channel_cleanup, ast_channel_context(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_get_bridge_channel(), ast_channel_language(), ast_channel_lock, ast_channel_name(), ast_channel_rings_set(), ast_channel_tech(), ast_channel_tech_pvt(), ast_channel_unlock, ast_clear_flag, ast_cond_signal, 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_get_chan_features_pickup_config(), ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parking_blind_transfer_park(), ast_parking_is_exten_park(), ast_parking_provider_registered(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_pickup_call(), ast_queue_unhold(), ast_read(), ast_remaining_ms(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), buf, bump_gains(), dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, canmatch_featurecode(), dahdi_pvt::canpark, ast_bridge_channel::chan, 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, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, dahdi_dnd(), dahdi_ec_enable(), dahdi_get_event(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, dahdi_wait_event(), dahdi_wink(), ast_channel::data, dahdi_pvt::defcontext, dahdi_subchannel::dfd, distinctiveringaftercid, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), exten, dahdi_pvt::firstdigit_timeout, ast_frame::flags, ast_frame::frametype, ast_smdi_md_message::fwd_st, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_pvt::interdigit_timeout, ISTRUNK, len(), dahdi_subchannel::linear, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::matchdigit_timeout, my_getsigstr(), my_handle_notify_message(), name, NEED_MFDETECT, NULL, dahdi_subchannel::owner, dahdi_pvt::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, RAII_VAR, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, ast_frame::samples, 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_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_complete, ss_thread_count, ss_thread_lock, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.

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

◆ analog_tone_to_dahditone()

static int analog_tone_to_dahditone ( enum analog_tone  tone)
static

Definition at line 1110 of file chan_dahdi.c.

1111 {
1112  switch (tone) {
1113  case ANALOG_TONE_RINGTONE:
1114  return DAHDI_TONE_RINGTONE;
1115  case ANALOG_TONE_STUTTER:
1116  return DAHDI_TONE_STUTTER;
1118  return DAHDI_TONE_CONGESTION;
1119  case ANALOG_TONE_DIALTONE:
1120  return DAHDI_TONE_DIALTONE;
1122  return DAHDI_TONE_DIALRECALL;
1123  case ANALOG_TONE_INFO:
1124  return DAHDI_TONE_INFO;
1125  default:
1126  return -1;
1127  }
1128 }
@ ANALOG_TONE_CONGESTION
Definition: sig_analog.h:73
@ ANALOG_TONE_INFO
Definition: sig_analog.h:76
@ ANALOG_TONE_DIALTONE
Definition: sig_analog.h:74
@ ANALOG_TONE_DIALRECALL
Definition: sig_analog.h:75
@ ANALOG_TONE_STUTTER
Definition: sig_analog.h:72
@ ANALOG_TONE_RINGTONE
Definition: sig_analog.h:71

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

Referenced by dahdievent_to_analogevent().

◆ analogsub_to_dahdisub()

static int analogsub_to_dahdisub ( enum analog_sub  analogsub)
static

Definition at line 1130 of file chan_dahdi.c.

1131 {
1132  int index;
1133 
1134  switch (analogsub) {
1135  case ANALOG_SUB_REAL:
1136  index = SUB_REAL;
1137  break;
1138  case ANALOG_SUB_CALLWAIT:
1139  index = SUB_CALLWAIT;
1140  break;
1141  case ANALOG_SUB_THREEWAY:
1142  index = SUB_THREEWAY;
1143  break;
1144  default:
1145  ast_log(LOG_ERROR, "Unidentified sub!\n");
1146  index = SUB_REAL;
1147  }
1148 
1149  return index;
1150 }
@ ANALOG_SUB_THREEWAY
Definition: sig_analog.h:111
@ ANALOG_SUB_REAL
Definition: sig_analog.h:109
@ ANALOG_SUB_CALLWAIT
Definition: sig_analog.h:110

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

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

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 19896 of file chan_dahdi.c.

◆ attempt_transfer()

static int attempt_transfer ( struct dahdi_pvt p)
static

Definition at line 7113 of file chan_dahdi.c.

7114 {
7115  struct ast_channel *owner_real;
7116  struct ast_channel *owner_3way;
7117  enum ast_transfer_result xfer_res;
7118  int res = 0;
7119 
7120  owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7121  owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7122 
7123  ast_verb(3, "TRANSFERRING %s to %s\n",
7124  ast_channel_name(owner_3way), ast_channel_name(owner_real));
7125 
7126  ast_channel_unlock(owner_real);
7127  ast_channel_unlock(owner_3way);
7128  ast_mutex_unlock(&p->lock);
7129 
7130  xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7131  if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7132  ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
7133  res = -1;
7134  }
7135 
7136  /* Must leave with these locked. */
7137  ast_channel_lock(owner_real);
7138  ast_mutex_lock(&p->lock);
7139 
7140  ast_channel_unref(owner_real);
7141  ast_channel_unref(owner_3way);
7142 
7143  return res;
7144 }
ast_transfer_result
Definition: bridge.h:1098
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1100
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4662
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958

References ast_bridge_transfer_attended(), AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_lock, ast_channel_name(), ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), AST_SOFTHANGUP_DEV, ast_verb, dahdi_pvt::lock, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

Referenced by dahdi_handle_event().

◆ available()

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

Definition at line 13032 of file chan_dahdi.c.

13033 {
13034  struct dahdi_pvt *p = *pvt;
13035 
13036  if (p->inalarm)
13037  return 0;
13038 
13039  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13040  return analog_available(p->sig_pvt);
13041 
13042  switch (p->sig) {
13043 #if defined(HAVE_PRI)
13045  {
13046  struct sig_pri_chan *pvt_chan;
13047  int res;
13048 
13049  pvt_chan = p->sig_pvt;
13050  res = sig_pri_available(&pvt_chan, is_specific_channel);
13051  *pvt = pvt_chan->chan_pvt;
13052  return res;
13053  }
13054 #endif /* defined(HAVE_PRI) */
13055 #if defined(HAVE_SS7)
13056  case SIG_SS7:
13057  return sig_ss7_available(p->sig_pvt);
13058 #endif /* defined(HAVE_SS7) */
13059  default:
13060  break;
13061  }
13062 
13063  if (p->locallyblocked || p->remotelyblocked) {
13064  return 0;
13065  }
13066 
13067  /* If no owner definitely available */
13068  if (!p->owner) {
13069 #ifdef HAVE_OPENR2
13070  /* Trust MFC/R2 */
13071  if (p->mfcr2) {
13072  if (p->mfcr2call) {
13073  return 0;
13074  } else {
13075  return 1;
13076  }
13077  }
13078 #endif
13079  return 1;
13080  }
13081 
13082  return 0;
13083 }
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:772
#define SIG_SS7
Definition: chan_dahdi.h:766
int analog_available(struct analog_pvt *p)
Definition: sig_analog.c:793
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
int sig_ss7_available(struct sig_ss7_chan *p)
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: chan_dahdi.h:420
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:429
void * sig_pvt
Definition: chan_dahdi.h:725
void * chan_pvt
Definition: sig_pri.h:374

References analog_available(), sig_pri_chan::chan_pvt, dahdi_analog_lib_handles(), dahdi_pvt::inalarm, dahdi_pvt::locallyblocked, 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(), dahdi_request(), is_member_available(), logger_register_level(), sip_options_contact_status_available_count(), and sip_options_update_aor_task().

◆ build_channels()

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

Definition at line 17637 of file chan_dahdi.c.

17638 {
17639  char *c, *chan;
17640  int x, start, finish;
17641  struct dahdi_pvt *tmp;
17642 
17643  if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17644  ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17645  return -1;
17646  }
17647 
17648  c = ast_strdupa(value);
17649 
17650  while ((chan = strsep(&c, ","))) {
17651  if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17652  /* Range */
17653  } else if (sscanf(chan, "%30d", &start)) {
17654  /* Just one */
17655  finish = start;
17656  } else if (!strcasecmp(chan, "pseudo")) {
17657  finish = start = CHAN_PSEUDO;
17658  } else {
17659  ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17660  return -1;
17661  }
17662  if (finish < start) {
17663  ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
17664  x = finish;
17665  finish = start;
17666  start = x;
17667  }
17668 
17669  for (x = start; x <= finish; x++) {
17670  if (conf->wanted_channels_start &&
17671  (x < conf->wanted_channels_start ||
17672  x > conf->wanted_channels_end)
17673  ) {
17674  continue;
17675  }
17676  tmp = mkintf(x, conf, reload);
17677 
17678  if (tmp) {
17679  ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
17680  } else {
17681  ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17682  (reload == 1) ? "reconfigure" : "register", value);
17683  return -1;
17684  }
17685  if (x == CHAN_PSEUDO) {
17686  has_pseudo = 1;
17687  }
17688  }
17689  }
17690 
17691  return 0;
17692 }
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12063
static int has_pseudo
Definition: chan_dahdi.c:567
static int reload(void)
Definition: chan_dahdi.c:19872
#define CHAN_PSEUDO
Definition: chan_dahdi.c:556
All configuration options for statsd client.
Definition: res_statsd.c:101
int value
Definition: syslog.c:37
static struct test_val c

References ast_log, ast_strdupa, ast_verb, c, CHAN_PSEUDO, has_pseudo, LOG_ERROR, LOG_WARNING, mkintf(), reload(), sig2str, strsep(), tmp(), and value.

Referenced by process_dahdi().

◆ bump_gains()

static int bump_gains ( struct dahdi_pvt p)
static

Definition at line 4877 of file chan_dahdi.c.

4878 {
4879  int res;
4880 
4881  /* Bump receive gain by value stored in cid_rxgain */
4882  res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
4883  if (res) {
4884  ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
4885  return -1;
4886  }
4887 
4888  return 0;
4889 }
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:4872
float cid_rxgain
Amount of gain to increase during caller id.
Definition: chan_dahdi.h:157
float txdrc
Definition: chan_dahdi.h:163
int law
Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:525
float rxdrc
Definition: chan_dahdi.h:164
float txgain
Software Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:161
float rxgain
Software Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:159

References ast_log, dahdi_pvt::cid_rxgain, dahdi_subchannel::dfd, 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().

◆ calc_energy()

static int calc_energy ( const unsigned char *  buf,
int  len,
struct ast_format law 
)
static

Definition at line 10680 of file chan_dahdi.c.

10681 {
10682  int x;
10683  int sum = 0;
10684 
10685  if (!len)
10686  return 0;
10687 
10688  for (x = 0; x < len; x++)
10689  sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10690 
10691  return sum / len;
10692 }
#define AST_ALAW(a)
Definition: alaw.h:84
#define abs(x)
Definition: f2c.h:195
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define AST_MULAW(a)
Definition: ulaw.h:85

References abs, AST_ALAW, ast_format_ulaw, AST_MULAW, buf, dahdi_pvt::law, and len().

Referenced by do_monitor(), and mwi_thread().

◆ canmatch_featurecode()

static int canmatch_featurecode ( const char *  pickupexten,
const char *  exten 
)
static

Definition at line 9453 of file chan_dahdi.c.

9454 {
9455  int extlen = strlen(exten);
9456 
9457  if (!extlen) {
9458  return 1;
9459  }
9460 
9461  if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9462  return 1;
9463  }
9464  /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9465  if (exten[0] == '*' && extlen < 3) {
9466  if (extlen == 1) {
9467  return 1;
9468  }
9469  /* "*0" should be processed before it gets here */
9470  switch (exten[1]) {
9471  case '6':
9472  case '7':
9473  case '8':
9474  return 1;
9475  }
9476  }
9477  return 0;
9478 }

References exten.

Referenced by analog_ss_thread().

◆ check_for_conference()

static int check_for_conference ( struct dahdi_pvt p)
static

Definition at line 7146 of file chan_dahdi.c.

7147 {
7148  struct dahdi_confinfo ci;
7149  /* Fine if we already have a master, etc */
7150  if (p->master || (p->confno > -1))
7151  return 0;
7152  memset(&ci, 0, sizeof(ci));
7153  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7154  ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7155  return 0;
7156  }
7157  /* If we have no master and don't have a confno, then
7158  if we're in a conference, it's probably a MeetMe room or
7159  some such, so don't let us 3-way out! */
7160  if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7161  ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7162  return 1;
7163  }
7164  return 0;
7165 }
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
int confno
Definition: chan_dahdi.h:526
struct dahdi_confinfo curconf
Definition: chan_dahdi.h:92

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

Referenced by dahdi_handle_event(), and my_check_for_conference().

◆ conf_add()

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

Definition at line 4439 of file chan_dahdi.c.

4440 {
4441  /* If the conference already exists, and we're already in it
4442  don't bother doing anything */
4443  struct dahdi_confinfo zi;
4444 
4445  memset(&zi, 0, sizeof(zi));
4446  zi.chan = 0;
4447 
4448  if (slavechannel > 0) {
4449  /* If we have only one slave, do a digital mon */
4450  zi.confmode = DAHDI_CONF_DIGITALMON;
4451  zi.confno = slavechannel;
4452  } else {
4453  if (!idx) {
4454  /* Real-side and pseudo-side both participate in conference */
4455  zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4456  DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4457  } else
4458  zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4459  zi.confno = p->confno;
4460  }
4461  if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4462  return 0;
4463  if (c->dfd < 0)
4464  return 0;
4465  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4466  ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4467  return -1;
4468  }
4469  if (slavechannel < 1) {
4470  p->confno = zi.confno;
4471  }
4472  c->curconf = zi;
4473  ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4474  return 0;
4475 }

References ast_debug, ast_log, c, dahdi_pvt::confno, errno, and LOG_WARNING.

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

◆ conf_del()

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

Definition at line 4488 of file chan_dahdi.c.

4489 {
4490  struct dahdi_confinfo zi;
4491  if (/* Can't delete if there's no dfd */
4492  (c->dfd < 0) ||
4493  /* Don't delete from the conference if it's not our conference */
4494  !isourconf(p, c)
4495  /* Don't delete if we don't think it's conferenced at all (implied) */
4496  ) return 0;
4497  memset(&zi, 0, sizeof(zi));
4498  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4499  ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4500  return -1;
4501  }
4502  ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4503  memcpy(&c->curconf, &zi, sizeof(c->curconf));
4504  return 0;
4505 }
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4477

References ast_debug, ast_log, c, errno, isourconf(), and LOG_WARNING.

Referenced by dahdi_conf_update(), dahdi_master_slave_unlink(), and my_conf_del().

◆ create_channel_name()

static struct ast_str* create_channel_name ( struct dahdi_pvt i)
static

Definition at line 9067 of file chan_dahdi.c.

9069 {
9070  struct ast_str *chan_name;
9071  int x, y;
9072 
9073  /* Create the new channel name tail. */
9074  if (!(chan_name = ast_str_create(32))) {
9075  return NULL;
9076  }
9077  if (i->channel == CHAN_PSEUDO) {
9078  ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9079 #if defined(HAVE_PRI)
9080  } else if (i->pri) {
9081  ast_mutex_lock(&i->pri->lock);
9082  y = ++i->pri->new_chan_seq;
9083  if (is_outgoing) {
9084  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9085  address[0] = '\0';
9086  } else if (ast_strlen_zero(i->cid_subaddr)) {
9087  /* Put in caller-id number only since there is no subaddress. */
9088  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9089  } else {
9090  /* Put in caller-id number and subaddress. */
9091  ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9092  i->cid_subaddr, (unsigned)y);
9093  }
9094  ast_mutex_unlock(&i->pri->lock);
9095 #endif /* defined(HAVE_PRI) */
9096  } else {
9097  y = 1;
9098  do {
9099  ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9100  for (x = 0; x < 3; ++x) {
9101  if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9102  ast_channel_name(i->subs[x].owner) + 6)) {
9103  break;
9104  }
9105  }
9106  ++y;
9107  } while (x < 3);
9108  }
9109  return chan_name;
9110 }
char * address
Definition: f2c.h:59
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:737
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:638
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1089
Support for dynamic strings.
Definition: strings.h:602
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
Definition: chan_dahdi.h:506
long int ast_random(void)
Definition: main/utils.c:2210

References ast_channel_name(), ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_strlen_zero(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::lock, NULL, dahdi_subchannel::owner, dahdi_pvt::span, and dahdi_pvt::subs.

Referenced by dahdi_cc_callback(), and dahdi_new().

◆ dahdi_ami_channel_event()

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

Definition at line 1803 of file chan_dahdi.c.

1804 {
1805  char ch_name[23];
1806 
1807  if (p->channel < CHAN_PSEUDO) {
1808  /* No B channel */
1809  snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1810  } else if (p->channel == CHAN_PSEUDO) {
1811  /* Pseudo channel */
1812  strcpy(ch_name, "pseudo");
1813  } else {
1814  /* Real channel */
1815  snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1816  }
1817  publish_dahdichannel(chan, p->group, p->span, ch_name);
1818 }
static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages.
Definition: chan_dahdi.c:1776
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:521

References CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::group, publish_dahdichannel(), and dahdi_pvt::span.

Referenced by dahdi_new().

◆ dahdi_answer()

static int dahdi_answer ( struct ast_channel ast)
static
Todo:
XXX this is redundantly set by the analog and PRI submodules!

Definition at line 6377 of file chan_dahdi.c.

6378 {
6379  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6380  int res = 0;
6381  int idx;
6382  ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6383  ast_mutex_lock(&p->lock);
6384  idx = dahdi_get_index(ast, p, 0);
6385  if (idx < 0)
6386  idx = SUB_REAL;
6387  /* nothing to do if a radio channel */
6388  if ((p->radio || (p->oprmode < 0))) {
6389  ast_mutex_unlock(&p->lock);
6390  return 0;
6391  }
6392 
6393  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6394  res = analog_answer(p->sig_pvt, ast);
6395  ast_mutex_unlock(&p->lock);
6396  return res;
6397  }
6398 
6399  switch (p->sig) {
6400 #if defined(HAVE_PRI)
6402  res = sig_pri_answer(p->sig_pvt, ast);
6403  break;
6404 #endif /* defined(HAVE_PRI) */
6405 #if defined(HAVE_SS7)
6406  case SIG_SS7:
6407  res = sig_ss7_answer(p->sig_pvt, ast);
6408  break;
6409 #endif /* defined(HAVE_SS7) */
6410 #ifdef HAVE_OPENR2
6411  case SIG_MFCR2:
6412  if (!p->mfcr2_call_accepted) {
6413  /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6414  openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6415  p->mfcr2_answer_pending = 1;
6416  if (p->mfcr2_charge_calls) {
6417  ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6418  openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6419  } else {
6420  ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6421  openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6422  }
6423  } else {
6424  ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6425  dahdi_r2_answer(p);
6426  }
6427  break;
6428 #endif
6429  case 0:
6430  ast_mutex_unlock(&p->lock);
6431  return 0;
6432  default:
6433  ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6434  res = -1;
6435  break;
6436  }
6437  ast_mutex_unlock(&p->lock);
6438  return res;
6439 }
#define SIG_MFCR2
Definition: chan_dahdi.h:769
int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1459
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)

References analog_answer(), ast_channel_tech_pvt(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_get_index, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::oprmode, 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(), and SUB_REAL.

◆ dahdi_call()

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

Definition at line 5103 of file chan_dahdi.c.

5104 {
5105  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5106  int x, res, mysig;
5107  char *dest;
5109  AST_APP_ARG(group); /* channel/group token */
5110  AST_APP_ARG(ext); /* extension token */
5111  //AST_APP_ARG(opts); /* options token */
5112  AST_APP_ARG(other); /* Any remining unused arguments */
5113  );
5114 
5115  ast_mutex_lock(&p->lock);
5116  ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5117 
5118  /* Split the dialstring */
5119  dest = ast_strdupa(rdest);
5120  AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5121  if (!args.ext) {
5122  args.ext = "";
5123  }
5124 
5125 #if defined(HAVE_PRI)
5126  if (dahdi_sig_pri_lib_handles(p->sig)) {
5127  char *subaddr;
5128 
5129  sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5130 
5131  /* Remove any subaddress for uniformity with incoming calls. */
5132  subaddr = strchr(p->exten, ':');
5133  if (subaddr) {
5134  *subaddr = '\0';
5135  }
5136  } else
5137 #endif /* defined(HAVE_PRI) */
5138  {
5139  ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5140  }
5141 
5142  if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5143  p->subs[SUB_REAL].needbusy = 1;
5144  ast_mutex_unlock(&p->lock);
5145  return 0;
5146  }
5148  ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5149  ast_mutex_unlock(&p->lock);
5150  return -1;
5151  }
5152  p->waitingfordt.tv_sec = 0;
5153  p->dialednone = 0;
5154  if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5155  {
5156  /* Special pseudo -- automatically up */
5157  ast_setstate(ast, AST_STATE_UP);
5158  ast_mutex_unlock(&p->lock);
5159  return 0;
5160  }
5161  x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5162  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5163  if (res)
5164  ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5165  p->outgoing = 1;
5166 
5168  set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5169  } else {
5170  set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5171  }
5172 
5173 #ifdef HAVE_PRI
5174  if (dahdi_sig_pri_lib_handles(p->sig)) {
5175  res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5176  (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5177  ast_mutex_unlock(&p->lock);
5178  return res;
5179  }
5180 #endif
5181 
5182 #if defined(HAVE_SS7)
5183  if (p->sig == SIG_SS7) {
5184  res = sig_ss7_call(p->sig_pvt, ast, rdest);
5185  ast_mutex_unlock(&p->lock);
5186  return res;
5187  }
5188 #endif /* defined(HAVE_SS7) */
5189 
5190  /* If this is analog signalling we can exit here */
5191  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5192  p->callwaitrings = 0;
5193  res = analog_call(p->sig_pvt, ast, rdest, timeout);
5194  ast_mutex_unlock(&p->lock);
5195  return res;
5196  }
5197 
5198  mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5199  switch (mysig) {
5200  case 0:
5201  /* Special pseudo -- automatically up*/
5202  ast_setstate(ast, AST_STATE_UP);
5203  break;
5204  case SIG_MFCR2:
5205  break;
5206  default:
5207  ast_debug(1, "not yet implemented\n");
5208  ast_mutex_unlock(&p->lock);
5209  return -1;
5210  }
5211 
5212 #ifdef HAVE_OPENR2
5213  if (p->mfcr2) {
5214  openr2_calling_party_category_t chancat;
5215  int callres = 0;
5216  char *c, *l;
5217 
5218  /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5219  p->dialdest[0] = '\0';
5220 
5221  c = args.ext;
5222  if (!p->hidecallerid) {
5224  } else {
5225  l = NULL;
5226  }
5227  if (strlen(c) < p->stripmsd) {
5228  ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5229  ast_mutex_unlock(&p->lock);
5230  return -1;
5231  }
5232  p->dialing = 1;
5233  chancat = dahdi_r2_get_channel_category(ast);
5234  callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5235  if (-1 == callres) {
5236  ast_mutex_unlock(&p->lock);
5237  ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5238  return -1;
5239  }
5240  p->mfcr2_call_accepted = 0;
5241  p->mfcr2_progress_sent = 0;
5243  }
5244 #endif /* HAVE_OPENR2 */
5245  ast_mutex_unlock(&p->lock);
5246  return 0;
5247 }
static int dahdi_sig_pri_lib_handles(int signaling)
Definition: chan_dahdi.h:786
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_BUSY
Definition: channelstate.h:43
@ AST_STATE_DIALING
Definition: channelstate.h:39
@ AST_STATE_RESERVED
Definition: channelstate.h:37
const char * ext
Definition: http.c:150
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest, int timeout)
Definition: sig_analog.c:985
void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rdest, int timeout, int layer1)
int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, const char *rdest)
struct ast_party_id id
Connected party ID.
Definition: channel.h:458
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291
char dialdest[256]
Delayed dialing for E911. Overlap digits for ISDN.
Definition: chan_dahdi.h:674
unsigned int outgoing
TRUE if we originated the call leg.
Definition: chan_dahdi.h:306
int outsigmod
Definition: chan_dahdi.h:149
char exten[AST_MAX_EXTENSION]
Extension to use in the dialplan.
Definition: chan_dahdi.h:471
int callwaitrings
Number of call waiting rings.
Definition: chan_dahdi.h:593
unsigned int dialednone
TRUE if analog type line dialed no digits in Dial()
Definition: chan_dahdi.h:245
struct timeval waitingfordt
Definition: chan_dahdi.h:652
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: chan_dahdi.h:584
unsigned int needbusy
Definition: chan_dahdi.h:84
const char * args
#define IS_DIGITAL(cap)
Definition: transcap.h:45

References analog_call(), args, AST_APP_ARG, ast_channel_connected(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_transfercapability(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_log, ast_mutex_lock, ast_mutex_unlock, AST_NONSTANDARD_APP_ARGS, ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, ast_strdupa, c, dahdi_pvt::callwaitrings, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, errno, ext, dahdi_pvt::exten, dahdi_pvt::hidecallerid, ast_party_connected_line::id, IS_DIGITAL, dahdi_pvt::law, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_subchannel::needbusy, NULL, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), dahdi_pvt::sig, SIG_MFCR2, sig_pri_call(), sig_pri_extract_called_num_subaddr(), dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_call(), ast_party_number::str, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_party_number::valid, and dahdi_pvt::waitingfordt.

◆ dahdi_callwait()

static int dahdi_callwait ( struct ast_channel ast)
static

Definition at line 5069 of file chan_dahdi.c.

5070 {
5071  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5072 
5074  if (p->cidspill) {
5075  ast_log(LOG_WARNING, "Spill already exists?!?\n");
5076  ast_free(p->cidspill);
5077  }
5078 
5079  /*
5080  * SAS: Subscriber Alert Signal, 440Hz for 300ms
5081  * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5082  */
5083  if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5084  return -1;
5085  save_conference(p);
5086  /* Silence */
5087  memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5088  if (!p->callwaitrings && p->callwaitingcallerid) {
5089  ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5090  p->callwaitcas = 1;
5091  p->cidlen = 2400 + 680 + READ_SIZE * 4;
5092  } else {
5093  ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5094  p->callwaitcas = 0;
5095  p->cidlen = 2400 + READ_SIZE * 4;
5096  }
5097  p->cidpos = 0;
5098  send_callerid(p);
5099 
5100  return 0;
5101 }
#define ast_free(a)
Definition: astmm.h:180
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
int ast_gen_cas(unsigned char *outbuf, int sas, int len, struct ast_format *codec)
Generate a CAS (CPE Alert Signal) tone for 'n' samples.
Definition: callerid.c:261
#define CALLWAITING_REPEAT_SAMPLES
Definition: chan_dahdi.c:679
static int save_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4958
#define READ_SIZE
Definition: chan_dahdi.c:673
static int send_callerid(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5033
unsigned char * cidspill
Analog caller ID waveform sample buffer.
Definition: chan_dahdi.h:566
int cidlen
Length of the cidspill buffer containing samples.
Definition: chan_dahdi.h:570
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
Definition: chan_dahdi.h:223
int callwaitcas
TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
Definition: chan_dahdi.h:591
int cidpos
Position in the cidspill buffer to send out next.
Definition: chan_dahdi.h:568

References ast_channel_tech_pvt(), 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().

Referenced by dahdi_read().

◆ dahdi_cc_callback()

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
inboundIncoming asterisk channel.
destSame dial string passed to dahdi_request().
callbackCallback 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
0on success.
-1on error.

Definition at line 13701 of file chan_dahdi.c.

13702 {
13703  struct dahdi_pvt *p;
13704  struct dahdi_pvt *exitpvt;
13705  struct dahdi_starting_point start;
13706  int groupmatched = 0;
13707  int channelmatched = 0;
13708 
13710  p = determine_starting_point(dest, &start);
13711  if (!p) {
13713  return -1;
13714  }
13715  exitpvt = p;
13716  for (;;) {
13717  if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13718  /* We found a potential match. call the callback */
13719  struct ast_str *device_name;
13720  char *dash;
13721  const char *monitor_type;
13722  char dialstring[AST_CHANNEL_NAME];
13723  char full_device_name[AST_CHANNEL_NAME];
13724 
13725  switch (ast_get_cc_monitor_policy(p->cc_params)) {
13726  case AST_CC_MONITOR_NEVER:
13727  break;
13728  case AST_CC_MONITOR_NATIVE:
13729  case AST_CC_MONITOR_ALWAYS:
13731 #if defined(HAVE_PRI)
13732  if (dahdi_sig_pri_lib_handles(p->sig)) {
13733  /*
13734  * ISDN is in a trunk busy condition so we need to monitor
13735  * the span congestion device state.
13736  */
13737  snprintf(full_device_name, sizeof(full_device_name),
13738  "DAHDI/I%d/congestion", p->pri->span);
13739  } else
13740 #endif /* defined(HAVE_PRI) */
13741  {
13742 #if defined(HAVE_PRI)
13743  device_name = create_channel_name(p, 1, "");
13744 #else
13745  device_name = create_channel_name(p);
13746 #endif /* defined(HAVE_PRI) */
13747  snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13748  device_name ? ast_str_buffer(device_name) : "");
13749  ast_free(device_name);
13750  /*
13751  * The portion after the '-' in the channel name is either a random
13752  * number, a sequence number, or a subchannel number. None are
13753  * necessary so strip them off.
13754  */
13755  dash = strrchr(full_device_name, '-');
13756  if (dash) {
13757  *dash = '\0';
13758  }
13759  }
13760  snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13761 
13762  /*
13763  * Analog can only do generic monitoring.
13764  * ISDN is in a trunk busy condition and any "device" is going
13765  * to be busy until a B channel becomes available. The generic
13766  * monitor can do this task.
13767  */
13768  monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13769  callback(inbound,
13770 #if defined(HAVE_PRI)
13771  p->pri ? p->pri->cc_params : p->cc_params,
13772 #else
13773  p->cc_params,
13774 #endif /* defined(HAVE_PRI) */
13775  monitor_type, full_device_name, dialstring, NULL);
13776  break;
13777  }
13778  }
13779  p = start.backwards ? p->prev : p->next;
13780  if (!p) {
13781  p = start.backwards ? ifend : iflist;
13782  }
13783  if (p == exitpvt) {
13784  break;
13785  }
13786  }
13788  return 0;
13789 }
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:471
@ AST_CC_MONITOR_NEVER
Definition: ccss.h:76
@ AST_CC_MONITOR_ALWAYS
Definition: ccss.h:87
@ AST_CC_MONITOR_NATIVE
Definition: ccss.h:78
@ AST_CC_MONITOR_GENERIC
Definition: ccss.h:83
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:884
static struct ast_str * create_channel_name(struct dahdi_pvt *i)
Definition: chan_dahdi.c:9067
static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
Definition: chan_dahdi.c:12999
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:802
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13302
#define AST_CHANNEL_NAME
Definition: channel.h:171
struct dahdi_pvt * prev
Definition: chan_dahdi.h:169
struct ast_cc_config_params * cc_params
Definition: chan_dahdi.h:726

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_starting_point::backwards, dahdi_pvt::cc_params, dahdi_starting_point::channelmatch, create_channel_name(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_starting_point::groupmatch, ifend, iflist, iflock, is_group_or_channel_match(), dahdi_pvt::next, NULL, dahdi_pvt::prev, dahdi_pvt::sig, dahdi_starting_point::span, and dahdi_pvt::span.

◆ dahdi_chan_conf_default()

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

870 {
871  /* recall that if a field is not included here it is initialized
872  * to 0 or equivalent
873  */
874  struct dahdi_chan_conf conf = {
875 #ifdef HAVE_PRI
876  .pri.pri = {
877  .nsf = PRI_NSF_NONE,
878  .switchtype = PRI_SWITCH_NI2,
879  .dialplan = PRI_UNKNOWN + 1,
880  .localdialplan = PRI_NATIONAL_ISDN + 1,
881  .nodetype = PRI_CPE,
882  .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
883 
884 #if defined(HAVE_PRI_CCSS)
885  .cc_ptmp_recall_mode = 1,/* specificRecall */
886  .cc_qsig_signaling_link_req = 1,/* retain */
887  .cc_qsig_signaling_link_rsp = 1,/* retain */
888 #endif /* defined(HAVE_PRI_CCSS) */
889 
890  .minunused = 2,
891  .idleext = "",
892  .idledial = "",
893  .internationalprefix = "",
894  .nationalprefix = "",
895  .localprefix = "",
896  .privateprefix = "",
897  .unknownprefix = "",
898  .colp_send = SIG_PRI_COLP_UPDATE,
899  .resetinterval = -1,
900  },
901 #endif
902 #if defined(HAVE_SS7)
903  .ss7.ss7 = {
904  .called_nai = SS7_NAI_NATIONAL,
905  .calling_nai = SS7_NAI_NATIONAL,
906  .internationalprefix = "",
907  .nationalprefix = ""